ACP プロトコル
職務
ACP(Agent Client Protocol)はエディタ/IDE と agent が通信する標準プロトコル。acp_adapter/ が Hermes を ACP server として露出し、ACP 対応クライアント(Zed、VS Code 拡張など)が直接 Hermes を駆動できる:セッション (session) 管理、リソース読み書き(ファイル/画像)、編集承認、由来(provenance)の追跡、権限でツールを隔離。これにより Hermes はメッセージプラットフォームにとどまらず、開発ワークフローにも組み込める。
設計動機
Hermes は元々メッセージプラットフォーム向けに設計された——ゲートウェイ (gateway) 層は Telegram/Discord のような長会話を受ける。しかし IDE は別物だ:作業ディレクトリはエディタが開いたもので、cwd はエディタに追従する。ファイル変更は agent が変えると言って変えるのでなく、ユーザーに一回見せなければならない。セッション間では「この圧縮 (compression) はどのセッションから来たか」を追跡できる必要がある。ACP 層はこうした IDE 固有の制約を Hermes 既存のプリミティブに翻訳する。コードは agent ループをもう一セット書き直すのではなく、ACP メッセージストリームを run_conversation に接続し、ACP リソースを OpenAI content parts に変換し、ツール呼び出し (tool dispatch) のファイル書き込みを EditProposal に改造して人審査に回す。核心は「適合であって書き直しではない」ことだ。
主要ファイル
server.py ヘッダ:1-92— "ACP agent server — exposes Hermes Agent via the Agent Client Protocol"リソース処理:96-150—_MAX_ACP_RESOURCE_BYTES、_resource_display_name、_is_text_resource/_is_image_resourceリソース テキスト/画像変換:201-296—_format_resource_text/_resource_link_to_parts/_image_data_url(リソース→OpenAI content parts)SessionState / SessionManager:159-175— ACP セッション状態と管理cwd 翻訳:29-62—_translate_acp_cwd/_normalize_cwd_for_compare(エディタ作業ディレクトリの整列)toolsets 展開:129-159—_expand_acp_enabled_toolsetsclass EditProposal:26-51— 編集提案(ファイル書き / patch)build_edit_proposal:178-220— ツール呼び出しから提案を構築(write_file / patch_replace / patch_v4a)承認リクエスタ:51-69—set_edit_approval_requester/ token 機構permissions.py— ツール権限隔離provenance:22-111—build_session_provenance/session_provenance_meta(操作由来追跡)auth.py/entry.py/events.py__main__.py— ACP server 起動入口(5 行)acp_registry/agent.json— agent メタデータマニフェスト(クライアント発見用)acp_registry/icon.svg— アイコン
データフロー
- ACP クライアント(エディタ)が
acp_registry/agent.jsonで Hermes ACP server を発見し起動(acp_adapter/__main__.py)。 - クライアントがセッションを開始 →
SessionManager:175がSessionStateを生成、cwd を整列(acp_adapter/session.py:29)、toolsets を展開(acp_adapter/session.py:129)。 - クライアントがメッセージ/リソースを送る →
リソース変換:201が ACP resource(ファイル/画像、acp_adapter/server.py:96のサイズ制限付き)を OpenAI content parts に変換し、run_conversation:588に渡す。 - agent がファイルを変更したいとき、ツール呼び出しは
build_edit_proposal:178でEditProposalになり、承認リクエスタ(acp_adapter/edit_approval.py:51) でユーザーに確認を求める。 - ツール実行は
acp_adapter/permissions.pyの権限管理に従う。各操作はacp_adapter/provenance.py:22で provenance を記録する。 - ストリーミング出力とイベント(
acp_adapter/events.py) をクライアントに返す。
acp_registry/agent.json はクライアントが初めて Hermes を見るときの名刺だ:バージョン、配布方式(uvx)、起動コマンド。この層の契約は実際のバイナリと揃っていなければならず、さもないとクライアントが間違ったバージョンを入れて起動しなくなる。
cwd 翻訳は ACP シナリオで最も罠にはまりやすい場所だ:Windows クライアントが Hermes を WSL で走らせ、ワークスペースは E:\Projects や \\wsl.localhost\... の UNC パスだったりする。_translate_acp_cwd がこれを POSIX に統一し、さもないと agent 内のすべての Path 操作が揃わなくなる。
編集提案は frozen dataclass で、鍵は old_text だ——_proposal_for_write_file が既存ファイルの内容を先に読み、diff 表示で「前/後」を見せ、盲変更を避ける。
@dataclass(frozen=True)
class EditProposal:
tool_name: str
path: str
old_text: str | None
new_text: str
arguments: dict[str, Any]承認リクエスタは ContextVar で束縛し、グローバル変数ではない。複数の並行 ACP セッションがそれぞれ自身の requester を持ち、混線しない。.env / id_rsa はデフォルトで workspace_session ではなく ask に回し、「ワークスペース全体を信頼する」ポリシーで誤って通るのを避ける。
provenance は IDE シナリオ特有のものだ:メッセージプラットフォームでは会話は一本の線だが、IDE では圧縮、分岐、resume される。build_session_provenance は parent_session_id を上に辿り、end_reason == 'compression' の層数を数え、sessionKind、compressionDepth をマークし、内部 Hermes session id と対外 ACP session id を _meta.hermes.sessionProvenance に一緒に置く。
境界と失敗
- ハンドシェイクバージョンの不一致:
agent.jsonはhermes-agent[acp]==0.19.0に固定している。Hermes が 0.20 に上がった後、クライアントが古いマニフェストをキャッシュしていると、起動した server とクライアントの schema が合わず、InitializeResponse のフィールドが欠けてハンドシェイクが失敗する。 - WSL cwd 翻訳の抜け:
translate_cwd_for_wsl_backendが新しい Windows パス形式をカバーしていないとき、agent は揃わない cwd を受け取る。すべてのPath操作がずれ、すぐにはエラーを出さず、最初のファイル書き込みで「ディレクトリが見つからない」と炸裂する。 - 承認リクエスタのデッドロック:承認は
ContextVar+ ユーザーコールバックで走る。クライアントのイベントループが詰まって ACK を返さないと、build_edit_proposalの後の待ちがずっと残る。ACP プロトコル層の cancel がこの待ち点にまで伝播するかは、events.pyの中断パスがカバーしているかによる。 - provenance 鎖の切断:圧縮分岐で
parent_session_idを書き間違えると、build_session_provenanceは切れ目に当たった時点でrootを返す。クライアントは continuation を新規セッションと誤表示し、履歴が「消えた」ように見える。
まとめ
ACP は Hermes をエディタワークフローに組み込む:セッション管理、リソース読み書き、編集承認、権限隔離、由来追跡。コアは server.py(プロトコル適合)+ session.py(セッション)+ edit_approval.py(人による編集承認)。ゲートウェイ層と補完的——ゲートウェイはメッセージプラットフォーム、ACP は IDE を接続する。