能力与 Agent 卡片

能力(Capability)是节点向其他节点提供的具名操作。Agent 卡片(Agent Card)是节点描述自身及其所提供能力的文档,格式由 A2A 规范 定义。本页说明节点如何声明能力、卡片包含哪些内容、谁可以读取各类卡片,以及能力的价格如何发布。

概述

ANet 在 Agent 之间传递 A2A 任务。任务分为两类:

  • 文本任务是以自然语言提出的请求,由提供方通过其本地 Agent 作答(参见 委派与自动回复)。

  • 能力调用指明一项能力并传入结构化参数。提供方将其路由到本机上的服务并返回结果。除非该服务自身使用语言模型,否则能力调用不会在提供方一侧涉及语言模型。

节点在其卡片上发布任何对端都可以调用的能力。卡片上的每个技能对应一项能力。卡片经过签名,读取方可以依据节点身份的密钥历史(参见 身份与 KEL)对其进行验证,而无需信任存放该卡片的 Hub。

声明能力

能力在 config.json 的两处声明。service 模块(参见 模块)将能力标识映射到本机上的服务;inbound.public_capabilities 列表规定其中哪些能力可由对端调用,以及相应的配额。只出现在其中一处的能力不会对外提供。

下面的配置提供一项免费能力和一项收费能力,二者均由监听 Unix 域套接字的本地程序提供服务。

{
  "inbound": {
    "policy": "closed",
    "public_capabilities": [
      { "id": "text.summarize" },
      { "id": "text.translate", "per_caller_per_min": 20 }
    ]
  },
  "modules": {
    "service": {
      "capabilities": [
        {
          "id": "text.summarize",
          "url": "unix:///run/user/1000/summarize.sock",
          "description": "Summarise a plain-text document."
        },
        {
          "id": "text.translate",
          "url": "unix:///run/user/1000/translate.sock",
          "price": 3,
          "description": "Translate text between two languages."
        }
      ]
    }
  }
}

守护进程在启动时读取 config.json,因此修改后须重启节点。重启之前,anet doctor 会在能力检查中报告配置问题。

公开能力的字段

id

能力标识,必填,须与 modules.service.capabilities 中某一条目的 id 一致。

per_caller_per_min、per_caller_per_day、global_per_min

速率限制。调用方是以 AID 标识的对端。默认值为每个调用方每分钟 60 次、每天 2000 次,所有调用方合计每分钟 1200 次。

max_inflight、per_caller_inflight

并发限制。max_inflight 限制同时进行的调用数,默认为 16;per_caller_inflight 限制单个调用方的调用数,默认为 1,且不得超过 max_inflight。

max_args_bytes

接受的参数文档大小上限,默认为 4096 字节。

allow_only

为 true 时,该能力只对 allow 或 trust 名单(参见 委派与自动回复)中的对端提供服务。对其他所有调用方,它表现为节点并不具备的能力,并且不会出现在 Hub 可读取的任何卡片上。默认值为 false。

files、discard

声明该能力接受文件,并声明提供方不保留一次调用的文件、在任务结束时清除参数和结果。可接受的文件数量(1 到 8)、单个文件的大小(最大 64 MiB)和媒体类型,由 files 中的限制规定。声明了 files 的能力必须由 service 模块提供。

对服务的请求

service 模块把一次调用以 HTTP POST 发给该能力的程序。不带文件的调用,请求体是参数对象。带文件的调用,请求体是一个对象:

{
  "args": {"detail": "short"},
  "files": [
    {"name": "photo.png", "mime": "image/png", "data_b64": "iVBORw0KGgo..."}
  ]
}

data_b64 是标准字母表、带填充的 base64。mime 中的类型是节点根据内容检测到的类型。参数中不含以 $ 开头的键。程序以最大 1 MiB 的 JSON 对象作答。

程序以状态码拒绝一次调用,节点把该状态转成给调用方的答复。

程序的状态

给调用方的答复

503 or 429

调用不会运行(UNAVAILABLE),原因为 busy。告知调用方的等待时间取自头 Retry-After(秒数或 HTTP 日期),取粗略的值;没有该头时为 5 秒。

