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)