Expand description
Serving A2A: this plane, as an agent other agents can call.
The client side (crate::peers::a2a) lets this plane call peers. This is
the other half — a peer calling us — and it is a different problem, because
everything arriving here came from somebody else.
§Why this is not a route on the operator API
Every route on crate::api::Api authenticates and then authorizes. An
Agent Card is public by design: it is what a caller reads before it has
credentials, and a card behind authentication cannot be discovered. Bolting
an unauthenticated path onto a surface whose invariant is “every route
authenticates” would delete that invariant for the one route nobody would
think to check.
So this is its own router with its own rule: the card is public, every method call is authenticated and authorized.
§What arrives here is untrusted
A message from a peer is data written by a party this plane does not control,
so it is admitted as Tainted with the sending
peer’s identity as its provenance source — never as trusted input. A skill
that wants to act on it has to say so at a gate, and a protected sink field
can name the one counterparty it will accept an amount from.
This is the same reason the operator API takes an event’s source from the
authenticated caller rather than the body: a party describing itself is not
evidence about itself.
§The capability is named, never inferred
A2A messages do not carry a “call this skill” field — the protocol assumes an agent works out what is being asked. This plane will not: choosing which capability to run on the strength of an untrusted message is a dispatch decision made by inference, and the thing doing the inferring would be a model reading attacker-controlled text.
The skill is taken from message.metadata.skill, matched against the card’s
advertised skill ids. When the agent advertises exactly one there is nothing
to infer and it is used; when it advertises several and none was named, the
call is refused rather than guessed.
§Optional capabilities say what is wired
Streaming and non-terminal task subscription are durable journal views.
Push is advertised only after with_push supplies durable registration
storage and a retrying transport worker; without that wiring every push
method uses PushNotificationNotSupportedError and the card advertises
false.
§A task belongs to the peer that admitted it
Every read, write, stream, push configuration and contextId join is scoped
to the admitting peer; another peer’s task answers TASK_NOT_FOUND, never a
refusal that confirms it exists.
Re-exports§
pub use crate::push::PushSweepReport;
Modules§
- action
- Actions this surface asks the policy engine about.
- code
- A2A-specific JSON-RPC error codes, from the spec’s mapping table.
- method
- JSON-RPC method names, exactly as A2A 1.0 spells them.
Structs§
- A2aArtifact
- One output produced by an A2A task.
- A2aMessage
- A2A’s
Message. - A2aReply
- How a skill shapes its A2A answer, when the default projection is not it.
- A2aServer
- This plane, served as an A2A agent.
- A2aTask
- A2A’s
Task— what this plane calls a run. - Part
- One piece of a message.
- RpcError
- A JSON-RPC error, carrying the HTTP status it should be served with.
- Task
Status - A2A’s
TaskStatus.
Enums§
- Server
Setup Error - Why a server could not be built.
- Task
State - A task’s lifecycle state, as A2A names them.
Constants§
- ARTIFACTS_
OMITTED_ KEY - The task-metadata key marking artifacts withheld by the replay budget.
Functions§
- policy_
problems - Whether
enginecan evaluate every request this surface puts to it.
Type Aliases§
- A2aPush
Worker - Durable A2A webhook delivery, driven by an operator scheduler.