接到 Agent 上
前提:管理员已经装好服务、登记身份、发布策略、创建 grant 并解锁对应钥匙。Agent 需要知道三样东西:
- 受保护配置的路径,通常是
/etc/anpio-key/service.json; grant_id;- 自己的系统账号(Agent 账号)。
完整协议和管理变更见仓库 ADAPTER.md。
用 CLI 发请求
Agent 在自己的账号下,把一个请求保存成文件:
{
"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
}
}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_PROOF | ANP origin proof,用 hot 键 |
RENEW_GRANT | 续 session grant,只延期不加次数 |
SIGN_PURPOSE | 设备/应用用途断言,用绑定了该用途的设备键 |
ECDH | X25519 协商,用协商键 |
SIGN_OBJECT_PROOF | W3C 对象 proof,用设备签名键 |
SIGN_DOCUMENT_PROOF | DID 文档 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:
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,也不要改签名头里的任何字符。
超时或连接中断时:
- 用原
request_id查询状态; - 不要生成新 ID 重签;
outcome_unknown表示结果不确定,可能需要管理员核对;completed只表示签名结果已保存,不表示对方业务已经执行。
用 Node
仓库的 adapters/keyd-v2.mjs 提供 AnpioKeyV2Client:
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 账号启动:
{
"mcpServers": {
"anpio-key": {
"command": "/usr/local/libexec/anpio-key",
"args": ["mcp", "--config", "/etc/anpio-key/service.json"]
}
}
}| 工具 | 输入 |
|---|---|
list_my_keys | 空对象 |
grant_status | grant_id |
get_did_document | key_id |
sign_request | grant_id、request_id、http |
request_status | request_id |
配置在启动时固定;工具参数不能改 socket、配置路径、DID 或 kid。口令不经过 MCP。
管理员做什么
管理员通过独立的 admin 通道:
prepare/commit:确认钥匙角色、发布策略、创建或撤销 grant;unlock:输入口令解锁指定热钥匙;complete-secret-operation:完成注册 proof 或热钥匙轮换。
注册、轮换和恢复都必须由管理员或可信管理适配器执行,Agent 不能代办。
服务重启后旧 grant 失效、钥匙锁定,需要管理员重新解锁和建权。文档在本地生成,不代表已经发布到网上。
给 Agent 的操作约束见仓库 skill。