A2A internals¶
This page is for developers who extend or debug the A2A transport. It covers the contract boundaries, routing, the AgentCard, the task lifecycle, and exposure. For setup, see Open standards → A2A.
Terms: a contract is a fixed interface the runtime checks. A plugin implements a contract and is selected by name. A session is one live run. HITL means human in the loop.
Contract boundaries¶
Two contracts split the work.
DelegationContract(mas.runtime.boundary.delegation) owns the LLM-visibledelegate_to_<agent>tool surface.AgentCommContract(mas.runtime.boundary.agentcomm) owns only the low-level send, after delegation is decided.
The runtime registry selects AgentCommContract implementations (category agent_comm):
LocalAgentComm(library-standard): in-process bus.A2AAgentComm(library_ioa.plugins.a2a.agent_comm): officiala2a-sdkclient. The constructor parametersurl,headers, andtimeoutcome from the infra Application endpoint.
The A2A server is a separate ingress adapter. It uses registry category agent_expose (library_ioa.plugins.a2a.exposure.A2AExposure). It is not an AgentCommContract implementation.
It maps each incoming A2A message/send onto the session turn mailbox (mas.ctl.session.mailbox.SessionTurnMailbox). The message is queued at the tail, and the call waits for its own turn. AgentCommContract.send is the outbound peer send after delegation.
Steer, cancel, and input-required¶
A2A has no steer RPC. Extra messages on a non-terminal working task are queued. They do not preempt an in-flight decode.
Control-protocol steer can do three things:
- preempt: keep the prefix, replace the rest.
- replace: discard the prefix, start a new turn.
- wait (
after): queue to the front until the current generation finishes.
A2A tasks/cancel cancels the server-side wait and emits a CANCELED status. It does not call ControlContract.cancel_inflight, so the runtime turn in progress is not interrupted.
input-required is HITL. It is not a mid-token splice.
Registry and routing¶
infra/v1 Application.spec.endpoints holds the public protocol configuration. It is keyed by the exact agency agent id. The runtime registry category stays agent_comm. The endpoint's protocol selects the implementation.
The MAS-wide in-process comm variant resolves from spec.agent_comm (type or protocol, with optional params) through registry.create. If it is omitted, the library default (defaults.agent_comm) applies. The delegation plugin does not choose it, and ctl does not hardcode it.
The route builder resolves every delegates_to target against materialized local agents and against infra endpoints with usage: use or use-and-deploy. Missing targets fail during wiring.
AgentCard¶
An AgentCard is the JSON document that describes an agent to A2A clients. agent_card_from_manifest() (library_ioa.plugins.a2a.agentcard) maps manifest metadata and skills to the official A2A AgentCard:
nameandversion(default0.1.0) come frommetadata.descriptioncomes fromspec.description, thenmetadata.description, then the name.- One
AgentSkillperspec.skillsentry. A single general skill when there are none. providercomes fromspec.provider.organizationdefaults toMAS Lab.- Capabilities come from the endpoint's
a2a.capabilities. Default input and output modes aretext/plain. - Interfaces: JSON-RPC at the advertised URL, HTTP+JSON at
<url>/a2a/rest, and gRPC whena2a.grpc_port(ora2a.grpc_url) is set.
Task lifecycle¶
MAS already has session_id for a complete run and a turn id for each input. A2A reuses them, so no second session model exists.
- A2A
contextIdmaps tosession_id. A new one is generated when absent. messageId(falling back totaskId) becomes the turn id.- Parent and correlation identifiers travel in A2A message metadata:
mas.caller_call_idandmas.correlation_id.
The executor (library_ioa.plugins.a2a.server.executor.MasLabAgentExecutor) supports:
- immediate text responses (a
Message, or a status update on an existing task); - text, data, file, and URL artifacts, and streamed text chunks as artifact updates;
- the
working,completed, andinput_requiredtask states (a turn that stops on a HITL request reportsinput_required); - cancellation events and push notifications (when
a2a.capabilities.pushNotificationsis on).
Tasks and push configurations live in memory (the SDK's InMemoryTaskStore). There is no durable task storage and no multi-replica subscription. The A2A compliance page lists what the TCK (technology compatibility kit) does and does not score.
Exposure topology¶
The infra endpoint entry does two jobs. It declares outbound reachability. It also marks public availability with usage: deploy or use-and-deploy. The legacy expose: true reads as use-and-deploy when usage is absent.
These settings are independent of agency topology on purpose:
- A private local worker may be exposed.
- An external dependency may be consumed without being exposed.
- An agent may have both a local
refand a named infra endpoint, when an overlay deliberately routes it remotely.
mas-ctl serve, chat, tui, and run-mas share one exposure helper (mas.ctl.session.exposure). Listen URLs come from Application endpoints.
- Dedicated
serve: a blocking listener for that agent. It needsusage: deployoruse-and-deploy. It advertises a control endpoint in the control directory unless you pass--no-control. It is the only path that starts the gRPC listener. chatandtui: the in-process agent owns the conversation. A deployed endpoint binds in the background for interrogation. Stdin or curses stays the conversation.run-mas: the entry agent is always in-process. Every hosted agent whose A2A endpoint hasusage: deployoruse-and-deploybinds in this process.usage: usepeers are client routes. Another process, such as a separatemas-ctl serve, owns those ports.
--bind NAME=a2a://… is a shortcut for an Application usage: use row. It expands to --override infra:spec.endpoints[...]=… on the same merged infra document as --infra-ref. It is not a second exposure path. It never opens a listener.
The advertised url cannot include a path prefix. A single port cannot host multiple independent AgentCards. The runtime does not infer either.
Compliance workflow¶
The optional tooling lives under library-ioa/compliance/a2a. See the top-level compliance/README.md.
- The official A2A TCK is a Git checkout, because its top-level runner is not in the published wheel.
- The official
a2aCLI is a Go binary. - MCP uses the official npm conformance framework (
library-ioa/compliance/mcp). - Reports are generated outside runtime tests.
See also¶
- Open standards → A2A
- Kernel operations: the session queue and steer verbs.
- Contracts
- Tutorial 5: A2A agents