Skip to main content

Module a2a

Module a2a 

Source
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.
TaskStatus
A2A’s TaskStatus.

Enums§

ServerSetupError
Why a server could not be built.
TaskState
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 engine can evaluate every request this surface puts to it.

Type Aliases§

A2aPushWorker
Durable A2A webhook delivery, driven by an operator scheduler.