Skip to main content

bus API

Table of Contents

Top

upsquad/bus/v1/envelope.proto

Endpoint

Endpoint addresses a routing participant on the bus. The bus maps an Endpoint to exactly one tenant-scoped queue; it is never resolved across tenants.

FieldTypeLabelDescription
kindEndpointKindkind is the participant class (team, role, coordinator).
idstringid identifies the participant within its kind: a team id for TEAM, a role name for ROLE. It is empty for COORDINATOR (there is one Coordinator queue per tenant).

Envelope

Envelope is the single A2A message contract carried on the bus. Every field is intra-tenant; the bus refuses to enqueue an Envelope with an empty tenant_id.

FieldTypeLabelDescription
idstringid is a globally-unique message id (UUIDv4). The bus generates one if the producer leaves it empty. It is distinct from the transport-level stream entry id and survives retries/re-enqueues unchanged.
schema_versionEnvelopeSchemaVersionschema_version pins the envelope contract. Consumers reject versions they do not understand. Must be a known, non-unspecified value.
tenant_idstringtenant_id scopes the envelope to a single tenant. REQUIRED. The bus keys every queue by this value; cross-tenant delivery is impossible.
task_idstringtask_id links the envelope to the Task — the unit of work AND the unit of accounting (ADR-0015). The Coordinator accrues cost/effort per hop onto this Task.
conversation_idstringconversation_id groups all envelopes belonging to one logical exchange (e.g. a WorkflowRun). Stable across the query/reply round-trips within a Task.
continuation_tokenstringcontinuation_token is the resume token for suspend/resume. A worker emitting a QUERY stamps the token it will be resumed with; the Coordinator echoes it on the matching REPLY so the suspended work-item is rehydrated and re-dispatched. Empty for fire-and-forget WORK.
fromEndpointfrom is the participant that emitted the envelope.
toEndpointto is the participant the envelope is delivered to. The bus derives the queue key from (tenant_id, to.kind, to.id).
kindMessageKindkind is the semantic class of the payload (work/result/query/reply/ control). Must be a known, non-unspecified value.
payloadbytespayload is the opaque application body (typically JSON or a serialized domain proto). The bus does not interpret it. content_type describes it.
content_typestringcontent_type is the IANA media type of payload (e.g. "application/json"). Advisory; the bus does not enforce it.
created_atgoogle.protobuf.Timestampcreated_at is when the producer minted the envelope. The bus stamps it if left zero. Preserved across retries.
attemptuint32attempt is the 1-based delivery attempt counter. EnqueueWork defaults it to 1; the bus increments it on every retry / crash-reclaim. When it exceeds the configured max, the envelope is routed to the DLQ.
idempotency_keystringidempotency_key deduplicates redelivery and duplicate publishes. The bus records this key in its dedupe store on successful completion; any later delivery carrying an already-completed key is acked and dropped without re-invoking the handler. Empty disables consumer-side dedupe for the message.
headersEnvelope.HeadersEntryrepeatedheaders carries optional out-of-band metadata (trace ids, the DLQ failure reason, etc.). Not interpreted for routing.

Envelope.HeadersEntry

FieldTypeLabelDescription
keystring
valuestring

EndpointKind

EndpointKind classifies a routing participant. The bus derives a queue (Redis Stream) key from (tenant_id, EndpointKind, id), so the kind + id together address where a message is delivered.

NameNumberDescription
ENDPOINT_KIND_UNSPECIFIED0ENDPOINT_KIND_UNSPECIFIED is the zero value reserved by protobuf.
ENDPOINT_KIND_TEAM1ENDPOINT_KIND_TEAM addresses a team work-queue; id is the team id. All workers serving that team compete for messages on one queue.
ENDPOINT_KIND_ROLE2ENDPOINT_KIND_ROLE addresses a capability/role work-queue (e.g. "coding", "architect"); id is the role name. All workers of that role compete for messages on one queue.
ENDPOINT_KIND_COORDINATOR3ENDPOINT_KIND_COORDINATOR addresses the deterministic Coordinator's control queue; id is empty. Results, replies, and control messages destined for the Coordinator route here.
ENDPOINT_KIND_FOREIGN4ENDPOINT_KIND_FOREIGN addresses a foreign A2A agent reachable over the Google A2A wire protocol (HLD docs/hld/HLD-a2a-egress-foreign-agents.md §6.1). id is the per-tenant foreign_agent_registry key (NEVER a raw URL — the base URL + credential resolve from the registry, so a workflow definition never embeds an external endpoint or secret). A FOREIGN destination is NOT a Redis work-queue: the deterministic Coordinator, after running its unchanged per-hop choke-point (Governor.Check → audit → cost), hands the hop to the ForeignDispatcher port (the A2A egress adapter, T5.4) instead of EnqueueWork. Workers can never forward to a FOREIGN endpoint — only the Coordinator routes the external edge, so the governed-every-hop invariant holds at the perimeter (HLD §8).

