Skip to content

apomesh-a2a

apomesh-a2a is a transport crate: the inbound Agent2Agent (A2A) v1.0 protocol adapter, beside the gRPC worker wire and the REST/SSE surface. It speaks A2A at its edge and translates-and-delegates onto the substrate’s existing session workflow: an inbound SendMessage against a served agent maps onto the published-agent session-start path, inheriting the strategy plane, supervision, HITL, and tenant isolation unchanged. The adapter carries no orchestration logic of its own, and the substrate stays protocol-blind — every A2A concept lives in this one crate. Touch it for the A2A wire types, the task-state projection, the auth prologue, the card projection, the discovery routes, and the JSON-RPC surface.

  • Layer: transports. See Agent federation for the design, and The dispatch lifecycle for how every transport converges on one session workflow.
  • Depends on: apomesh-protocol (the wire budget blob it decodes), apomesh-substrate-types (the boundary types — TenantContext, AgentRef, the authz Scope, the HITL and lifecycle enums the projection reads), apomesh-substrate, and apomesh-orchestrator (the transport-blind create_session_workflow / respond_to_hitl / cancel_session_workflow the adapter delegates to).
  • Consumed by: apomesh-orchestrator-bin — the daemon binary builds the A2aState, calls build_a2a_router, and merges it onto the shared REST listener. It is the crate’s only consumer; the transport is wired, not depended on by the substrate layers.
  • The A2A domain model (types) — a fully independent wire model: Task / TaskState / Message / Part / Artifact / AgentCard / AgentSkill, with the member-presence Part codec and the ProtoJSON TASK_STATE_* strings. No substrate or prost type carries an A2A serde derive.
  • The task-state projection (mapping) — the pure, exhaustive, canary-guarded table folding a session’s LifecyclePhase / ExitCondition / terminal output and live HITL pause into an A2A TaskState. Wildcard-free over every substrate enum.
  • The auth prologue (auth) — the third trust-boundary prologue over the shared SessionAuth: the Bearer / API-key extractor, the fail-closed route→scope gate, and the AuthenticatedCaller it installs.
  • The card projection (card) — an AgentCard projected from a published agent (curated skills only), each card addressed at its own per-shape endpoint.
  • The discovery routes (routes) — the public well-known card and the authenticated own-tenant catalog.
  • The JSON-RPC surface (rpc) and its substrate delegation (task) — method dispatch plus the SessionBackend port that fronts the orchestrator.
  • build_a2a_router(state, session_auth) — the composition seam: returns the axum::Router (public well-known + auth-gated /a2a/*) that orchestrator-bin merges onto the REST listener.
  • A2aState — the router state: the registry, the serving-agent designation, the card projection context, and the SessionBackend.
  • SessionBackend / DaemonSessionBackend — the narrow async delegation port and its production adapter over the orchestrator daemon (start / read / completed-status / on-stall-pause / respond / cancel).
  • The route path constants — WELL_KNOWN_CARD_PATH (/.well-known/agent-card.json), CATALOG_PATH (/a2a/catalog), and RPC_ENDPOINT_PATH (/a2a/agents/{namespace}/{slug}/{version}).

The served JSON-RPC methods are SendMessage, GetTask, CancelTask (plus the on-stall HITL continuation), the streaming methods SendStreamingMessage / SubscribeToTask (SSE), and ListTasks. GetExtendedAgentCard and the push-notification-config methods are served but return the spec’s unsupported-operation / push-not-supported errors (-32004 / -32003).

orchestrator-bin mounts the adapter onto the shared listener (no new listener):

let state = A2aState::new(
agent_registry,
config.a2a.serving_tenant,
config.a2a.serving_agent,
config.a2a.serving_agent_version,
card_context, // endpoint base URL, honored security schemes, streaming flag
);
let rest_router = rest_router.merge(build_a2a_router(state, session_auth));

A peer then GETs /.well-known/agent-card.json, reads the card’s url, and POSTs A2A JSON-RPC there — see Build → Agent2Agent (A2A) for the request shapes.