Skip to main content

Agent-to-Agent communication protocol for CLI agents

Project description

Synapse A2A

Google A2A プロトコル準拠の CLI エージェント間通信フレームワーク

Python 3.10+ License: MIT Tests

Claude Code / Codex / Gemini などの CLI エージェントを PTY でラップし、Google A2A プロトコルで相互通信を可能にするフレームワーク

flowchart LR
    subgraph Terminal1["Terminal 1"]
        subgraph Agent1["synapse claude :8100"]
            Server1["A2A Server"]
            PTY1["PTY + Claude CLI"]
        end
    end
    subgraph Terminal2["Terminal 2"]
        subgraph Agent2["synapse codex :8120"]
            Server2["A2A Server"]
            PTY2["PTY + Codex CLI"]
        end
    end
    subgraph External["外部"]
        ExtAgent["Google A2A Agent"]
    end

    Server1 <-->|"POST /tasks/send"| Server2
    Server1 <-->|"A2A Protocol"| ExtAgent
    Server2 <-->|"A2A Protocol"| ExtAgent

目次


主な特徴

カテゴリ 機能
A2A 準拠 全通信が Message/Part + Task 形式、Agent Card による発見
CLI 連携 既存の CLI ツールを改造せずに A2A エージェント化
@Agent 記法 @claude, @codex-8120 で直接メッセージ送信
送信元識別 metadata.sender + PID マッチングで送信元を自動識別
Priority Interrupt Priority 5 で SIGINT 送信後にメッセージ送信(緊急停止)
マルチインスタンス 同じエージェントタイプを複数同時起動(ポート自動割当)
外部連携 他の Google A2A エージェントとの通信

クイックスタート

1. インストール

# uv でインストール(推奨)
uv sync

# または pip
pip install -e .

2. エージェントを起動

# Terminal 1: Claude
synapse claude

# Terminal 2: Codex
synapse codex

# Terminal 3: Gemini
synapse gemini

ポートは自動割当されます:

エージェント ポート範囲
Claude 8100-8109
Gemini 8110-8119
Codex 8120-8129

3. エージェント間通信

端末内で @Agent を使ってメッセージ送信:

@codex この設計をレビューして
@gemini APIの改善案を出して

複数インスタンスがある場合は @type-port 形式で指定:

@codex-8120 こちらを担当して
@codex-8121 こちらを担当して

4. HTTP API

# メッセージ送信
curl -X POST http://localhost:8100/tasks/send \
  -H "Content-Type: application/json" \
  -d '{"message": {"role": "user", "parts": [{"type": "text", "text": "Hello!"}]}}'

# 緊急停止(Priority 5)
curl -X POST "http://localhost:8100/tasks/send-priority?priority=5" \
  -H "Content-Type: application/json" \
  -d '{"message": {"role": "user", "parts": [{"type": "text", "text": "Stop!"}]}}'

アーキテクチャ

A2A サーバー / クライアント構成

Synapse では 各エージェントが A2A サーバーとして動作 します。中央サーバーは存在せず、P2P 構成です。

┌─────────────────────────────────────┐    ┌─────────────────────────────────────┐
│  synapse claude (port 8100)         │    │  synapse codex (port 8120)          │
│  ┌───────────────────────────────┐  │    │  ┌───────────────────────────────┐  │
│  │  FastAPI Server (A2A Server)  │  │    │  │  FastAPI Server (A2A Server)  │  │
│  │  /.well-known/agent.json      │  │    │  │  /.well-known/agent.json      │  │
│  │  /tasks/send                  │◄─┼────┼──│  A2AClient                    │  │
│  │  /tasks/{id}                  │  │    │  └───────────────────────────────┘  │
│  └───────────────────────────────┘  │    │  ┌───────────────────────────────┐  │
│  ┌───────────────────────────────┐  │    │  │  PTY + Codex CLI              │  │
│  │  PTY + Claude CLI             │  │    │  └───────────────────────────────┘  │
│  └───────────────────────────────┘  │    └─────────────────────────────────────┘
└─────────────────────────────────────┘

各エージェントは:

  • A2A サーバー: 他のエージェントからのリクエストを受け付ける
  • A2A クライアント: 他のエージェントにリクエストを送信する

主要コンポーネント

コンポーネント ファイル 役割
FastAPI Server synapse/server.py A2A エンドポイント提供
A2A Router synapse/a2a_compat.py A2A プロトコル実装
A2A Client synapse/a2a_client.py 他エージェントへの通信
TerminalController synapse/controller.py PTY 管理、IDLE/BUSY 検出
InputRouter synapse/input_router.py @Agent パターン検出
AgentRegistry synapse/registry.py エージェント登録・検索

起動シーケンス

sequenceDiagram
    participant Synapse as Synapse Server
    participant Registry as AgentRegistry
    participant PTY as TerminalController
    participant CLI as CLI Agent

    Synapse->>Registry: 1. エージェント登録 (agent_id, pid, port)
    Synapse->>PTY: 2. PTY 起動
    PTY->>CLI: 3. CLI エージェント起動
    Synapse->>PTY: 4. 初期指示送信 (sender: synapse-system)
    PTY->>CLI: 5. AI が初期指示を受信

