Skip to content

接到 Agent 上 ​

前提:管理员已经装好服务、登记身份、发布策略、创建 grant 并解锁对应钥匙。Agent 需要知道三样东西:

  • 受保护配置的路径,通常是 /etc/anpio-key/service.json;
  • grant_id;
  • 自己的系统账号(Agent 账号)。

完整协议和管理变更见仓库 ADAPTER.md。

用 CLI 发请求 ​

Agent 在自己的账号下,把一个请求保存成文件:

json
{
  "operation": "SIGN_HTTP",
  "grant_id": "管理员给的GRANT_ID",
  "request_id": "6b79d06e-33cf-44e2-8209-81938b6a8ed3",
  "http": {
    "method": "GET",
    "url": "https://service.example.com/v1/status",
    "headers": {},
    "body": {"state": "absent"},
    "nonce": null
  }
}
bash
anpio-key data --config /etc/anpio-key/service.json --file request.json

每个新操作要自己生成一个 UUID,并在调用前把它和原始输入保存下来。重试时复用同一个 request_id;不要重复使用示例里的 UUID。

其他数据操作:

操作用途
GET_CAPABILITIES看协议版本、operations、用途和 grant 类型
LIST_AUTHORIZED_KEYS看自己当前能用哪些钥匙
GET_DOCUMENT取某把钥匙的公开文档,需要 key_id
GET_GRANT_STATUS查 grant 的期限和剩余次数
GET_REQUEST_STATUS用原 request_id 查签名结果
SIGN_ORIGIN_PROOFANP origin proof,用 hot 键
RENEW_GRANT续 session grant,只延期不加次数
SIGN_PURPOSE设备/应用用途断言,用绑定了该用途的设备键
ECDHX25519 协商,用协商键
SIGN_OBJECT_PROOFW3C 对象 proof,用设备签名键
SIGN_DOCUMENT_PROOFDID 文档 proof,用根键的管理面 grant

SIGN_ORIGIN_PROOF、SIGN_PURPOSE、ECDH、SIGN_OBJECT_PROOF、SIGN_DOCUMENT_PROOF 默认关;先查 GET_CAPABILITIES 的 operations,名字不在里面就是没开,不要按构建版本猜。字段、编码与错误码见仓库 ADAPTER.md §11。

数据接口没有解锁、密码、通用根签名、任意字节签名或生命周期操作。唯一能用根键的数据面操作是 SIGN_DOCUMENT_PROOF,它的 grant 只能由管理面签发;换设备、改文档、注册这些根操作全部留在管理面。

调用方不是 Agent 账号:能力令牌 ​

anpio-key data 默认走 sign.sock,只认登记过的 Agent 主体。如果 Agent 跑在管理员账号下(单人 Mac、Claude Code 直接起进程),管理员可以签一张能力令牌,改用 capability.sock:

bash
anpio-key admin --config /Library/ANPIOKey/service.json capability mint \
  --uid 601 --did '<did>' --label mybot --out /tmp/mybot.capability

anpio-key data --config /Library/ANPIOKey/service.json \
  --capability-file /tmp/mybot.capability --file request.json

令牌把调用方指向一个已登记主体和一个 DID;grant 仍然照旧检查。这个入口默认关,开启方式、DID 作用域、四个 CAPABILITY_* 错误码和重启语义见能力令牌。anpio-cli 用户不用直接碰这条命令:did attach --capability-file 会把令牌放进身份目录,之后自动带上。

拿到签名之后 ​

用 daemon 返回的规范化 URL、原始 body 和签名头发送请求,关闭自动重定向。不要重新序列化 body,也不要改签名头里的任何字符。

超时或连接中断时:

  1. 用原 request_id 查询状态;
  2. 不要生成新 ID 重签;
  3. outcome_unknown 表示结果不确定,可能需要管理员核对;
  4. completed 只表示签名结果已保存,不表示对方业务已经执行。

用 Node ​

仓库的 adapters/keyd-v2.mjs 提供 AnpioKeyV2Client:

js
import { randomUUID } from 'node:crypto'
import { AnpioKeyV2Client } from './adapters/anpio-key-v2.mjs'

const client = new AnpioKeyV2Client({
  config: '/etc/anpio-key/service.json',
  binary: '/usr/local/libexec/anpio-key',
})
const request = {
  grant_id: 管理员给的GrantId,
  request_id: randomUUID(),
  method: 'GET',
  url: 'https://service.example.com/v1/status',
}
await saveOperation(request)          // 由你的应用实现
const signed = await client.sign(request)
const response = await fetch(signed.url, {
  method: signed.method,
  headers: signed.headers,
  body: signed.body,
  redirect: 'manual',
})

client.fetch(request) 把签名和发送合在一起,同样禁用重定向,也不自动重试。

用现有 SDK ​

anpioKeyV2Connector 接到 @connectx-sdk/core 的 createConfig / signRequest 上,需要你提供一个稳定的 requestId 函数。高层热密钥解析要求 SDK 0.4.2 或更新;更早版本可能错误地要求热钥匙匹配根指纹。

SDK 的 ANP-02 登录体和 awiki 的 JSON-RPC envelope 不是同一种 body。先构造正确的 body 再签名,不能签完再包装。

用 MCP ​

构建时启用 mcp,然后由 Agent 账号启动:

json
{
  "mcpServers": {
    "anpio-key": {
      "command": "/usr/local/libexec/anpio-key",
      "args": ["mcp", "--config", "/etc/anpio-key/service.json"]
    }
  }
}
工具输入
list_my_keys空对象
grant_statusgrant_id
get_did_documentkey_id
sign_requestgrant_id、request_id、http
request_statusrequest_id

配置在启动时固定;工具参数不能改 socket、配置路径、DID 或 kid。口令不经过 MCP。

管理员做什么 ​

管理员通过独立的 admin 通道:

  • prepare / commit:确认钥匙角色、发布策略、创建或撤销 grant;
  • unlock:输入口令解锁指定热钥匙;
  • complete-secret-operation:完成注册 proof 或热钥匙轮换。

注册、轮换和恢复都必须由管理员或可信管理适配器执行,Agent 不能代办。

服务重启后旧 grant 失效、钥匙锁定,需要管理员重新解锁和建权。文档在本地生成,不代表已经发布到网上。

给 Agent 的操作约束见仓库 skill。

Apache-2.0 许可