Confer — 协议设计

定义 Confer 实例之间、用户客户端与服务器之间的所有协议。所有协议都基于开放标准,便于将来联邦化。

Agent 身份

DID:web 格式

每个用户/企业实例托管自己的 DID document:

https://acme.com/.well-known/did.json

DID document 结构(W3C DID v1.0 兼容):

{
  "@context": ["https://www.w3.org/ns/did/v1"],
  "id": "did:web:acme.com",
  "verificationMethod": [
    {
      "id": "did:web:acme.com#key-1",
      "type": "Ed25519VerificationKey2020",
      "controller": "did:web:acme.com",
      "publicKeyMultibase": "z6MkpTHR8VNsBxYAAWHut2Geadd9jSrue..."
    }
  ],
  "service": [
    {
      "id": "did:web:acme.com#confer-agent",
      "type": "ConferAgent",
      "serviceEndpoint": "https://acme.com/a2a/v1"
    }
  ]
}

用户 Agent 的 DID 形式:did:web:acme.com:agents:laowang —— 主实例 + 路径段。这样一个实例可以承载多个用户。

密钥轮换

AgentFacts (NANDA-compatible)

每个 Agent 公开一份 AgentFacts 描述自己。位置:

https://acme.com/agents/{slug}/agent.json

或 well-known 总目录:

https://acme.com/.well-known/agents.json

结构示例:

{
  "@context": "https://nanda.dev/schemas/agent/v1",
  "did": "did:web:acme.com:agents:support",
  "name": "ABC Industries Support Agent",
  "description": "Technical support for X100, X200 industrial controllers",
  "owner": {
    "type": "Organization",
    "name": "ABC Industries Ltd.",
    "url": "https://acme.com"
  },
  "capabilities": [
    {
      "type": "qa",
      "scope": ["X100", "X200", "Modbus", "RTU", "TCP"],
      "languages": ["en", "zh", "de"]
    },
    {
      "type": "code-generation",
      "scope": ["python", "c", "embedded"],
      "languages": ["en", "zh"]
    }
  ],
  "endpoints": {
    "a2a": "https://acme.com/a2a/v1",
    "stream": "https://acme.com/a2a/v1/stream"
  },
  "trust": {
    "verifiedBy": ["did:web:nanda.org"],
    "issuedAt": "2024-10-01T00:00:00Z"
  },
  "publicKey": {
    "id": "did:web:acme.com#key-1",
    "type": "Ed25519VerificationKey2020"
  }
}

字段说明:

A2A 协议

协议层

所有 A2A 通信走 HTTPS POST/GET,编码 JSON。

关键:使用 HTTP Message Signatures(RFC 9421)而非 bearer token。原因:

入站请求示例

POST /a2a/v1/messages HTTP/1.1
Host: acme.com
Content-Type: application/json
Date: Sun, 24 Nov 2024 14:30:00 GMT
Digest: SHA-256=X48E9qOokqqrvdts8nOJRJN3OWDUoyWxBf7kbu9DBPE=
Signature: keyId="did:web:vendor-x.com#key-1",
           algorithm="ed25519",
           headers="(request-target) host date digest",
           signature="aBcDeF..."
Authorization: Capability eyJhbGciOiJFZDI1NTE5IiwidHlwIjoiQ2FwIn0...

{
  "from": "did:web:vendor-x.com:agents:engineer-li",
  "to": "did:web:acme.com:agents:support",
  "thread_id": "thread_8f3a9c",
  "message": {
    "type": "question",
    "content": "X100 在 RTU 模式下的电压范围?",
    "language": "zh",
    "context": {
      "via": "claude-code",
      "project_hint": "modbus integration"
    }
  }
}

验证流程(接收方)

  1. 解析 Signature header
  2. 提取 keyId(含 DID)
  3. 拉 DID document(带缓存:ETag + 60s TTL)
  4. 取出公钥,验证 signature
  5. 验证 Digest 匹配 body 哈希
  6. 检查 Date 在 5 分钟内(防 replay)
  7. 验证 Capability token(macaroon 风格,下面详述)
  8. 连接同意闸门:发送方是否已被接收方加为联系人?未连接 → 不跑 LLM,挂起为连接请求(见下)
  9. 已连接 → 走 policy engine 决定要不要响应

Capability token

Capability token 让发送方 Agent 表明”我代表 X 用户来询问 Y 类问题”,可以细粒度限制权限。

JWT 风格但用 macaroon 思路:

{
  "iss": "did:web:vendor-x.com",
  "sub": "did:web:vendor-x.com:users:engineer-li",
  "aud": "did:web:acme.com",
  "scope": ["ask:technical", "ask:product:X100"],
  "exp": 1737000000,
  "ctx": {
    "thread_id": "thread_8f3a9c",
    "delegation_depth": 1
  }
}

响应流式输出

LLM 生成答案是流式的,A2A 也支持 SSE:

GET /a2a/v1/stream/{message_id} HTTP/1.1
Host: acme.com
Signature: ...

返回 text/event-stream

event: token
data: {"text": "X100 "}

event: token
data: {"text": "在 RTU "}

event: citation
data: {"source": "X100 安装手册 p.12", "url": "..."}

event: done
data: {"thread_id": "thread_8f3a9c"}

权限模型(Claude Code-inspired)

三级权限分层:

L1 - 自动(无需确认)

L2 - 询问一次

UI 表现:弹出权限卡片,4 个选项:

L3 - 显式同意(每次都问)

UI 表现:模态弹窗 + 详细操作清单 + 倒计时(防误点)。

Standing policies

用户可以预先设置规则,覆盖默认行为:

peer.acme-industries:
  allow:
    - read: "src/modbus/**"
    - ask: "technical:*"
  deny:
    - read: ".env"
    - read: "**/secrets/**"
    - ask: "personal:*"
  always_consult: true

peer.unknown:
  default: ask_user
  require_human_in_loop: true

连接同意闸门(consent gate)

回答一条 A2A 消息会消耗接收方的 LLM 预算。为防止陌生 Agent 在主人不知情时疯狂发消息、烧掉主人的 token,连接是消费的前置条件:

模型形态对标 LinkedIn / 企业联邦:发现层开放(任何人可读 agents.json、AgentFacts),交互层需同意(连接后才能消耗对方算力)。

成为「已连接」有两条路径:

  1. 接收方主动通过 POST /contacts/lookupPOST /contacts 添加该 peer;
  2. peer 先发起,接收方在收件箱批准其连接请求。

Pending inbox(离线代答)

主人离线时收到已连接 peer 的问题:

联邦发现

域名查找

输入域名 acme.com,客户端:

  1. https://acme.com/.well-known/did.json 拿主 DID
  2. https://acme.com/.well-known/agents.json 列出该域名下所有公开 Agent
  3. 选一个加为联系人

公共注册表(v2+)

接入 NANDA Index 或类似公共注册表,支持:

信任图(v2+)

反垃圾

翻译策略

协议演化策略

← Back to Confer A2A · DID:web · RFC 9421 · NANDA