通信フロー

sequenceDiagram
    participant User as ユーザー
    participant Claude as Claude (8100)
    participant Client as A2AClient
    participant Codex as Codex (8120)

    User->>Claude: @codex 設計をレビューして
    Claude->>Client: send_to_local()
    Client->>Codex: POST /tasks/send-priority
    Codex->>Codex: Task 作成 → PTY に書き込み
    Codex-->>Client: {"task": {"id": "...", "status": "working"}}
    Client-->>Claude: [→ codex] 送信完了

CLI コマンド

基本操作

# エージェント起動(フォアグラウンド)
synapse claude
synapse codex
synapse gemini

# ポート指定
synapse claude --port 8105

# CLI ツールに引数を渡す
synapse claude -- --resume

コマンド一覧

コマンド 説明
synapse <profile> フォアグラウンドで起動
synapse start <profile> バックグラウンドで起動
synapse stop <profile> エージェント停止
synapse list 実行中エージェント一覧
synapse logs <profile> ログ表示
synapse send <target> <message> メッセージ送信

外部エージェント管理

# 外部エージェント登録
synapse external add http://other-agent:9000 --alias other

# 一覧表示
synapse external list

# メッセージ送信
synapse external send other "タスクを処理して"

A2A CLI ツール

低レベル操作用:

# エージェント一覧
python3 synapse/tools/a2a.py list

# メッセージ送信
python3 synapse/tools/a2a.py send --target claude --priority 1 "Hello"

# 緊急停止
python3 synapse/tools/a2a.py send --target claude --priority 5 "Stop!"

API エンドポイント

A2A 準拠

エンドポイント メソッド 説明
/.well-known/agent.json GET Agent Card
/tasks/send POST メッセージ送信
/tasks/send-priority POST Priority 付き送信
/tasks/{id} GET タスク状態取得
/tasks GET タスク一覧
/tasks/{id}/cancel POST タスクキャンセル
/status GET IDLE/BUSY 状態

外部エージェント

エンドポイント メソッド 説明
/external/discover POST 外部エージェント登録
/external/agents GET 一覧
/external/agents/{alias} DELETE 削除
/external/agents/{alias}/send POST 送信

Task 構造

A2A プロトコルでは、全ての通信が Task として管理されます。

Task ライフサイクル

stateDiagram-v2
    [*] --> submitted: POST /tasks/send
    submitted --> working: 処理開始
    working --> completed: 正常終了
    working --> failed: エラー
    working --> input_required: 追加入力待ち
    input_required --> working: 入力受信
    completed --> [*]
    failed --> [*]

Task オブジェクト

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "context_id": "conversation-123",
  "status": "working",
  "message": {
    "role": "user",
    "parts": [
      {"type": "text", "text": "この設計をレビューして"}
    ]
  },
  "artifacts": [],
  "metadata": {
    "sender": {
      "sender_id": "synapse-claude-8100",
      "sender_type": "claude",
      "sender_endpoint": "http://localhost:8100"
    }
  },
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:30:05Z"
}

フィールド説明

フィールド 説明
id string タスクの一意識別子(UUID)
context_id string? 会話コンテキスト ID(マルチターン用)
status string submitted / working / completed / failed / input_required
message Message 送信されたメッセージ
artifacts Artifact[] タスク完了時の成果物
metadata object 送信元情報など(metadata.sender
created_at string 作成日時(ISO 8601)
updated_at string 更新日時(ISO 8601)

Message 構造

{
  "role": "user",
  "parts": [
    {"type": "text", "text": "メッセージ内容"},
    {"type": "file", "file": {"name": "doc.pdf", "mimeType": "application/pdf", "bytes": "..."}}
  ]
}
Part タイプ 説明
text テキストメッセージ
file ファイル添付
data 構造化データ

初期指示 Task

エージェント起動時、Synapse は A2A Task として初期指示を送信します。

{
  "id": "init-task-id",
  "status": "working",
  "message": {
    "role": "user",
    "parts": [{"type": "text", "text": "[Synapse A2A Protocol Instructions]\n\n..."}]
  },
  "metadata": {
    "sender": {
      "sender_id": "synapse-system",
      "sender_type": "system",
      "sender_endpoint": "http://localhost:8100"
    }
  }
}

PTY 出力形式:

[A2A:init1234:synapse-system] [Synapse A2A Protocol Instructions]

You are participating in a multi-agent environment connected via the Synapse A2A Protocol.

## Your Identity
- Agent ID: synapse-claude-8100
- Agent Type: claude
- Port: 8100

## How to Send Messages (@Agent)
...

初期指示には以下が含まれます:

  • エージェントの identity(ID, type, port)
  • @Agent でのメッセージ送信方法
  • 利用可能な他のエージェント一覧
  • 送信元識別と 返信方法[A2A:task_id:sender_id] から sender_id を抽出して返信)

送信元識別

A2A メッセージの送信元は metadata.sender で識別できます。

PTY 出力形式

[A2A:<task_id>:<sender_id>] <message>

例:

