A2A RFC: actor-chain extension for delegated authority
- Upstream repo: a2aproject/A2A
- Issue: A2A #2028 — actor-chain extension
- Status: Open and by far the most active of our filings — 24 comments, no
maintainer verdict. The thread converged on two properties that must not be
conflated (well-formedness versus proven authority), then on
scopesbeing derived from a validated credential rather than authorization-bearing. Two participants agree on an executable vector set. See Thread state for who is actually in the thread. - Last verified: 2026-08-22
- Authors: Burin Labs
- Reference impl:
harn_vm::actor_chain::ActorChain(crates/harn-vm/src/actor_chain.rs), carried through theharn-serveA2A adapter (crates/harn-serve/src/adapters/a2a/schema.rs) under task and messagemetadata - Anchor threads: A2A #1937 (context-binding profile for delegated authority) and A2A #153 (confused deputy)
Written against A2A v1.0 conventions: a2a.proto is normative, operations are
PascalCase, and enum values are SCREAMING_SNAKE_CASE ProtoJSON strings.
Problem statement#
A2A v1.0 carries no identity in the payload. Authentication is
out-of-band: SecurityScheme declarations on the agent card plus
transport-level mechanisms (HTTP auth, mTLS). The canonical data model
has no field on Message, Task, or the agent card for the human (or
upstream agent) a request is made on behalf of. The only
identity-adjacent field is tenant, which is an opaque routing id, not
a principal. The only escape hatch is the untyped metadata map.
That gap matters as soon as agents delegate to agents:
- Attribution. When agent C receives work from agent B, which received it from agent A acting for user U, C sees only B's transport credentials. The full chain A→B→C-for-U exists nowhere on the wire.
- Audit. Post-hoc "who caused this side effect" reconstruction has to join transport logs across every hop, each with its own identity representation.
- Confused deputy (#153): a callee that can't see the originating principal can be tricked into using its own broader authority on behalf of a less-privileged caller.
The OAuth ecosystem already has the vocabulary for this: RFC 8693 token
exchange expresses delegation as nested act (actor) claims, and the
ID-JAG / WIMSE drafts under active development build agent-specific
delegation on the same shape. A2A can interoperate with that work
without inventing a token format — the missing piece is a standard,
optional place in the A2A payload where a chain travels.
#1937 proposes the complementary half: binding an already-valid delegation to a task/session/target/scope. This proposal is about carrying the chain itself in a standard shape. The two compose: a context-binding profile needs a chain representation to bind.
Proposed shape#
An A2A extension (v1.0 extension mechanism: an AgentExtension
entry in AgentCard.capabilities.extensions[], keyed by URI), rather
than a core schema change. Peers that support it declare:
{
"capabilities": {
"extensions": [
{
"uri": "https://a2a-protocol.org/extensions/actor-chain/v1",
"required": false
}
]
}
}
The extension defines one reserved metadata member, actorChain, valid
on Message.metadata and echoed on Task.metadata:
{
"actorChain": {
"origin": { "sub": "user:alice@example.com" },
"actors": [
{ "sub": "agent:coordinator", "scopes": ["repo:read", "ci:trigger"] },
{ "sub": "agent:rebase-worker", "scopes": ["repo:read"] }
],
"mayAct": "agent:rebase-worker"
}
}
origin— the outermost principal the work is ultimately for (typically a human).actors— the delegation hops in order, mirroring RFC 8693 nestedactclaims flattened for readability; each hop optionally carries the authority scopes that hop held, so attenuation is visible.mayAct— optional RFC 8693may_actanalogue.
Audit, not authz. The chain is attribution and audit history. It MUST NOT be used to grant access: authorization stays with the transport-level credentials and whatever token the callee validated. This mirrors the position the ID-JAG authors have taken and avoids the "self-asserted identity as capability" trap — a payload field anyone can write must never be a credential.
Compatibility and migration#
The extension is additive and optional. Peers that don't declare it ignore the metadata member (A2A metadata is already tolerate-by-default). Peers that do declare it SHOULD echo the chain (with their own hop appended) when they delegate onward.
The reference implementation ships this today under
metadata.actor_chain / metadata.harn.actor_chain with the same
entry shape (sub + scopes), validated on ingest and appended per
hop. Migration to a ratified extension URI and member name is a rename.
Thread state#
The discussion has moved further than the original filing. Four things are settled enough in-thread to treat as the current shape:
- Two properties, never conflated. Well-formedness is checkable from the
payload alone: each hop's
scopesmust be a subset of its predecessor's, and a violation is exactly the confused-deputy shape from #153. Authority is not, becauseactorChainis caller-supplied and a fabricated chain can narrow perfectly at every hop. Proving a grant needs a per-hopproof_refthat an outside verifier resolves without trusting the payload. - Scopes are derived, not authoritative. Per-hop
scopesrender what a validated credential already granted; they never carry authority themselves. A malformed or missing chain therefore degrades attribution, never access. This came from a 2026-08-20 review mapping OAuth token exchange onto the shape, and it is the correction to fold into the extension text. - Missing is not absent. No
proof_refmeans no reconciliation aid was supplied. It must not be read as evidence that no grant occurred. Present but unresolvable, and present but invalidly signed, are further distinct states. - An
originAnchorslot is reserved and inert. Named, unpopulated, and pinned by two negative cases: a populated anchor must verify identically to an unpopulated one, and an anchor can never substitute for scope a predecessor actually held.
Two participants have since checked each other against a shared executable vector set covering those cases, agreeing on the negatives and on one documented limit: a hop that rewrites its predecessor's scopes upward narrows perfectly in the forwarded chain, so that case is only catchable receiver-side.
Read that agreement carefully. No maintainer, member, owner, or collaborator
of a2aproject has replied to this issue — all 24 comments carry
author_association: NONE. The two parties who agree on the vector set wrote 15
of those 24 comments and have been in continuous conversation with each other
since 2026-07, so their agreement is corroboration between two participants, not
independent confirmation. The technical content above stands on its own
reasoning; the thread's volume is not evidence of upstream demand. The
per-participant detail is in the
status ledger.
Open questions for upstream maintainers#
- Extension vs core. Is the v1.0 extension mechanism the intended incubation path for this, or is payload identity in scope for core once #1937 settles?
- Nested vs flattened. RFC 8693 nests
actclaims; the shape above flattens to an ordered array for readability. Should the wire shape stay byte-compatible with RFC 8693 claims instead? - Relationship to signed evidence. A2A v1.0 already does JWS for agent-card signatures. Should hops be signable, or is that deliberately deferred to token-level mechanisms (ID-JAG / WIMSE)?
- Interaction with
tenant. Should the extension state thattenantremains routing-only, to keep it from being repurposed as a principal?