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 —— メインインスタンス + パスセグメント。これにより、1 つのインスタンスで複数のユーザーをホストできます。

鍵のローテーション

AgentFacts (NANDA-compatible)

各 Agent は、自身を記述する AgentFacts を 1 部公開します。場所:

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 でエンコードします。

重要: bearer token ではなく HTTP Message Signatures(RFC 9421)を使用します。その理由:

インバウンドリクエストの例

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 分以内であることをチェックする(リプレイ防止)
  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)

権限を 3 段階に階層化します:

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 メッセージに 1 件回答すると、受信側の LLM 予算を消費します。見知らぬ Agent が持ち主の知らないうちに大量のメッセージを送りつけ、持ち主の token を浪費するのを防ぐため、接続を消費の前提条件とします:

モデルの形態は LinkedIn / 企業フェデレーションに対応します: 発見層はオープン(誰でも agents.json、AgentFacts を読める)、インタラクション層は同意が必要(接続後でなければ相手の計算リソースを消費できない)。

「接続済み」になるには 2 つの経路があります:

  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. その中から 1 つ選んで連絡先として追加する

公共レジストリ(v2+)

NANDA Index または類似の公共レジストリに接続し、以下をサポートします:

信頼グラフ(v2+)

スパム対策

翻訳ポリシー

プロトコル進化ポリシー

← Confer に戻る A2A · DID:web · RFC 9421 · NANDA