IBM Bob Shell v2.0.2 で追加された ACP(Agent Client Protocol)サーバーを実際に動かし、セッション作成からプロンプト送信・応答受信までの一連の流れを確認しました。従来の bob run との違いと、外部プログラムから Bob を制御する具体的な手順を解説します。
本記事の内容は Bob Shell v2.0.4 で検証しています。ACP は v2.0.2(2026年8月)で追加された機能であり、今後のバージョンで仕様が変更される可能性があります。
検証日: 2026-09-18 / macOS (Darwin 24.6.0)
ACP とは何か
ACP(Agent Client Protocol)は、コードエディタ / IDE と AI コーディングエージェント間の通信を標準化するプロトコルです。JSON-RPC 2.0 over stdio で動作します。
MCP(Model Context Protocol)がツールの公開に特化しているのに対し、ACP はエージェントのセッション管理・プロンプト送信・応答ストリーミングといったエージェント制御の全体をカバーします。JetBrains、Zed、Neovim、Eclipse、Emacs など主要なエディタ / IDE がすでに対応しており、エコシステムが急速に広がっています。
Bob Shell v2.0.2 で bob acp コマンドが追加され、ACP サーバーとして起動できるようになりました。changelog によれば、ACP 対応エディタ(Zed、IntelliJ、Neovim)から Bob に接続でき、モード・MCP サーバー・スキル・ツール承認・セッション管理といった Bob の完全なランタイムが利用可能とされています。
Bob の ACP 実装では、認証は現時点で IBM SSO(ブラウザ認証)のみです。bob run では BOB_API_KEY 環境変数による API キー認証が使えますが、bob acp ではサポートされていません。ACP の主な想定はエディタからエージェントへの接続ですが、プロトコル自体はクライアントの種類を限定しません。
Bob Shell(bob run)との違い
ACP は主にエディタからの接続を想定したプロトコルですが、JSON-RPC over stdio という汎用的な設計のため、外部プログラムやオーケストレーターからも利用できます。ここでは、従来の bob run(ヘッドレス CLI)と bob acp を比較し、それぞれの使いどころを整理します。
| 観点 |
bob run(Shell) |
bob acp(ACP サーバー) |
|---|---|---|
| インターフェース | ヘッドレス CLI(bob の TUI に対する非対話モード) |
JSON-RPC 2.0 over stdio |
| 実行モデル | 1コマンド = 1タスク。終了で完了 | 永続プロセス。セッションを管理 |
| セッション管理 |
--resume で再開可能 |
new / list / resume / close / delete / fork |
| 応答の受け取り | stdout にテキスト出力 | ストリーミング(agent_message_chunk) |
| モード指定 | --mode agent |
session/set_mode で動的変更 |
| 出力形式 | pretty / json / stream-json | JSON-RPC メッセージ(構造化) |
| コスト制御 |
--max-cost / --max-turns
|
セッション設定として送信 |
| 認証 | SSO または BOB_API_KEY
|
SSO のみ |
| ユースケース | シェルスクリプト・CI/CD | エディタ連携・オーケストレーター |
ひとことで言えば、bob run は「1コマンド1タスク」(--resume でセッション継続も可能)、bob acp は「常駐してプログラムから操作する」 ためのインターフェースです。
ACP サーバーの起動オプション
bob acp [options]
Options:
--trust ワークスペースを自動信頼
--auto-approve ツール呼び出しの許可プロンプトをスキップ
--disable-mcp MCP サーバーの初期化を無効化
--disable-subagents サブエージェントのツール登録を無効化
--log-level <level> debug | info | warn | error | silent
--accept-license IBM ライセンスに同意
--auto-approve はすべてのツール呼び出しを無条件に許可します。信頼できる環境でのみ使用してください。
実践: ACP で Bob と対話する
名前付きパイプ(FIFO)を使ってシェルスクリプトから ACP サーバーと対話する手順を示します。
通信の全体像
クライアント Bob ACP サーバー
│ │
│─── initialize ──────────────────────▶│
│◀── result (capabilities, modes) ─────│
│ │
│─── notifications/initialized ───────▶│
│ │
│─── session/new ─────────────────────▶│
│◀── result (sessionId) ───────────────│
│◀── session/update (commands) ────────│ ← スキル一覧
│ │
│─── session/prompt ──────────────────▶│
│◀── session/update (chunk: "Four") ───│ ← ストリーミング
│◀── session/update (chunk: ".") ──────│
│◀── result (stopReason: "end_turn") ──│
│ │
│─── session/close ───────────────────▶│
│ │
Step 1: ACP サーバーの起動と初期化
ACP サーバーを起動し、初期化ハンドシェイクを行います。protocolVersion は数値(文字列ではない)で渡す必要があります。
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": 1,
"clientInfo": { "name": "my-app", "version": "0.1" },
"capabilities": {}
}
}
{
"result": {
"protocolVersion": 1,
"agentCapabilities": {
"loadSession": true,
"sessionCapabilities": {
"list": {}, "delete": {}, "resume": {}, "close": {}
},
"promptCapabilities": {
"embeddedContext": true, "image": true
},
"mcpCapabilities": { "http": true, "sse": true }
},
"agentInfo": {
"name": "bob-shell",
"title": "Bob",
"version": "2.0.4"
}
}
}
初期化後、notifications/initialized を通知として送ります(id なし)。
Step 2: セッションの作成
session/new でセッションを作成します。cwd(作業ディレクトリ)と mcpServers は必須パラメータです。
{
"jsonrpc": "2.0",
"id": 2,
"method": "session/new",
"params": {
"cwd": "/path/to/workspace",
"mcpServers": {}
}
}
{
"result": {
"sessionId": "c86bd99c7b392c871ea00eb26aa2dcc5",
"modes": {
"currentModeId": "agent",
"availableModes": [
{ "id": "agent", "name": "Agent" },
{ "id": "plan", "name": "Plan" },
{ "id": "ask", "name": "Ask" },
{ "id": "forge", "name": "Forge" },
{ "id": "forgeshell", "name": "ForgeShell" }
]
}
}
}
セッション作成直後、Bob は session/update 通知でスキル一覧(available_commands_update)を送ってきます。
Step 3: プロンプトの送信と応答の受信
session/prompt でプロンプトを送信します。prompt パラメータは配列(Content Block の配列)です。
{
"jsonrpc": "2.0",
"id": 3,
"method": "session/prompt",
"params": {
"sessionId": "c86bd99c7b392c871ea00eb26aa2dcc5",
"prompt": [
{ "type": "text", "text": "What is 2+2? Answer in one word only." }
]
}
}
応答はストリーミングで返ってきます。session/update の agent_message_chunk としてチャンク単位で配信され、最後に id:3 の result で完了が通知されます。
{"method":"session/update", "params":{
"sessionId":"c86bd...72a7",
"update":{
"sessionUpdate":"agent_message_chunk",
"content":{"type":"text", "text":"Four"}
}
}}
{"id":3, "result":{"stopReason":"end_turn"}}
実測結果: 「What is 2+2?」に対して「Four.」と回答。stopReason は "end_turn" で正常終了。
E2E テスト用シェルスクリプト
上記の流れを自動化するスクリプトです。名前付きパイプ(FIFO)で ACP サーバーの stdin を制御します。
#!/bin/bash
FIFO=/tmp/bob-acp-fifo
rm -f "$FIFO"
mkfifo "$FIFO"
# ACP サーバー起動
bob acp --accept-license --trust --auto-approve \
< "$FIFO" > /tmp/bob-acp-responses.jsonl 2>/dev/null &
ACP_PID=$!
exec 3>"$FIFO"
# 1. Initialize
echo '{"jsonrpc":"2.0","id":1,"method":"initialize",
"params":{"protocolVersion":1,
"clientInfo":{"name":"test","version":"0.1"},
"capabilities":{}}}' >&3
sleep 2
# 2. Initialized notification
echo '{"jsonrpc":"2.0",
"method":"notifications/initialized"}' >&3
sleep 1
# 3. Create session
echo '{"jsonrpc":"2.0","id":2,"method":"session/new",
"params":{"cwd":"'"$PWD"'","mcpServers":{}}}' >&3
sleep 4
# sessionId を取得
SID=$(grep '"id":2' /tmp/bob-acp-responses.jsonl \
| sed -n 's/.*"sessionId":"\([^"]*\)".*/\1/p' \
| head -1)
echo "Session: $SID"
# 4. Send prompt
echo '{"jsonrpc":"2.0","id":3,"method":"session/prompt",
"params":{"sessionId":"'"$SID"'",
"prompt":[{"type":"text",
"text":"What is 2+2? Answer in one word."}]}}' >&3
# 応答を待機
for i in $(seq 1 30); do
sleep 1
grep -q '"id":3' /tmp/bob-acp-responses.jsonl && break
done
# クリーンアップ
exec 3>&-
kill $ACP_PID 2>/dev/null
wait $ACP_PID 2>/dev/null
rm -f "$FIFO"
# 結果表示
echo "=== Responses ==="
cat /tmp/bob-acp-responses.jsonl
実際の活用: Claude Code(Opus)から Bob を ACP で呼び出す
ACP は本来エディタとエージェントの接続を想定したプロトコルですが、クライアントの種類は限定されていません。この記事の検証では、Claude Code(Opus)のシェルスクリプト実行機能から ACP 経由で Bob を呼び出しました。つまり AI エージェント(Opus)が別の AI エージェント(Bob)を ACP で制御するという構成です。
Claude Code (Opus)
└── Bash ツールでシェルスクリプトを実行
└── bob acp (FIFO 経由)
└── initialize → session/new → session/prompt → 応答受信
Opus 側でスクリプトを生成・実行し、Bob の応答を JSON-RPC のストリームとして受け取り、結果を解析するところまでを一連の流れとして動作確認しています。ACP が stdio ベースの JSON-RPC であるため、シェルスクリプトだけで統合できる点が実用上のメリットでした。
この構成は「Opus が設計・検証を担当し、Bob が実行を担当する」という分業パターンの一例です。Bob のトークン単価はフロンティアモデル(Opus 等)と比べて大幅に安いため、実行量の多い作業を Bob に委ね、設計や判断をフロンティアモデルが担うことで、コストを抑えつつ高品質な成果を得られます。bob run でも同様の分業は可能ですが、ACP ではセッションを維持したまま複数のプロンプトを送れるため、対話的な作業指示や段階的なタスク分割に向いています。
ACP のメソッド一覧
Bob Shell v2.0.4(ACP は v2.0.2 で追加)の実装から確認できたメソッドの一覧です。
| カテゴリ | メソッド | 説明 |
|---|---|---|
| 接続 | initialize |
ハンドシェイク・能力交換 |
| 接続 | notifications/initialized |
初期化完了通知 |
| セッション | session/new |
新規セッション作成 |
| セッション | session/list |
既存セッション一覧 |
| セッション | session/load |
保存済みセッション読込 |
| セッション | session/resume |
セッション再開 |
| セッション | session/close |
セッション終了 |
| セッション | session/delete |
セッション削除 |
| セッション | session/fork |
セッション分岐 |
| セッション | session/cancel |
実行中タスクの中断 |
| プロンプト | session/prompt |
プロンプト送信 |
| プロンプト | session/update |
応答ストリーム・状態変更(通知) |
| 設定 | session/set_mode |
モード変更(agent/plan/ask/forge) |
| 設定 | session/set_config_option |
設定の動的変更 |
| 権限 | session/request_permission |
ツール実行の許可要求 |
使いどころ: いつ ACP を選ぶか
| やりたいこと | 推奨 | 理由 |
|---|---|---|
| CI/CD でタスクを1回実行 | bob run |
1コマンドで完結。終了コードで成否判定 |
| シェルスクリプトからバッチ実行 | bob run |
--max-cost / --max-turns で制御可能 |
| 外部アプリから対話的に制御 | bob acp |
セッション維持・ストリーミング応答 |
| 複数エージェントのオーケストレーション | bob acp |
セッション管理 API で並行制御 |
| IDE やフロントエンドへの組込み | bob acp |
構造化メッセージで UI 更新が容易 |
| セッションの中断・再開 | どちらも可 | Shell: --resume / ACP: session/resume
|
ハマりポイント
実際に動かして遭遇した注意点です。
protocolVersion は数値
"protocolVersion": "2025-draft" のように文字列で送ると Invalid params になります。Bob の ACP 実装では protocolVersion: 1(数値)が必要です。
stdin を閉じるとプロセスが終了する
ACP サーバーは stdio ベースのため、stdin の EOF でプロセスが終了します。パイプで接続する場合は名前付きパイプ(FIFO)を使い、fd を保持してください。
prompt は配列
session/prompt の prompt パラメータはオブジェクトではなく配列です。[{"type":"text","text":"..."}] の形式で送ります。
session/new の必須パラメータ
cwd と mcpServers は必須です。省略すると Invalid params で拒否されます。MCP サーバーを使わない場合でも "mcpServers": {} を明示的に渡します。
セッション ID は動的
session/new の応答から sessionId を取得し、以降のリクエストに使います。ハードコードすると Resource not found エラーになります。
FAQ
Q: ACP は HTTP サーバーとして起動できますか?
現時点(v2.0.4)では stdio 経由の JSON-RPC のみです。HTTP/SSE は MCP 側のケイパビリティとして宣言されていますが、ACP サーバー自体は stdio トランスポートです。
Q: 認証はどうなりますか? API キーは使えますか?
現時点では IBM SSO(ブラウザ認証)のみです。initialize の応答で authMethods に SSO だけが返されます。bob run にある --team-id オプションは bob acp には存在せず、Bob Shell 内部に BOB_API_KEY 環境変数の参照はありますが、ACP の認証メソッドとしては公開されていません。自動化等の目的で、バックエンドで Bob を ACP 経由で呼び出す際には、事前に SSO 認証済みの状態が必要ですのでご注意ください。
まとめ
Bob の ACP サーバーは、従来の bob run(ワンショット CLI)を補完する形で、プログラムから Bob を永続的に制御するための標準的なインターフェースを提供します。
- JSON-RPC over stdio で、任意の言語からクライアントを書ける
- セッションのライフサイクル管理(作成・再開・分岐・削除)が構造化されている
- 応答のストリーミングにより、リアルタイムな UI 更新が可能
- MCP との組み合わせで、ツールの動的な追加も視野に入る
マルチエージェントシステムや社内ツールへの組み込みを検討している方にとって、ACP は有力な選択肢の一つになると思います。Bob の ACP サーバー、ぜひ試してみてください。
