A2A v1.0 的 Agent Card:顶层 url 拆成 supportedInterfaces,填错不会报错只会调用失败
信源:A2A (Agent2Agent) Protocol v1.0 规范 ;A2A 官方仓库与发现文档 a2aproject/A2A(agent-discovery.md);AgentCard.net v1.0 schema 参考 。
A2A (Agent2Agent) 是 Google 发起、后捐给 Linux Foundation 的开放协议,让不同框架(LangGraph、CrewAI、Google ADK、Genkit 等)构建的 agent 互相发现能力、协商交互方式、协作完成任务,而不暴露各自内部状态。传输绑定:JSON-RPC 2.0 (HTTP/SSE)、gRPC、HTTP/REST。
Agent Card 是 A2A Server 发布的 JSON 元数据文档,描述身份、能力、技能、服务端点、认证要求。相当于 agent 的数字名片,是发现的唯一来源:No card, no discovery.
发现机制:well-known URI 与注册表
A2A Server 把 Agent Card 托管在 well-known URI,遵循 RFC 8615,标准路径:
https://{agent-server-domain}/.well-known/agent-card.json
客户端 HTTP GET 即可拿到 JSON。旧版 v0.x 用 /.well-known/agent.json(v0.3.0 改名),迁移期建议两个都发布。内容类型 application/a2a+json(application/json 实际也可)。
注册表模式:中心化 registry 维护一批 Agent Card,客户端按 skills/tags 查询。私有发现走配置文件、环境变量或专有 API。
v1.0 字段逐个过
supportedInterfaces(v1.0 新引入)
AgentInterface[],必填。有序列表,第一个是首选。取代了旧的顶层 url、preferredTransport、additionalInterfaces。每项自带:
urlprotocolBinding:JSONRPC/GRPC/HTTP+JSON,或自定义绑定 URIprotocolVersion- 可选
tenant路由键
声明了却不在该 URL 提供该绑定,就是错的。
capabilities
AgentCapabilities,必填。字段:streaming、pushNotifications、extensions、extendedAgentCard。未声明的功能客户端不得调用——未声明 streaming 的调用会返回错误。extendedAgentCard: true 表示认证后可经 GetExtendedAgentCard 拿更详细名片。
v1.0 移除了 stateTransitionHistory。写 streaming: true 但服务端没有流式端点会失败。
skills
AgentSkill[],必填。每项 id / name / description / tags 必填,examples、per-skill modes、per-skill security 可选。skills 是发现匹配单元,router 按它匹配任务,每个技能应聚焦单一任务边界。
v1.0 里 tags 变成必填,用于驱动技能级匹配。
provider / version / documentationUrl / iconUrl
provider(AgentProvider,可选):v1.0 把name改名为organization;存在时url必填。version(string,必填):agent 自身版本(语义化),不是协议版本。协议版本现在放在每个supportedInterfaces项上。documentationUrl(string,可选):指向技术文档,不是营销首页。iconUrl(string,可选):HTTPS 稳定地址。name(string,必填):作者可读名称,短且具体。description(string,必填):做什么、何时该被调用,是给人和 LLM 路由器的主信号,别写少于 20 字符的一句话。
securitySchemes 与 security
securitySchemes 是 map,可选,命名认证方案:
apiKeySecuritySchemehttpAuthSecuritySchemeoauth2SecuritySchemeopenIdConnectSecuritySchememtlsSecurityScheme
凭据永远带外获取,禁止把 API key / token 写进名片。
security 是数组,可选,声明哪些方案及其 scopes 是调用所必需,仿 OpenAPI security requirement。要有意公开的 agent 就两个都省略;只声明 securitySchemes 不声明 security,会让客户端猜是否需要认证。
defaultInputModes / defaultOutputModes
两个都是 string[],必填。输入是所有技能接受的 MIME 类型,例如 text/plain、application/json、image/png;输出是返回的 MIME 类型。技能可用 inputModes 覆盖默认输入。
signatures
AgentCardSignature[],可选。用 JWS 证明名片由提供方签发。对去除 signatures 字段和默认值后的名片做 RFC 8785 (JCS) 规范化再签名。客户端从开放网络取回名片后,应至少校验一个签名(kid/jku 头或可信密钥库)再信任。多签名支持密钥轮换。签名后即使改一个字段,JWS 都会失效。
Get Extended Agent Card 运维
capabilities.extendedAgentCard 为 true 时,同一个 well-known URL 对已认证的 GET 返回更详细名片(含公开名片没有的私有技能)。客户端 SHOULD 用它替换缓存的公开名片,直到会话结束或版本变化。
若声明支持但未配置,返回 ExtendedAgentCardNotConfiguredError;未声明则返回 UnsupportedOperationError。敏感信息建议用认证版扩展名片;端点可加 mTLS、IP 限制、OAuth 2.0;registry 可做选择性披露。规范强烈建议用带外动态凭据,不要在名片里嵌静态密钥。
完整 v1.0 示例(含 OAuth2、streaming、pushNotifications)
{
"name": "Customer Support Agent",
"description": "Answers customer support questions, retrieves order context, and escalates unresolved issues to a human team.",
"supportedInterfaces": [
{
"url": "https://api.example.com/a2a/customer-support",
"protocolBinding": "JSONRPC",
"protocolVersion": "1.0"
}
],
"provider": { "organization": "Example Inc.", "url": "https://example.com" },
"version": "1.0.0",
"capabilities": { "streaming": true, "pushNotifications": true, "extendedAgentCard": false },
"defaultInputModes": ["text/plain", "application/json"],
"defaultOutputModes": ["text/plain", "application/json"],
"skills": [
{
"id": "resolve-customer-support-request",
"name": "Resolve customer support request",
"description": "Classifies a customer support request, gathers needed context, proposes a resolution, and escalates when confidence is low.",
"tags": ["support", "orders", "returns"],
"examples": ["Help me return my order."]
}
],
"securitySchemes": {
"oauth2": {
"oauth2SecurityScheme": {
"flows": {
"clientCredentials": {
"tokenUrl": "https://api.example.com/a2a/customer-support/oauth/token",
"scopes": { "agent.invoke": "Invoke agent skills" }
}
}
}
}
},
"security": [{ "oauth2": ["agent.invoke"] }]
}
TypeScript 类型(v1.0)
export interface AgentCard {
name: string;
description: string;
supportedInterfaces: AgentInterface[];
provider?: AgentProvider;
version: string;
documentationUrl?: string;
capabilities: AgentCapabilities;
securitySchemes?: Record;
security?: Record[];
defaultInputModes: string[];
defaultOutputModes: string[];
skills: AgentSkill[];
signatures?: AgentCardSignature[];
iconUrl?: string;
}
export interface AgentInterface {
url: string;
protocolBinding: 'JSONRPC' | 'GRPC' | 'HTTP+JSON' | (string & {});
protocolVersion: string;
tenant?: string;
}
export interface AgentProvider {
organization: string;
url: string;
}
export interface AgentCapabilities {
streaming?: boolean;
pushNotifications?: boolean;
extensions?: AgentExtension[];
extendedAgentCard?: boolean;
}
export interface AgentSkill {
id: string;
name: string;
description: string;
tags: string[];
examples?: string[];
inputModes?: string[];
outputModes?: string[];
}
export interface AgentCardSignature {
protected: string;
signature: string;
header?: Record;
}
v1.0 的 11 个操作与 8 个 TaskState
A2A v1.0 共十一个操作:Send Message、Send Streaming Message、Get Task、List Tasks、Cancel Task、Subscribe to Task、Create/Get/List/Delete Push Notification Config、Get Extended Agent Card。List Tasks(过滤 + 分页)随 v1.0 加入。
- JSON-RPC 用 PascalCase:
SendMessage、SendStreamingMessage、GetTask、ListTasks、CancelTask、SubscribeToTask、GetExtendedAgentCard。 - HTTP+JSON:
POST /message:send、POST /message:stream、GET /tasks/{id}、GET /tasks、POST /tasks/{id}:cancel、POST /tasks/{id}:subscribe、GET /extendedAgentCard。 - gRPC:
A2AService,protobuf v3 over HTTP/2 + TLS。
旧文档里的 message/send、message/stream 是 v0.3 时代写法,要按 A2A-Version 区分。
八个 TaskState:SUBMITTED / WORKING / COMPLETED / FAILED / CANCELED / REJECTED / INPUT_REQUIRED / AUTH_REQUIRED。终态是 completed / failed / canceled / rejected,对终态任务 Subscribe 返回 UnsupportedOperationError。
v0.x → v1.0 迁移对照
| v0.x | v1.0 |
|---|---|
url | supportedInterfaces[0].url |
preferredTransport | supportedInterfaces[] 顺序(首选 = 数组第一项) |
additionalInterfaces | supportedInterfaces[] |
protocolVersion(顶层) | supportedInterfaces[].protocolVersion |
supportsAuthenticatedExtendedCard | capabilities.extendedAgentCard(RPC 改名 GetExtendedAgentCard) |
provider.name | provider.organization |
capabilities.stateTransitionHistory | 移除(需要就建模成 extension) |
常见部署坑
- well-known 路径返回的是名片本身,而名片里的
url字段指向真正收发 A2A 消息的 JSON-RPC 端点——这是两个不同地址,混淆它们是最常见的部署错误。 - 声明了
streaming: true却没有对应的流式端点,调用直接失败;未声明的能力同样不能调用。 - 把 API key / token 写进公开名片。凭据必须带外获取。
signatures签完之后又改字段,JWS 立刻失效;JCS 规范化是签名输入的一部分,改一个字符都要重签。- v0.x 旧字段残留:顶层
url、preferredTransport、additionalInterfaces、protocolVersion、provider.name、stateTransitionHistory都应按上表清掉,否则客户端行为取决于实现先读哪个字段。
发布前自查清单
- 名片走 HTTPS,放在
/.well-known/agent-card.json。 - 每个
supportedInterfaces可达,且真的提供声明的绑定。 skills有tags与清晰的任务边界描述。- 声明的
capabilities与实际一致:未声明的返回错误,声明的必须可用。 securitySchemes只描述如何认证,绝不含凭据。- 名片内容变化时 bump
version。
安全提示
Agent Card 是自发布的,技能的 description 应视为不可信输入喂给模型,和 MCP tool description 一样要防投毒;委托前优先校验已签名名片。
其他参考资料
- A2A 官方高层面总结:
- AG2 客户端接入文档: —
card_url指向/.well-known/agent-card.json,prefer=jsonrpc/rest/grpc,grpcs://用系统 CA,card_signature_verifier校验 JWS - Rust SDK 类型: