A2A
How permdock/a2a emits Agent Card security schemes and requirements per skill and filters the authenticated extended card by the caller's permissions.
What it is
The Agent2Agent (A2A) protocol 1.0 is a Linux Foundation project for agent-to-agent communication, backed by more than 150 organisations. An agent publishes an Agent Card describing its identity, endpoints and skills. The parts relevant to authorization:
securitySchemesandsecurityRequirementson the card, using the OpenAPI-style vocabulary, declare how a caller must authenticate and which scopes it needs.- Signed cards let a caller verify that a card was published by the agent it claims to describe.
- The authenticated extended card is a second card, fetched with credentials, that can expose caller-specific skills: the same agent shows different capabilities to different callers.
Why it matters for PermDock
An A2A agent built on PermDock has two authorization jobs. Outbound, its card must state which scopes each skill requires, and that information already exists as permission.scope. Inbound, when another agent calls a skill, the request carries a principal (the user the calling agent works for), an actor (the calling agent) and delegated authority, which is exactly the two-principal subject. Per-skill permission requirements and permission-filtered extended cards are the A2A twin of MCP list_tools filtering. See the a2a adapter.
How PermDock uses it
import { createPermDock } from "permdock/a2a";
const { agentCard, extendedAgentCard, protectSkill } = createPermDock(policy, {
subject: (auth) => userFrom(auth), // principal from the caller's token
skills: {
summarise: { permission: permissions.post.read },
publish: {
permission: permissions.post.publish,
data: (params) => loadPost(params.postId),
},
},
});
// Public card: securitySchemes + securityRequirements per skill, derived from permission.scope
app.get("/.well-known/agent-card.json", (c) => c.json(agentCard()));
// Extended card: only the skills this caller may invoke
app.get("/agent/authenticatedExtendedCard", (c) =>
c.json(extendedAgentCard(c.get("auth"))),
);What the adapter does:
- Emits
securitySchemesfrom the adapter's OAuth configuration (the same shape used by the OpenAPI emitter), and asecurityRequirementsentry per skill listing the skill'spermission.scope. - Filters the extended card.
extendedAgentCard(auth)builds a request-scopedPermDockfrom the caller's credentials and includes only skills whose permission the subject holds (canon collection actions; instance actions are included when a representative check or an explicitadvertiserule passes). - Guards skill execution.
protectSkillwraps a skill handler: it validates parameters against the resource schema at the boundary, loads the instance withdata, callsdecide, and returns a structured refusal with reasons andalternativesondenied, or an approval request onapproval-required. - Fills
actoranddelegationfrom the calling agent's identity and token scopes, so the calling agent cannot exceed the user it acts for. - Signed cards use the host's key:
sign(card, signPayload)hands the signer the RFC 8785 canonical card and stores the detached JWS insignatures, because PermDock does not manage keys.
The public card lists every skill with its scopes: a scope names what a token must carry, not what any user holds, so it discloses nothing the OAuth metadata does not. The extended card is the per-caller view.
Request lifecycle
- A calling agent fetches the public card and reads the
securityRequirementsfor the skill it wants (post:publish). - It obtains a token with that scope for the user it acts for, typically through the OAuth flows described in OAuth for agent delegation.
- It fetches the authenticated extended card.
extendedAgentCard(auth)builds a request-scopedPermDockand lists only the skills the subject may invoke, so the caller learns up front whetherpublishis available to this user. - It invokes the skill.
protectSkillvalidates parameters at the boundary, loads the instance, and callsdecidewithprincipalfrom the token,actorfrom the caller's identity anddelegationfrom the token scopes. grantedruns the handler;deniedreturns the reasons andalternatives;approval-requiredputs the task in the A2Ainput-requiredstate and returns the approvaltokenin the Problem Details body (see approvals).- The decision is emitted through
on('decision')with the calling agent asactor, so cross-agent calls are attributable.
Relationship to the other agent adapters
The A2A adapter reuses the MCP adapter's translation of a Decision into a structured refusal and the OpenAPI emitter's security-scheme configuration. An agent that exposes both an MCP server and an A2A card from the same policy advertises the same scopes in both, and the extended card and list_tools agree on what a caller may do.
Mapping table
| A2A 1.0 concept | PermDock concept |
|---|---|
Agent Card securitySchemes | Adapter OAuth configuration, shared with the OpenAPI emitter |
Agent Card securityRequirements (per skill) | permission.scope of the skill's permission |
| Skill | Entry in skills: { name: { permission, data? } } |
| Authenticated extended card | extendedAgentCard(auth) filtered by can per skill |
| Public card | agentCard() listing all skills with their requirements |
| Signed card | sign(card, signPayload): the host's signer returns a compact JWS over the RFC 8785 card; the adapter appends the detached { protected, signature } to signatures |
| Calling agent identity | actor |
Caller's token scopes / authorization_details | delegation |
| User the calling agent acts for | principal via subject(auth) |
| Skill invocation | protectSkill: boundary validation, decide, structured refusal |
| Refusal payload | Decision reasons and alternatives |
Sources
- A2A protocol specification.
- Linux Foundation announcement: A2A surpasses 150 organisations.
- Product plan,
permdock/a2aAPI sketch.
Last updated on
WebMCP
How permdock/webmcp registers browser-exposed tools through document.modelContext only when the client snapshot allows them, and how WebMCP hints and Permissions-Policy fit in.
Web Bot Auth
How Web Bot Auth (RFC 9421 HTTP Message Signatures with Signature-Agent discovery) gives PermDock's HTTP adapters a verified agent identity to fill the actor half of the subject.