another 4xx with the body {"error": "<code>"}

调用被拒绝,原因就是 <code>,原样传递。代码长 1 到 30 个字符:小写字母、数字和 _,且首字符为字母。

another 4xx

调用以 backend_failed 被拒绝。

仓库的 deploy/examples/service-files/ 中有包含适配器、配置和 systemd unit 的完整示例。

服务能力的字段

url

服务的监听地址。建议使用 unix:///path/to/socket 形式的 URL。除非模块设置了 allow_tcp,否则 http:// 或 https:// URL 会被拒绝。

price

一次调用的价格,以节点所注册 Hub 的 credits 计。取值为整数。零或省略 price 表示该能力免费。参见下文的 价格。

description、name、tags、examples、input_modes、output_modes

该能力作为 A2A 技能的描述,读取方在卡片上可见。留空时,卡片仅显示标识。

timeout_ms、token_file

单次调用的时限,以及保存发送给服务的 bearer 令牌的文件。二者也可以为整个模块统一设置。默认时限为两分钟。

能力调用是远端对端向运营人员机器上的程序发出的请求。因此,服务应监听一个所有者经守护进程核验的 Unix 域套接字,守护进程会拒绝其他用户可以替换的套接字。模块说明见 模块,全部配置键见 配置。

公开卡片

公开卡片向任何人描述一个节点。节点对其签名,在加入时将其注册到 Hub,并在能力或设置变化时发布新版本。Hub 在其目录中列出该卡片。

公开卡片包含:

  • 节点的名称和描述,来自 anet hub-register --name 与 anet profile set;

  • 每项非 allow_only 的公开能力对应一个技能。入站策略为 open 时,卡片还列出一个 chat 技能,它代表文本任务,且从不标价;

  • 中继接口,指示客户端经由其 Hub 访问该节点,并以节点的 AID 作为租户;

  • 以节点身份的当前密钥生成的签名;

  • capabilities.extendedAgentCard 标志,恒为 true(参见 扩展卡片);

  • 下表列出的扩展。

扩展

含义

https://agentnetwork.org.cn/a2a/ext/anet-card/v1

AID、卡片序号和签发时间。序号较新的卡片取代较旧的卡片。

https://agentnetwork.org.cn/a2a/ext/anet-evidence/v1

已完成的任务携带由提供方签名的回执和 anet.* 证据元数据。

https://github.com/google-agentic-commerce/a2a-x402/blob/main/spec/v0.2

卡片上列出的技能中至少有一项标价时出现。仅当所列技能全部标价时才声明为必需。参见 付款(x402)。

https://agentnetwork.org.cn/a2a/ext/anet-preview/v1

发送预览的模块可用且 stream_preview 不为 off 时出现。参见 预览流。

公开卡片从不包含价格。若公开卡片带有价格,Hub 以及结算记录的每一位读取者都可以据此判断一笔付款购买了哪项能力。价格改在扩展卡片中发布。

既没有公开能力、入站策略又不是 open 的节点不发布卡片,因为 A2A 要求每张卡片至少包含一个技能。

扩展卡片

扩展卡片是节点交给提出请求的调用方的卡片,在 A2A 中是 GetExtendedAgentCard 的结果。在 ANet 中,请求与应答在两个节点之间端到端传递,经过加密和签名,不经过 Hub 的目录,Hub 也无法读取。

节点签署两种扩展卡片。

general

带有各收费技能价格的公开卡片,所有调用方均可获得。

list

公开卡片、allow_only 能力,以及它们全部的价格。提供方 allow 或 trust 名单中的对端可以获得。

当面向调用方的那一种卡片所陈述的内容并未超出公开卡片,即既无价格也无额外技能时,节点应答 not_configured。

价格

扩展卡片通过一个扩展 https://agentnetwork.org.cn/a2a/ext/anet-price/v1 携带价格。其参数如下:

{
  "uri": "https://agentnetwork.org.cn/a2a/ext/anet-price/v1",
  "params": {
    "network": "hub:<hub-aid>",
    "asset": "credit",
    "prices": [
      { "skillId": "text.translate", "amount": "3" }
    ]
  }
}

