0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

IBM Bob の ACP サーバーを使ってみた — Bob Shell との違いと実践ガイド

0
Posted at

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/updateagent_message_chunk としてチャンク単位で配信され、最後に id:3 の result で完了が通知されます。

ストリーミング応答(通知、id なし)
{"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 を制御します。

bob-acp-e2e-test.sh
#!/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/promptprompt パラメータはオブジェクトではなく配列です。[{"type":"text","text":"..."}] の形式で送ります。

session/new の必須パラメータ

cwdmcpServers は必須です。省略すると 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 サーバー、ぜひ試してみてください。

参考リソース

Blog banner with free trial guidance - Blue.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?