Replies: 1 comment
-
|
This aligns closely with what we've been building at Tenuo. We opted for capability tokens (Warrants) with mandatory proof-of-possession and offline verification, specifically to address the prompt injection threat model where the agent itself cannot be trusted. Here's what skill registration looks like in our A2A integration: server = A2AServer(
name="Paper Search Agent",
url="https://paper-search.example.com",
public_key=agent_key.public_key,
trusted_issuers=trusted_issuers,
require_warrant=True,
)The constraint is enforced by the runtime, not the LLM. @server.skill("fetch_url", constraints={"url": UrlSafe(allow_domains=["arxiv.org", "scholar.google.com"])})
async def fetch_url(url: str) -> Dict[str, Any]:
# This code NEVER runs if the warrant doesn't authorize the domain
...And attenuation for delegation: search_warrant = root_warrant.attenuate(
signing_key=orchestrator_key,
holder=paper_search_key.public_key,
capabilities={
"fetch_url": {"url": UrlSafe(allow_domains=["arxiv.org"])},
},
ttl_seconds=300,
)A few thoughts on your open questions:
This gives us:
A serialized warrant looks like: Or inspected:
Actually, we encountered so many edge cases building this (key rotation, delegation depth limits, revocation propagation, constraint semantics) that we drafted a formal specification for Agent Capabilities & Warrants. We're looking for partners to help refine it into an open standard so we don't all reinvent the wheel. If you're interested in co-authoring, critiquing the spec, or testing against your use cases, let me know. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
SEP: Capability Negotiation for A2A
Status: Draft
Author: @kurt-r2c
Created: 2025-01-20
Abstract
This SEP proposes capability negotiation for A2A, enabling agents to request and receive minimal authority for specific tasks. Rather than accumulating ambient permissions from all connected agents, a caller requests only the capabilities needed for the task at hand, limiting blast radius from prompt injection or compromise.
Motivation
Current agentic architectures accumulate ambient authority as tools are added to an LLM client:
This violates the principle of least privilege. A task requiring email search should not carry code execution authority.
Specification
Design Principle
Agents MUST request capabilities scoped to the task, not the session.
A capability is an unforgeable token that both designates a resource and authorizes a specific operation. Agents cannot invoke operations for which they hold no capability, regardless of what the downstream agent permits for the associated user principal.
Capability Advertisement
Agents MUST advertise available capability grants in their Agent Card:
{ "name": "acme-documents", "version": "1.0", "capabilityGrants": [ { "id": "documents:read", "description": "Read documents accessible to the user principal", "operations": ["retrieve", "search", "list"], "attenuable": true }, { "id": "documents:write", "description": "Create and modify documents", "operations": ["create", "update", "delete"], "attenuable": true, "requires": ["documents:read"] }, { "id": "documents:admin", "description": "Full access (legacy wrapper)", "operations": ["*"], "attenuable": false, "legacy": true } ] }The
legacy: trueflag indicates a wrapper around non-capability-aware services. These provide protocol compatibility while signaling reduced security guarantees. Callers SHOULD prefer attenuable grants when available.Capability Request Flow
1. Task-Scoped Request
Before invoking skills, agents request capabilities for the specific task. Resource scope is expressed as a query against the user principal's accessible resources, not as direct resource identifiers:
{ "jsonrpc": "2.0", "id": 1, "method": "a2a/capabilities/request", "params": { "grants": ["documents:read"], "purpose": "Summarize quarterly reports", "resourceQuery": { "collection": "reports", "filter": {"quarter": "2025-Q1"} }, "expires": "2025-01-09T13:00:00Z" } }The
purposefield enables audit trails and human approval UX. TheresourceQueryis resolved against the OAuth user principal bound to the session—the caller never sees underlying storage paths or identifiers.2. Capability Issuance
Agent responds with scoped capability tokens and opaque resource handles:
{ "jsonrpc": "2.0", "id": 1, "result": { "capabilities": [ { "id": "cap_7f3a9b", "grant": "documents:read", "token": "<opaque-capability-token>", "resourceHandles": [ {"handle": "rh_001", "displayName": "Q1 Financial Summary"}, {"handle": "rh_002", "displayName": "Q1 Sales Report"} ], "operations": ["retrieve", "search"], "expires": "2025-01-09T13:00:00Z", "revocationId": "rv_abc123", "principal": "user:alice@example.com" } ] } }The issued capability reflects the intersection of what the grant permits, what the caller requested, and what the user principal's access policy allows.
3. Capability-Bound Invocation
Skill invocations MUST include the authorizing capability and reference resources by handle:
{ "jsonrpc": "2.0", "id": 2, "method": "a2a/skill/invoke", "params": { "skill": "retrieve_document", "arguments": {"resourceHandle": "rh_001"}, "capabilityId": "cap_7f3a9b" } }The downstream agent MUST reject if:
Delegation and Attenuation
When delegating to sub-agents, callers attenuate capabilities:
{ "jsonrpc": "2.0", "method": "a2a/capabilities/attenuate", "params": { "capabilityId": "cap_7f3a9b", "constraints": { "resourceHandles": ["rh_001"], "operations": ["retrieve"], "expires": "2025-01-09T12:30:00Z" } } }For agent-to-agent task delegation, the capability context determines what the downstream agent can invoke:
{ "method": "a2a/task/send", "params": { "message": { "role": "user", "parts": [{"type": "text", "text": "Summarize this document"}] }, "capabilities": ["cap_7f3a9b"], "attenuations": { "cap_7f3a9b": { "operations": ["retrieve"], "expires": "2025-01-09T12:35:00Z" } } } }Prompt injection in the message content cannot access skills beyond the attenuated capability set.
Security Considerations
Prompt Injection Mitigation
Compromise of an agent holding
cap_7f3a9bcannot:Token Format
This specification is token-format agnostic. Implementations MAY use:
The
tokenfield is opaque to the protocol. Agents MUST accept their own issued tokens. Agents MUST NOT accept tokens issued by other entities.Migration Path
capabilityGrantsin Agent Card. Callers MAY ignore and use ambient authority, as long as they explicitly advertise this state.capabilityIdin skill invocations. Missing capability falls back to ambient authority.Open Questions
resourceQuerysyntax be its own SEP? It should likely be standardized.Beta Was this translation helpful? Give feedback.
All reactions