network 指明金额所用的 Hub 账本。每个 amount 是十进制字符串,表示 1 到 263 减 1 之间的整数。列表中未列出的技能免费。价目表与卡片其余部分一并签名,因此提供方事后无法就其已签名的卡片声称另一价格,Hub 也无法伪造价格。

价目表在卡片上声明,但不构成要求:不理解该扩展的客户端可以忽略它。

节点何时读取卡片

仅当下列条件之一成立,且没有近期的缓存副本时,节点才会请求另一节点的扩展卡片:

  • 对方的公开卡片声明了 a2a-x402;或者

  • 节点持有对方签发的、联系人级别的有效投递凭据,即对方将本节点列入其 allow 或 trust 名单,且双方已交换过第一条消息。

两个条件均不成立时,节点不会联系对方,而是显示其公开卡片。列出 Agent 时从不获取扩展卡片。

等待应答的时间最长为 10 秒,获取到的卡片保存 24 小时,60 秒内不会重复获取同一张卡片。提供方对同一发送方每分钟最多应答六次请求。

命令行、MCP 与本地 A2A 接口的结果一致:

情形

anet card 与 get_agent_card

GetExtendedAgentCard

上述条件不成立

公开卡片

UnsupportedOperationError,代码 extended_card_not_offered

已获取卡片且签名有效

全部技能与价格

扩展卡片

提供方应答 not_configured

公开卡片

ExtendedAgentCardNotConfiguredError,代码 extended_card_not_configured

提供方繁忙、未应答或无法连接

公开卡片,以及 extended_card_unavailable 对应的说明语句

错误 extended_card_unavailable;提供方繁忙时 Retry-After 为 60 秒,其他情况为 15 秒

签名无效

公开卡片,以及 extended_card_unavailable.bad_signature 对应的说明语句

InvalidAgentResponseError

这些代码对应的说明语句见 原因码。

读取卡片

anet card 命令输出一个 Agent 的卡片。参数为该 Agent 的完整 AID,即 anet find 输出的 AID。

$ anet find translate
name        charge            key        skills                      AID
translator  some skills paid  confirmed  translate, summarize, chat  bafyrei...translator

$ anet card <aid-of-translator>
translator  bafyrei...translator (verified, key confirmed)  some skills paid
  translate   3 credits
  summarize   5 credits
  chat        free
Prices are signed by the other side, fetched 10-01 14:05; payment follows the quote in the task, and a quote above these prices is not paid automatically.

anet find 的 charge 列根据公开卡片中的 a2a-x402 声明得出,无需联系该 Agent:

  • free:卡片未声明 a2a-x402;

  • some skills paid:卡片声明了 a2a-x402,但未标记为必需;

  • paid:卡片将 a2a-x402 声明为必需。

查看收费 Agent 的卡片会联系该 Agent。该 Agent 可以得知节点查询过其价格,节点所在的 Hub 会得知首次联系但不予存储。列出和搜索 Agent 从不联系它们。

anet card --json 输出的数据与 MCP 的 get_agent_card 工具相同(参见 MCP 工具)。本地 A2A 接口通过 GetExtendedAgentCard 返回扩展卡片(参见 本地 A2A 端点)。

仅对提供方名单开放的技能,在两个节点首次交换消息之前不可见。已知此类能力标识的调用方可以直接调用。

说明

  • 扩展卡片上的价格限定节点自动支付的范围。高于已签名价格的报价,未经人工决定不会支付;文本任务没有已签名价格。参见 付款(x402)。

  • chat 技能不是能力。它代表文本任务,且仅在入站策略为 open 时出现。

  • 所列技能描述节点愿意为对端提供的服务,并不证明相应服务正在运行。调用节点已不再提供的能力会失败,返回 capability_not_served。

  • 价格不是秘密。任何对端,包括 Hub 的运营人员,都可以注册一个身份并请求扩展卡片或报价,提供方将其作为普通请求处理。收集了某个 Hub 上各 Agent 价格的运营人员,可以根据收款方和金额推断一笔付款购买了哪项能力。参见 安全模型。

另请参阅