Agent Client Protocol アーキテクチャ
ACP は、コーディングインターフェースとコーディングエージェントの関係を標準化します。これにより、機能を確立し、プロジェクトセッションを開き、プロンプトをやり取りし、進行状況をストリーミングし、許可を要求し、作業をキャンセルし、セッションを終了または再開するための共通の方法が提供されます。
2つの役割
| 役割 | 責務 |
|---|---|
| クライアント / ホスト | エージェントプロセスを開始し、人間向けインターフェースを表示し、ワークスペースを選択し、任意のファイル、ターミナル、および MCP サーバーを提供し、権限ポリシーを適用し、ライブ更新を表示する |
| ACP エージェント | プロジェクトセッションとプロンプトを受け入れ、コーディング作業を実行し、メッセージとツールの活動を報告し、必要に応じて許可を求め、型付きの停止理由を返す |
ADK-Rust はどちらの役割も担うことができます。これは 2 つのプロトコルではなく、2 つの配置方向です。
ADK-Rust が別のコーディングエージェントを消費する場合、左側は ADK-Rust で、右側は外部プロセスです。エディタが ADK-Rust エージェントを消費する場合、エディタが左側を所有し、AcpServer が右側を所有します。
1 回の ACP ターン
接続は双方向です。クライアントは、プロンプトの実行中も読み取りを継続しなければなりません。エージェントが最終的なプロンプト応答の前に通知や権限要求を送る場合があるためです。
セッション ID と状態
ACP セッションは、1 つのプロジェクトに関する継続中の会話を識別します。そこには絶対 cwd、任意の追加ディレクトリ、複数のプロンプト、ストリーミング更新、およびライフサイクルが含まれます。ADK-Rust サーバーでは、1 つの ACP セッションが 1 つの ADK-Rust セッションに対応し、モデル履歴とセッション状態が同じ会話に結び付いたままになります。
アクティブな接続を閉じることは、永続化された履歴を削除することとは異なります。
session/closeはアクティブなセッションとそのプロセスを解放する;session/resumeは永続化された ADK セッション状態に接続する;session/loadは永続化されたセッションを再アクティブ化し、保存されている会話を順序付きのsession/update通知としてクライアントに再生してから、要求を完了する;session/forkは永続化されたセッションを、新しいセッション ID に分岐させる。その保存済み履歴は元の履歴のコピーであり、元は変更されない;session/deleteは永続化されたセッションを削除する;session/listは、構成済みのSessionServiceを通じて可視なセッションを返す。
session/load は、提供された cwd をセッションの保存済み作業ディレクトリに対して、session/resume と同じ方法で検証し、未知のセッション識別子に対してはセッション未検出エラーを返します。再生は、保存された各ユーザー、エージェント、思考、ツールのイベントを元の時系列順で対応する SessionUpdate バリアントにマッピングするため、再接続したエディタは、表示される履歴を発生順に復元します。
インタラクティブなセッション制御
エージェントは、SessionControls プロバイダーを提供することで、クライアントにインタラクティブな制御を公開できます。その場合、サーバーはそれらを session/new、session/load、session/resume、および session/fork の応答で通知します。
- モード — 「ask」と「code」のような、名前付きモードの集合と現在の選択。
session/set_modeは要求されたモードを通知済みの集合に対して検証し、記録し、CurrentModeUpdateを発行します。未知のモードは拒否され、現在のモードは変更されません。 - 設定オプション — クライアントが読み取りおよび変更できる選択肢とトグル。
session/set_config_optionは値をオプションの宣言済み選択肢に対して検証し、記録し、ConfigOptionUpdateを発行します。未知のオプションまたは無効な値は拒否されます。 - 利用可能なコマンド — セッションがアクティブになると、ACP スラッシュコマンドが
AvailableCommandsUpdateとして表示される。
モードと設定の選択は、ADK セッション状態(acp:mode、acp:config:<id>)に保持されるため、読み込み、再開、分岐をまたいで維持されます。記録されたセッションタイトルは、アクティブ化時および変更されるたびに SessionInfoUpdate として表示されます。Plan 更新マッピングは存在しますが、ADK プラン原語がプラン項目を公開するまでは休止したままです。SessionControls を提供しないエージェントはモードもオプションも公開せず、公開される機能をサーバーの実装内容と正確に一致させます。
コンテンツは 1 つのマッピングを通じて境界を越える
クライアントから届くプロンプトと、それに向けてストリーミングされる更新は、どちらも単一のコンテンツモジュールを通過し、ACP ContentBlock 値を adk_core::Part 値へ、またその逆へマッピングします。双方向で 1 つのマッピングを維持することで、サーバーのプロンプトパーサー、サーバーストリーマー、そしてクライアントが、各コンテンツ型の表現方法について一致できます。
このマッピングはペイロードを忠実に保持します。テキストブロックは文字列をそのまま保ったまま Part::Text にマッピングされます。埋め込みリソースブロックは Part::EmbeddedResource にマッピングされ、ソース URI、任意の MIME タイプ、および内容が保持されます。テキストリソースは両方向でそのまま転送され、base64 エンコードされることはありません。バイナリリソースは通信経路上で base64 エンコードされ、境界の ADK 側で生のバイト列にデコードされます。画像ブロックと音声ブロックは Part::InlineData にマッピングされ、MIME タイプとデコード済みバイト列が保持されます。サーバーはこれらのプロンプトメディアを公開し受け入れ、クライアントはテキスト以外の ADK コンテンツ(埋め込みリソース、画像、音声)を破棄せず、対応する ACP ブロックとして送信します。
ストリーミング更新はテキスト以上を運ぶ
プロンプトの実行中、サーバーは型付き ADK イベントを ACP session/update 通知へ変換します。モデルのテキストと考えはメッセージチャンクと考えチャンクになり、埋め込みリソースの内容は埋め込みリソースメッセージチャンクになります。それに加えて、2 種類の更新が、クライアントにターンのより豊かなビューを与えます。
- 使用量更新。 ADK イベントが使用量メタデータを含む場合、サーバーは報告されたトークン数を反映した
UsageUpdateを送信し、ランタイムが報告する場合は USD のコストも送信します。使用量メタデータを持たないイベントは更新を生成せず、サーバーが数値を捏造することはありません。 - リッチなツール呼び出し更新。 ツール呼び出しは、ツールの宣言された動作から推論されたツール
kindを持つToolCallとして始まります。その後のToolCallUpdateには、ツール結果の内容と、ツールが影響したと報告したファイルの場所が含まれるため、エディタは差分と影響を受けたファイル一覧を描画できます。この更新は、元のToolCallと同じ識別子を保持し、ターンをまたいだ相関を維持します。
クライアント側の方向は同等の忠実度を持ちます。ADK-Rust アプリケーションが External_Agent を消費すると、そのストリーミング表面(OutputChunk)は、エージェントのテキストと思考だけでなく、External_Agent の ToolCallUpdate も公開します(ステータス、種類、タイトル、内容テキスト、影響を受けるファイルの場所を含む id 関連付けされた tool-update として)、さらにその UsageUpdate も公開します(使用したトークンとサイズ、報告される場合はコストと通貨も含む)。エージェントのメッセージテキストはこれまでどおり正確に公開されるため、既存のテキスト消費側には影響ありません。
権限要求は tool の確認をブリッジします
ADK-Rust エージェントは、tool 呼び出し(ToolConfirmationRequest)に対する人間の承認を待つ間、1 ターンを一時停止できます。サーバー側では、その一時停止は tool とその引数を説明するネイティブな ACP session/request_permission 要求になります。クライアントの結果がターンを再開させます。承認は allow に対応し、拒否またはキャンセルはいずれも deny に対応するため、キャンセルされた要求が tool を実行することはありません。各結果は function-call 識別子によって正確な呼び出しに関連付けられ、tool-confirmation の決定を通じてランナーにフィードバックされます。ネストされた権限要求は生成された prompt タスクから発行されるため、外側の session/prompt 応答は引き続き通常どおり完了します。
機能は契約です
初期化は装飾的なハンドシェイクではありません。各側は、自身がサポートする操作とコンテンツのみを通知します。ADK-Rust はその機能を使って、stdio のみを受け入れるエージェントに対して任意の HTTP や SSE MCP 設定を送らないようにし、アプリケーションが対応する実装を提供した場合にのみ filesystem または terminal の host 操作を通知します。
サーバーは、prompt ハンドラが受け入れるコンテンツタイプを正確に通知します。埋め込みリソースのコンテンツは adk_core::Part::EmbeddedResource に、image と audio のコンテンツは adk_core::Part::InlineData に対応するため、embedded_context、image、audio の prompt 機能を通知します。session/load ハンドラを登録しているため load_session を通知し、さらに session/fork ハンドラを登録しているため fork session 機能も通知します。session mode と configuration option は、エージェントが SessionControls provider を提供する場合にのみ通知されるため、提供しないエージェントはどちらも通知しません。remote transport、model selector、および experimental protocol の追加は通知されないままです。サーバーが通知していない content type を含む prompt は、部分的に処理されるのではなく、説明的な error で拒否されます。呼び出し側は、すべての ACP 実装が同じ表面を持つと仮定するのではなく、交渉済みの capability object に基づいて設計する必要があります。