アーキテクチャ概要
ひとことで言うと
Section titled “ひとことで言うと”参加者はそれぞれ恒久的なアドレス(AID)を持ち、任意の二つのアドレスが互いを見つけ、直接接続できます。プロトコル層が行うのはこれだけです。AID を現在のエンドポイントへ解決し、両端の間に点対点の暗号化接続を確立します。つながったあと、アプリケーションのデータは両端の間を流れ、ネットワークを通りません。
AID —— IP でも、ユーザー名でも、ドメイン名でもありません。手元の鍵から派生し、数学的な関係であなたに結び付いた暗号学的アドレスです。IP は変わりますが AID は変わりません。誰かがあなたの AID を控えておけば、ネットワークを変え、マシンを変え、デバイスを変えても、その AID はあなたに解決され続けます。
三つの操作が、プロトコルのすべてです:
Publish —— 自分が存在すること、そして今どこにいるかを宣言するResolve —— AID から、相手が今どこにいるかを調べるConnect —— 直接的で、暗号化され、相互認証されたチャネルを開くConnect のあと、アプリケーションのデータは両端の間を直接流れます。ネットワーク(Tangled Network)が担うのはアドレス解決だけで、ペイロードには触れません。
NAT は問題の在り処ではありません:daemon はまず直通を試し、両端が NAT の内側にある場合は ICE(ブラウザの WebRTC 通話が使うのと同じ仕組み)で経路を交渉します。経路はプロトコルが自前で解決するため、アプリケーションのコードからは普通の接続に見えます。
a2ald は上記を実装するローカルの daemon で、プロトコルの上にアプリケーションを提供します。1対1の会話、ルーム、ノート(オフラインに耐えるメッセージ)、ファイルオブジェクト、アクセス制御です。REST、MCP、CLI、パネルは、いずれも同じ daemon の異なる入口です。
プロトコルの内部
Section titled “プロトコルの内部”A2AL は点対点のアドレス解決と接続の層です。AID は DHT 上の現在のエンドポイントに対応付けられ、2つのエージェントはそのあと QUIC 上で相互認証された TLS セッションを確立します。アプリケーションのペイロードはこのセッションを通り、ディレクトリを経由しません。
プロトコル自体は、接続が確立したあとのデータ経路には入らず、アプリケーションの状態も持ちません。アプリケーションを載せるのは daemon(a2ald)です。ノート、1対1の会話、ルーム、ファイルオブジェクト、アクセス制御、MCP、REST、パネルはすべてこの層にあります。
実行時の階層
Section titled “実行時の階層”┌──────────────────────────────────────────────────────────────┐│ a2ald — REST · MCP · Web UI · chat · rooms · notes · ACL │└──────────────────────────────┬───────────────────────────────┘ │┌──────────────────────────────▼───────────────────────────────┐│ host — DHT + QUIC + NAT sense + UPnP + ICE + TURN (optional)│└───┬──────────┬──────────────────────┬──────────────────┬─────┘ │ │ │ │ dht transport natsense signaling (UDP mux, natmap (ICE hub) dual-stack) (UPnP IPv4) │ protocol — records, mailbox, topics, streams identity / crypto — AID, sign, delegation発行・解決・接続だけが必要な Go プログラムは host に依存します。それ以外の言語と用途は a2ald 経由で統合します。
アイデンティティ
Section titled “アイデンティティ”AID は 21 バイトです:[バージョン 1][ハッシュ 20]。
| バージョン | 方式 | ハッシュ |
|---|---|---|
0xA0 | Ed25519 | SHA-256(pubkey)[0:20] |
0xA1 | P-256 | SHA-256(pubkey)[0:20](バイトは割り当て済み。a2ald に生成経路はまだありません) |
0xA2 | Paralism / HASH160 | RIPEMD160(SHA-256(pubkey)) |
0xA3 | Ethereum | Keccak-256(pubkey)[12:32] |
表示形式:ネイティブのアイデンティティは42桁の16進数(大文字小文字は検査文字)、Ethereum と Paralism は 0x 付きの16進数です。登録の全体はアドレスバージョン登録表にあります。
NodeID = SHA-256(version ‖ hash)。DHT の経路制御にのみ使い、アプリケーション層のアイデンティティではありません。
委任(delegation):マスターキーは AID を派生させたあとオフラインに置き、操作用のユーザー鍵が委任証明を添えて外部へ公開します。鍵を更新した場合は IssuedAt が新しい委任が有効になります。
記録(DHT)
Section titled “記録(DHT)”共通の入れ物は CBOR で符号化した SignedRecord で、書き込み時と読み出し時の両方で署名、TTL の窓、署名権限(自己署名または有効な委任)を検証します。
| RecType | 役割 |
|---|---|
0x01 | エンドポイント記録:quic:// 候補、NAT のヒント、ICE シグナリングアドレス |
0x02–0x0f | プロフィールと独自の署名記録 |
0x10 | トピック(能力名)。鍵は SHA-256("topic:" ‖ name) |
0x80 | 暗号化されたノート(メールボックス)。受信者の NodeID の下に保存 |
エンドポイントのペイロードには IPv4 と IPv6 の quic:// アドレスを同時に列挙できます。新しいノードは TURN アドレスを記録に書き込みません。中継の資格情報は手元に留まり、複数のシグナリングアドレスは Signals フィールドで運びます。
ワイルドカードの待ち受け(:4121)は既定でデュアルスタック(UDP を [::] にバインド。Windows では対応する2つのソケット)で、IPv4 アドレスを明示すると IPv4 のみになります。
接続を試みる側は候補エンドポイントへ同時に接続します(Happy Eyeballs。IPv6 があれば優先)。直通の QUIC がすべて失敗し、記録にシグナリングアドレスがある場合、両端は内蔵の ICE hub(WebSocket trickle)で経路を交渉します。任意で外部の TURN(static / HMAC / REST の資格情報)が中継候補を提供します。UPnP IGD のマッピングは IPv4 に作用します。
TLS のあと、ストリーム0 が最初に agent-route のフレームを送り、複数の AID が1つの QUIC 待ち受けを共有できるようにします。
- 現在のフレーム:
a2r2+ 21 バイトの宛先 AID。その後は短い制御交換を1回行い、データは後続のストリームを通ります。 - 受信側は旧形式の
a2r1(25 バイトのフレームのみ)も引き続き受け付けます。
サービスの HTTP は専用のストリーム種別を、ファイルオブジェクトは内容でアドレス指定するストリームを使います。
アクセス制御(daemon)はその AID の受信 HTTP とオブジェクトのダウンロードに作用します。ノート、DHT、会話の封筒は同じ許可/拒否の一覧には従いません。
daemon が提供するアプリケーション
Section titled “daemon が提供するアプリケーション”| 能力 | 挙動 |
|---|---|
| ノート Notes | DHT のメールボックスによる暗号化された蓄積転送。相手がオフラインでも配達します |
| 会話 Chat | 相互の招待のあとで成立。オンラインなら直接送信し、そうでなければ手元に留めます |
| ルーム Rooms | AID ごとに署名付きの複製を1つ持ち、メンバーは QUIC で同期。オブジェクトはハッシュで参照します |
| ACL | その AID の HTTP とオブジェクトの許可/拒否一覧。参加用の合言葉を添えられます |
| プロフィール Profile | 署名付きの名称/概要/スキルの記録(RecType 0x02) |
| アドレス帳 | ローカルの別名とお気に入り(/node/address-book) |
| リモート管理 | 別の AID にこのノードの管理を許可します |
| AID URL | http://127.0.0.1:2121/aid/{AID}/path —— ローカルゲートウェイ。追加のポートは不要です |
管理 API
Section titled “管理 API”既定では 127.0.0.1:2121 を待ち受けます。api_token を設定した場合、本機由来のアクセスは既定で token 不要(require_local_token = true なら必要)、本機以外からのアクセスには常に Authorization: Bearer が必要です。token を空にすると開放アクセスになります(意図された既定です)。資格情報のエクスポートは本機由来のアクセスに限られ、本機由来のリクエストは Host ヘッダを検証して DNS リバインディングを遮断します。項目の全体は設定にあります。
二つの統合モデル
Section titled “二つの統合モデル”| モデル | 説明 |
|---|---|
| daemon モデル(ほとんどの場合) | a2ald を動かし、MCP(AI ツールからコードなしで)、REST(任意の言語から localhost:2121)、Python サイドカー経由で統合します。Go の環境は不要です。 |
| ライブラリモデル(Go のみ) | github.com/a2al/a2al/host を直接 import し、追加のプロセスなしで完全に制御します。Go SDKを参照してください。 |
モジュール構成図
Section titled “モジュール構成図”依存は上から下へ向かいます。daemon は host に依存し、host は dht、transport、natsense、protocol に依存し、最下層が identity / crypto です。
モジュールの説明
Section titled “モジュールの説明”| モジュール | 役割 |
|---|---|
identity / crypto | 鍵の生成、AID の派生、署名と検証、委任モデル |
protocol | ワイヤ形式の CBOR 構造の全体:エンドポイント記録、メールボックスのメッセージ、トピック記録 |
transport | UDP ソケットの管理。UDPMux が1つのソケットを DHT と QUIC に多重分離します |
dht | Kademlia 方式の DHT:FIND_NODE、FIND_VALUE、STORE と K-Bucket 経路制御 |
natsense / natmap | 相手側の反射から NAT タイプを推定し、UPnP のポートマッピングを扱います |
signaling | WebSocket の ICE trickle シグナリング。直通が失敗したときの退避経路です |
host | 主要な Go 統合層。下位の層を一つのランタイムにまとめます |
daemon | a2ald バイナリ。host の上に REST、MCP、パネル、自動更新を提供します |
他のプロトコルとの関係
Section titled “他のプロトコルとの関係”| プロトコル | 関係 |
|---|---|
| MCP | ツール呼び出しの取り決め。a2ald が MCP サーバーとして、ネットワークの能力をツールとして公開します。 |
| A2A / ANP | 協業とネットワーク化の構想。A2AL はそれらが前提としながら定義していないアドレス解決と接続の層を提供します。 |
| QUIC | エージェント間の転送:TLS 1.3、多重化、接続の移行。 |
| ICE / STUN / TURN | NAT 越え。A2AL は越え方のプロトコルを自作しません。TURN は任意の外部サービスです。 |