Module a2a_wire
Expand description
Shared A2A v1.0 wire types for both inbound and outbound.
Pure-Serde protocol DTOs for the A2A (Agent2Agent) v1.0 protobuf-JSON
payload, aligned to the official specification and a2a.proto
(package lf.a2a.v1): camelCase field names, SCREAMING_SNAKE_CASE enum
values, and oneof discriminators expressed as the branch field name (no
kind discriminator). Inbound (zeroclaw-gateway/src/a2a.rs) uses these
to construct responses; outbound (zeroclaw-tools/src/a2a_client.rs) uses
them to build requests and deserialize peer responses. Router/server-only
types stay gateway-local.
This follows the established precedent of crate::jsonrpc: a
dependency-light, pure-Serde wire-model source shared across crates
without cross-crate coupling. No a2a-rs/protobuf footprint.
JsonSchema derives are gated behind the schema-export feature (mirrors
zeroclaw-config), so consuming crates can generate OpenAPI/OPTIONS
schemas from these types directly.
Structs§
- Agent
Capabilities - A2A
AgentCapabilities— optional feature flags. OnlySomevalues serialize;Nonefields are omitted. - Agent
Card - A2A
AgentCard(spec §14) — the discovery surface for an agent. Serializes to the protobuf-JSON wire shape. - Agent
Interface - A2A
AgentInterface(spec §5.8) — a declared transport interface. The first entry ofsupportedInterfacesis the preferred transport.tenant, when set, MUST be echoed into thetenantfield of every request sent to this interface (spec §5.2). - Agent
Skill - A2A
AgentSkill(spec §4.4).id/name/descriptionare spec-required. - Artifact
- A2A
Artifact(protomessage Artifact) — a task output.partsis the samePartoneof used by messages. - Json
RpcError - A2A JSON-RPC error object.
- Json
RpcRequest - A2A JSON-RPC 2.0 request envelope (spec §9).
- Json
RpcResponse - A2A JSON-RPC 2.0 response envelope. Peers wrap the result payload
(
Task,SendMessageResponse, …) inresult; errors come back aserrorwith the spec’s negative codes.resultisOption<T>so a present-but-nullresult deserializes toNonewithout forcingT: Default(the response union types are untagged enums with no Default). - Message
- A2A
Message(protomessage Message) — one unit of client/server communication.messageIdandroleare spec-REQUIRED on send, andpartsMUST contain at least onePart(spec §5.7 REQUIRED — a list field with REQUIRED behavior must have ≥1 element). - Part
- A2A
Part(protomessage Part) — a section of communication content. Thecontentoneof is expressed without a discriminator: the active branch is exactly one oftext/raw/url/data; the shared optional fields (metadata/filename/mediaType) ride alongside it. The oneof invariant is enforced at deserialization (viadeserialize_part): a payload with zero content branches or more than one is rejected, matching the protooneofsemantics (spec §5.7 — aPartcarries exactly one content branch). A struct (not an enum) lets serde handle the field-name-keyed shape directly while a custom deserializer validates the oneof invariant. - Send
Message Configuration SendMessageConfiguration(proto) — optional send tuning.- Send
Message Params SendMessagerequestparams(protoSendMessageRequest).tenantechoes the selectedAgentInterface.tenant;messageis REQUIRED.- Task
- A2A
Task(protomessage Task) — returned bySendMessage/GetTask/CancelTask. Fields beyond the spec-requiredid/statusare optional and tolerate absence: a peer that omitscontextIdorartifactsstill parses. - Task
Status - A2A
TaskStatus(protomessage TaskStatus).
Enums§
- Role
- A2A
Role(protoenum Role) — the sender of a message. ProtoJSON serializes enum values as their SCREAMING_SNAKE_CASE proto names (spec §5.5). - Send
Message Response SendMessageResponse(protomessage SendMessageResponse) — theoneof payloadwith branchestask/message. Custom de/serialization enforces exactly-one branch and the flat proto-shape ({"task": {...}}/{"message": {...}}): the default externally-tagged enum serializer would nest the branch value one level too deep ({"task":{"task":{...}}}) and would not round-trip through the custom deserializer.- Task
State - A2A
TaskState(protoenum TaskState) — task lifecycle state. SCREAMING_SNAKE_CASE on the wire (spec §5.5).TASK_STATE_UNSPECIFIEDis rejected at deserialization: the spec marksstateas REQUIRED and the default UNSPECIFIED value must not be accepted as a valid wire value.
Functions§
- escape_
fence_ body - Unwrap a JSON-RPC response into its result, validating the transport
envelope. Fails on: missing/invalid
jsonrpcversion (must be"2.0"), response id mismatch (whenexpected_idisSome), ambiguous envelope (bothresultanderrorpresent), missing payload (neitherresultnorerror), and a present non-successerror. Escape the XML closing-tag trigger (</) in untrusted content before it is placed inside an<a2a-* ...>provenance wrapper, so a peer-controlled value containing a closing marker such as</a2a-artifact>cannot terminate the wrapper early. The wrapper is advisory provenance (the model is already told the interior isuntrusted-external), but an inert<\/keeps marker-looking content from confusing any downstream cursor/splitter. Defined here (the api crate) so both the inboundrpc_resulterror path and the outbound tool renderers share one canonical implementation. - rpc_
result