EnvelopeSchemaVersion

EnvelopeSchemaVersion is the current envelope schema version. Producers stamp Envelope.schema_version with this value; consumers reject envelopes whose schema_version they do not understand. Bumping this is a versioned, buf-breaking-checked change.

NameNumberDescription
ENVELOPE_SCHEMA_VERSION_UNSPECIFIED0ENVELOPE_SCHEMA_VERSION_UNSPECIFIED is the zero value reserved by protobuf. An envelope carrying the unspecified version is rejected by the bus as malformed.
ENVELOPE_SCHEMA_VERSION_V11ENVELOPE_SCHEMA_VERSION_V1 is the initial envelope contract (this file).

MessageKind

MessageKind is the semantic class of an envelope payload. It drives how the Coordinator and harness interpret the message; it does NOT affect routing (that is determined by to).

NameNumberDescription
MESSAGE_KIND_UNSPECIFIED0MESSAGE_KIND_UNSPECIFIED is the zero value reserved by protobuf and is rejected by the bus as malformed.
MESSAGE_KIND_WORK1MESSAGE_KIND_WORK is a unit of work dispatched to a team/role for an agent to execute (the Coordinator's "next hop").
MESSAGE_KIND_RESULT2MESSAGE_KIND_RESULT is the completed output of a work item, returned to the Coordinator for governance, audit, cost accrual, and next-hop routing.
MESSAGE_KIND_QUERY3MESSAGE_KIND_QUERY is a sub-query emitted by a worker that needs input from another role/team. The emitting agent checkpoints and stands down; it carries a continuation_token so the Coordinator can resume it on the matching reply.
MESSAGE_KIND_REPLY4MESSAGE_KIND_REPLY answers a prior QUERY. The Coordinator matches it to the suspended work-item via continuation_token and re-dispatches.
MESSAGE_KIND_CONTROL5MESSAGE_KIND_CONTROL is an out-of-band control signal (e.g. cancel, pause, coordinator liveness) that is not itself a unit of accounted work.

Scalar Value Types

.proto TypeNotesC++JavaPythonGoC#PHPRuby
doubledoubledoublefloatfloat64doublefloatFloat
floatfloatfloatfloatfloat32floatfloatFloat
int32Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint32 instead.int32intintint32intintegerBignum or Fixnum (as required)
int64Uses variable-length encoding. Inefficient for encoding negative numbers – if your field is likely to have negative values, use sint64 instead.int64longint/longint64longinteger/stringBignum
uint32Uses variable-length encoding.uint32intint/longuint32uintintegerBignum or Fixnum (as required)
uint64Uses variable-length encoding.uint64longint/longuint64ulonginteger/stringBignum or Fixnum (as required)
sint32Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int32s.int32intintint32intintegerBignum or Fixnum (as required)
sint64Uses variable-length encoding. Signed int value. These more efficiently encode negative numbers than regular int64s.int64longint/longint64longinteger/stringBignum
fixed32Always four bytes. More efficient than uint32 if values are often greater than 2^28.uint32intintuint32uintintegerBignum or Fixnum (as required)
fixed64Always eight bytes. More efficient than uint64 if values are often greater than 2^56.uint64longint/longuint64ulonginteger/stringBignum
sfixed32Always four bytes.int32intintint32intintegerBignum or Fixnum (as required)
sfixed64Always eight bytes.int64longint/longint64longinteger/stringBignum
boolboolbooleanbooleanboolboolbooleanTrueClass/FalseClass
stringA string must always contain UTF-8 encoded or 7-bit ASCII text.stringStringstr/unicodestringstringstringString (UTF-8)
bytesMay contain any arbitrary sequence of bytes.stringByteStringstr[]byteByteStringstringString (ASCII-8BIT)