A2A 中的 Agent Card:完整 JSON 示例与字段解析
Agent Card 是一份 JSON 文档,告诉客户端代理应调用谁、任务发到哪里、有哪些可用技能。在 A2A(Agent2Agent)协议中,卡片通常发布在 /.well-known/agent-card.json:没有它难以发现;描述含糊则难以正确路由。
- Agent Card - 代理能力的公开契约
- Discovery - 通过 well-known URL 或 registry 发现卡片
- skills - 具体能力,而不是笼统的「什么都会」
- capabilities - streaming、push、扩展卡片
- security - OpenAPI 风格的认证方案
为什么需要 Agent Card
A2A 连接独立代理:一方是客户端,另一方是执行者。发送任务前,客户端会读取卡片并回答:
- 这个代理是否匹配用户意图?
- 哪个 endpoint 接收任务?
- 输入和输出支持哪些 MIME 类型?
- 是否需要认证,以及何种方式?
- 是否支持事件流与 webhook 通知?
卡片不是营销文案。编排器与 LLM 路由器会解析它。description、skills、examples 越具体,执行者选择就越稳定。
完整 JSON 示例
下面是一个可运行示例:代理可在网站中搜索商品、计算价格,并在用户确认后创建线索。字段采用 camelCase,与常见 A2A JSON 卡片一致。
{
"name": "Site Commerce Agent",
"description": "搜索网站目录、计算价格与交期,并在用户确认后创建线索。处理目录、草稿购物车与订单状态。不处理支付,也不改价。",
"version": "1.2.0",
"protocolVersion": "0.3.0",
"url": "https://api.example.com/a2a",
"documentationUrl": "https://docs.example.com/a2a/commerce-agent",
"iconUrl": "https://example.com/icons/commerce-agent.svg",
"provider": {
"organization": "Example Shop",
"url": "https://example.com"
},
"capabilities": {
"streaming": true,
"pushNotifications": true,
"stateTransitionHistory": true,
"extendedAgentCard": false
},
"defaultInputModes": [
"text/plain",
"application/json"
],
"defaultOutputModes": [
"text/plain",
"application/json"
],
"skills": [
{
"id": "search-products",
"name": "商品搜索",
"description": "按查询、品类、价格与库存搜索商品。返回带 id、名称、价格与简短描述的候选列表。",
"tags": ["catalog", "search", "products"],
"examples": [
"找本周可配送、800 欧元以下的笔记本电脑",
"显示适合 20 人团队的可用套餐"
],
"inputModes": ["text/plain", "application/json"],
"outputModes": ["application/json", "text/plain"]
},
{
"id": "calculate-quote",
"name": "报价计算",
"description": "为所选条目与数量计算价格、税费、运费与交期。不创建订单。",
"tags": ["pricing", "quote", "shipping"],
"examples": [
"计算 product_id=sku-1042 共 3 件、配送到柏林的费用",
"比较 50 用户的 Basic 与 Pro 套餐"
],
"inputModes": ["application/json", "text/plain"],
"outputModes": ["application/json"]
},
{
"id": "create-lead",
"name": "创建线索",
"description": "在用户明确确认后创建线索或申请草稿。需要联系方式与数据处理同意。",
"tags": ["lead", "order-draft", "crm"],
"examples": [
"为 ACME 创建 Pro 套餐申请,联系人:ops@acme.example",
"根据 quote_id=q-7781 生成订单草稿"
],
"inputModes": ["application/json"],
"outputModes": ["application/json", "text/plain"]
},
{
"id": "get-order-status",
"name": "订单状态",
"description": "按已认证用户的 order_id 或公开运单号返回支付与配送状态。",
"tags": ["orders", "status", "tracking"],
"examples": [
"订单 ORD-20441 的状态是什么?",
"运单号 TRK-998877 的包裹在哪里?"
]
}
],
"securitySchemes": {
"bearer": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
},
"oauth2": {
"type": "oauth2",
"flows": {
"clientCredentials": {
"tokenUrl": "https://auth.example.com/oauth/token",
"scopes": {
"catalog:read": "读取目录与报价",
"leads:write": "创建线索",
"orders:read": "读取订单状态"
}
}
}
}
},
"security": [
{
"oauth2": ["catalog:read"]
},
{
"bearer": []
}
]
}
在 A2A v1.0 中,endpoint 常用 supportedInterfaces 数组描述,而不是单一顶层 url。含义相同:告诉客户端任务发往何处、使用何种 binding(JSONRPC、HTTP+JSON、GRPC 等)。
v1.0 片段示例:
{
"supportedInterfaces": [
{
"url": "https://api.example.com/a2a",
"protocolBinding": "JSONRPC",
"protocolVersion": "1.0"
}
]
}
顶层字段解析
| 字段 | 是否必填 | 作用 |
|---|---|---|
name |
是 | 可读的代理名称 |
description |
是 | 具体摘要:做什么、不做什么 |
version |
是 | 实现版本(建议 semver) |
url / supportedInterfaces |
是* | 任务 endpoint,不是卡片 URL |
skills |
是 | 至少一个 skill |
capabilities |
建议 | 诚实的能力标志 |
defaultInputModes / defaultOutputModes |
建议 | 默认 MIME |
provider |
否 | 所属组织 |
documentationUrl / iconUrl |
否 | 文档与 UI 图标 |
protocolVersion |
取决于 schema | 协议版本(v0.3 常在顶层) |
securitySchemes / security |
否 | 客户端如何认证 |
* 在 v0.3 schema 中通常要求 url。在 v1.0 中由 supportedInterfaces 承担 endpoint 角色。
name 与 description
name 给人与日志看。description 给路由器读。差:「有用的网站代理」。好:列出操作、边界与结果形态。
version
这是代理实现版本,不一定是协议版本。skills 或响应契约发生破坏性变更时提升 major。客户端可能缓存卡片,并在版本变化时重新拉取。
url - 常见错误
url 是 message/send / 任务的发送地址。它 不是 /.well-known/agent-card.json 的路径。
错误:
"url": "https://example.com/.well-known/agent-card.json"
正确:
"url": "https://api.example.com/a2a"
capabilities
| 标志 | 含义 |
|---|---|
streaming |
支持流式响应(SSE / stream) |
pushNotifications |
长任务的 webhook 通知 |
stateTransitionHistory |
任务状态变迁历史 |
extendedAgentCard |
认证后可获取扩展/私有卡片 |
仅在真实实现时设为 true。对不支持 streaming 的代理开启 stream 会得到错误。
defaultInputModes 与 defaultOutputModes
整个代理的默认 MIME。skill 可覆盖。常见值:text/plain、application/json、application/pdf、image/png。
skills 解析
skill 是路由单元。一个 skill = 一项清晰能力。
| 字段 | 是否必填 | 说明 |
|---|---|---|
id |
是 | 在代理内唯一,kebab-case 便于管理 |
name |
是 | UI 短名称 |
description |
是 | 接受什么、返回什么、有何限制 |
tags |
否 | 搜索与过滤关键词 |
examples |
否但强烈建议 | 给编排器用的 2-3 个真实提示 |
inputModes / outputModes |
否 | 该 skill 的 MIME 覆盖 |
examples 不是装饰。没有它们,编排器只能根据描述猜测输入,更容易出错。
差的 skill:
{
"id": "website",
"name": "Website",
"description": "处理网站相关事务"
}
好的 skill 应如完整示例:具体 id、明确边界、tags 与 examples。
认证:securitySchemes 与 security
方案通常遵循 OpenAPI 方式:
apiKeyhttp(Basic / Bearer)oauth2openIdConnectmutualTLS
securitySchemes 描述可用方法。security 设定默认要求:
security数组中多个对象 = 备选(OR);- 同一对象中多个键 = 全部需要(AND)。
公开的是认证 方式,不是密钥。不要把 API key、refresh token 或内部主机名放进 JSON。
Discovery:如何发现卡片
典型流程:
- 客户端知道代理的基础域名。
- 请求
https://agent.example.com/.well-known/agent-card.json。 - 校验必填字段。
- 按描述、tags、examples 选择 skill。
- 按
security完成认证。 - 将任务发到
url/supportedInterfaces。
卡片也可发布在 registry 或代理目录中。此时 discovery 走搜索,well-known 仍是所有者的权威来源。
本地检查:
curl -s https://api.example.com/.well-known/agent-card.json
Agent Card 中不要发布的内容
- API key、密码、私钥;
- 未受保护的内部管理或 staging URL;
- 外部客户端不可用的操作;
- 夸大的 capabilities(未实现却写
streaming: true); - 「能做网站上的一切」这类含糊 skills。
公开卡片既是攻击面,也是路由面。保持精确且最小够用。
常见错误
- 把
url与卡片 URL 搞混。 - 空的
skills数组。 代理几乎无法被路由。 - 没有边界的描述。 未说明不做什么(支付、删除、改价)。
- 缺少
examples。 编排器更难理解合法输入。 - 生产卡片写 localhost。 客户端无法访问。
- 整个产品只有一个 skill。 更好拆成多个权限与 MIME 不同的窄 skills。
发布前小清单
- 通过 HTTPS 提供,且
Content-Type: application/json。 - 有
name、description、version、endpoint 与至少一个 skill。 - 描述具体。
- 关键 skills 带有
examples与tags。 capabilities与真实服务器一致。- JSON 中无密钥。
- 卡片中的 endpoint 能响应测试任务。
- 破坏性变更时升级版本。
总结
Agent Card 是 A2A 的主要 discovery 契约。带有精确 skills、诚实 capabilities 与明确 security 的完整 JSON,能让客户端代理找到正确执行者,并避免误调用。
若需要协助设计 Agent Card、A2A 服务器,或将代理接入网站 API - 请联系我。
常见问题
Agent Card 应该放在哪里?
标准公开路径是代理域名上的 /.well-known/agent-card.json。 也可注册到目录或 registry,但 well-known URL 仍是无需单独索引的便捷 discovery 入口。
url 与卡片地址有何不同?
卡片地址用于 discovery;url(或 supportedInterfaces)用于执行任务。 客户端先读取 JSON,再向代理的工作 endpoint 发送消息/任务。
一张卡片应该有多少 skills?
有多少真正不同、输入或权限不同的能力,就写多少。 通常 3-7 个窄 skills 优于一个笼统的「什么都做」。路由需要清晰边界、tags 与 examples。
Agent Card 必须声明认证吗?
不总是。 公开只读代理可以省略 security。涉及写入、个人数据与付费操作时,声明 securitySchemes 与 security,并把密钥放在卡片之外。
每次部署都要更新卡片吗?
当 skills、endpoint、capabilities、auth 或代理含义变化时更新。 无契约变更的技术补丁可反映在 version;破坏性变更应提升 major 并配套明确文档。