[A2A:abc12345:synapse-claude-8100] この設計をレビューしてください

Task API での確認

curl -s http://localhost:8120/tasks/{task_id} | jq '.metadata.sender'

レスポンス:

{
  "sender_id": "synapse-claude-8100",
  "sender_type": "claude",
  "sender_endpoint": "http://localhost:8100"
}

仕組み

  1. 送信時: Registry を参照し、PID マッチングで自身の agent_id を特定
  2. Task 作成時: metadata.sender に送信元情報を付与
  3. 受信時: PTY プレフィックスまたは Task API で確認

Priority(優先度)

Priority 動作 用途
1-4 通常の stdin 書き込み 通常メッセージ
5 SIGINT 送信後に書き込み 緊急停止
# 緊急停止
synapse send claude "Stop!" --priority 5

Agent Card

各エージェントは /.well-known/agent.json で Agent Card を公開します。

curl http://localhost:8100/.well-known/agent.json
{
  "name": "Synapse Claude",
  "description": "PTY-wrapped claude CLI agent with A2A communication",
  "url": "http://localhost:8100",
  "capabilities": {
    "streaming": false,
    "pushNotifications": false,
    "multiTurn": true
  },
  "skills": [
    {"id": "chat", "name": "Chat", "description": "Send messages to the CLI agent"},
    {"id": "interrupt", "name": "Interrupt", "description": "Interrupt current processing"}
  ],
  "extensions": {
    "synapse": {
      "agent_id": "synapse-claude-8100",
      "pty_wrapped": true,
      "priority_interrupt": true,
      "at_agent_syntax": true
    }
  }
}

設計思想

Agent Card は「名刺」として他者向け情報のみを含みます:

  • capabilities, skills, endpoint など
  • 内部指示は含まない(起動時に A2A Task で送信)

レジストリとポート管理

レジストリファイル

~/.a2a/registry/
├── synapse-claude-8100.json
├── synapse-claude-8101.json
└── synapse-gemini-8110.json

自動クリーンアップ

stale エントリは以下の操作で自動削除:

  • synapse list 実行時
  • メッセージ送信時(対象が死んでいる場合)

ポート範囲

PORT_RANGES = {
    "claude": (8100, 8109),
    "gemini": (8110, 8119),
    "codex": (8120, 8129),
    "dummy": (8190, 8199),
}

テスト

218 のテストケースで A2A プロトコル準拠を検証:

# 全テスト
pytest

# 特定カテゴリ
pytest tests/test_a2a_compat.py -v
pytest tests/test_sender_identification.py -v

開発・リリース

PyPI への公開

タグをプッシュすると GitHub Actions で自動的に PyPI へ公開されます。

# 1. pyproject.toml のバージョンを更新
# version = "0.2.0"

# 2. タグを作成してプッシュ
git tag v0.2.0
git push origin v0.2.0

手動公開

# uv でビルド・公開
uv build
uv publish

ユーザーのインストール方法

# pipx(推奨)
pipx install synapse-a2a

# または pip
pip install synapse-a2a

# uvx で直接実行
uvx synapse-a2a claude

既知の制約

  • TUI 描画: Ink ベースの CLI で描画が乱れる場合あり
  • PTY 制限: 一部の特殊入力シーケンスは未対応
  • Streaming: 未対応

ドキュメント

パス 内容
guides/usage.md 使い方詳細
guides/architecture.md アーキテクチャ詳細
guides/troubleshooting.md トラブルシューティング
docs/project-philosophy.md 設計思想

ライセンス

MIT License


関連リンク

Project details


Release history Release notifications | RSS feed

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

synapse_a2a-0.1.0.tar.gz (63.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

synapse_a2a-0.1.0-py3-none-any.whl (44.3 kB view details)

Uploaded Python 3

File details

Details for the file synapse_a2a-0.1.0.tar.gz.

File metadata

  • Download URL: synapse_a2a-0.1.0.tar.gz
  • Upload date:
  • Size: 63.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for synapse_a2a-0.1.0.tar.gz
Algorithm Hash digest
SHA256 031556542b6c3cba6a901d59e51414ee3dec553048197a12adcacc098343c5b7
MD5 b1d4c42ca2d421f436125d42a2fd3ac6
BLAKE2b-256 9b9fefb9107d6c565cbe1979ef5cd7bccee56dbae47262073b0f0383439592df

See more details on using hashes here.

Provenance

The following attestation bundles were made for synapse_a2a-0.1.0.tar.gz:

Publisher: publish.yml on s-hiraoku/synapse-a2a

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file synapse_a2a-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: synapse_a2a-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 44.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for synapse_a2a-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b693fb1119f9feb162d3e307298184ff8f5eb411fb304817771d25709673251b
MD5 c163f59cfb1417f2328a0e5d9be36970
BLAKE2b-256 bc447aee71ea38fb8b8d7e258ea8129ff9e3c5e7fc2531e0f3d67624adaf0d1d

See more details on using hashes here.

Provenance

The following attestation bundles were made for synapse_a2a-0.1.0-py3-none-any.whl:

Publisher: publish.yml on s-hiraoku/synapse-a2a

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page