Rufat Nuriyev 已更新

A2A 中的 Agent Card:完整 JSON 示例与字段解析

在笔记本电脑屏幕上解析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发现与路由图解

为什么需要 Agent Card

A2A 连接独立代理:一方是客户端,另一方是执行者。发送任务前,客户端会读取卡片并回答:

  1. 这个代理是否匹配用户意图?
  2. 哪个 endpoint 接收任务?
  3. 输入和输出支持哪些 MIME 类型?
  4. 是否需要认证,以及何种方式?
  5. 是否支持事件流与 webhook 通知?

卡片不是营销文案。编排器LLM 路由器会解析它。descriptionskillsexamples 越具体,执行者选择就越稳定。

这对企业主意味着什么

Agent Card 是技术细节,但会带来业务后果。如果缺失或写得含糊,合作方系统和 AI 编排器根本无法在众多选项中发现你的服务——就像一个没有正确 SEO 标记的网站。如果卡片开放得太多(例如 capabilitiessecurity 与实际限制不符),就会带来风险:外部代理可能尝试调用本不该对外开放的操作。

你不必自己写 JSON,但值得向开发团队确认:哪些 skill 和数据对外部代理可见、需要哪种认证方式,以及发布前是否核对过下面的清单。

完整 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(JSONRPCHTTP+JSONGRPC 等)。

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 角色。

namedescription

name 给人与日志看。description 给路由器读。差:「有用的网站代理」。好:列出操作、边界与结果形态。

version

这是代理实现版本,不一定是协议版本。skills 或响应契约发生破坏性变更时提升 major。客户端可能缓存卡片,并在版本变化时重新拉取。

url - 常见错误

urlmessage/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 会得到错误。

defaultInputModesdefaultOutputModes

整个代理的默认 MIME。skill 可覆盖。常见值:text/plainapplication/jsonapplication/pdfimage/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。

认证:securitySchemessecurity

方案通常遵循 OpenAPI 方式:

  • apiKey
  • http(Basic / Bearer)
  • oauth2
  • openIdConnect
  • mutualTLS

securitySchemes 描述可用方法。security 设定默认要求:

  • security 数组中多个对象 = 备选(OR);
  • 同一对象中多个键 = 全部需要(AND)。

公开的是认证 方式,不是密钥。不要把 API key、refresh token 或内部主机名放进 JSON。

Discovery:如何发现卡片

典型流程:

  1. 客户端知道代理的基础域名。
  2. 请求 https://agent.example.com/.well-known/agent-card.json
  3. 校验必填字段。
  4. 按描述、tags、examples 选择 skill。
  5. security 完成认证。
  6. 将任务发到 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。

公开卡片既是攻击面,也是路由面。保持精确且最小够用。

常见错误

  1. url 与卡片 URL 搞混。
  2. 空的 skills 数组。 代理几乎无法被路由。
  3. 没有边界的描述。 未说明不做什么(支付、删除、改价)。
  4. 缺少 examples 编排器更难理解合法输入。
  5. 生产卡片写 localhost。 客户端无法访问。
  6. 整个产品只有一个 skill。 更好拆成多个权限与 MIME 不同的窄 skills。

发布前小清单

  1. 通过 HTTPS 提供,且 Content-Type: application/json
  2. namedescriptionversionendpoint 与至少一个 skill。
  3. 描述具体。
  4. 关键 skills 带有 examplestags
  5. capabilities 与真实服务器一致。
  6. JSON 中无密钥。
  7. 卡片中的 endpoint 能响应测试任务。
  8. 破坏性变更时升级版本。

什么时候不需要 Agent Card

如果你的业务暂时不打算与外部 AI 代理、代理市场或合作方编排器集成,完整的 Agent Card 可以先放一放。以下情况并不需要它:

  • 只通过网页组件回答人类问题的站内聊天机器人;
  • 没有公开 API 的 MVP,与其他代理的集成会在之后再加;
  • 代理只被你自己的代码调用,而不被第三方系统调用的场景。

一旦出现合作方集成需求,或代理需要接入市场或他人的编排器,卡片就变为必需。

总结

Agent CardA2A 的主要 discovery 契约。带有精确 skills、诚实 capabilities 与明确 security 的完整 JSON,能让客户端代理找到正确执行者,并避免误调用。

如需开发、AI 部署或网站运维方面的帮助 - 请与我联系

常见问题

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。涉及写入、个人数据与付费操作时,声明 securitySchemessecurity,并把密钥放在卡片之外。

每次部署都要更新卡片吗?

当 skills、endpoint、capabilities、auth 或代理含义变化时更新。 无契约变更的技术补丁可反映在 version;破坏性变更应提升 major 并配套明确文档。

本文术语

A2A — Agent-to-Agent — AI 代理之间互相调用的协议

endpoint — specific API URL that accepts requests — 接受请求的具体 API 地址

webhook — HTTP callback when an event happens — 事件发生时触发的 HTTP 回调

LLM — Large Language Model — 大语言模型

semver — versioning as MAJOR.MINOR.PATCH for compatibility signals — 用 MAJOR.MINOR.PATCH 表达兼容性的版本规则

SSE — Server-Sent Events — 服务器通过 HTTP 向浏览器单向推送事件的流

API key — secret token that authenticates API callers — 用于验证 API 调用方的密钥

staging — pre-production environment for final checks — 上线前做最终检查的预发环境

MVP — Minimum Viable Product — 最小可行产品

联系方式