Skip to content

ACP 協議

源码版本v2026.7.20

職責

ACP(Agent Client Protocol)是編輯器/IDE 與 agent 通訊的標準協議。acp_adapter/ 把 Hermes 暴露為 ACP server,讓支援 ACP 的客戶端(Zed、VS Code 擴充功能等)能直接驅動 Hermes:管理會話、讀寫資源(檔案/圖片)、審批編輯、追溯來源(provenance)、按權限隔離工具 (tool)。這讓 Hermes 不止於訊息平台,也能嵌入開發工作流。

設計動機

Hermes 原本為訊息平台設計——網關層 (gateway layer) 接 Telegram/Discord 這類長會話。但 IDE 是另一回事:工作目錄是編輯器開的,cwd 要跟著編輯器走;改檔案不能 agent 說改就改,得彈到使用者面前過一遍;會話之間還要能追溯「這條壓縮 (compression) 自哪條」。ACP 這層就是把這些 IDE 特有約束翻譯成 Hermes 已有的原語。程式碼裡沒有重寫一套 agent 迴圈,而是把 ACP 訊息流接到 run_conversation,把 ACP 資源轉成 OpenAI content parts,把工具呼叫裡的寫檔案操作改造成 EditProposal 走人審。核心是「適配,不是重寫」。

關鍵檔案

資料流

  1. ACP 客戶端(編輯器)按 acp_registry/agent.json 發現並啟動 Hermes ACP server(acp_adapter/__main__.py)。
  2. 客戶端發起會話 → SessionManager:175 建立 SessionState,對齊 cwd(acp_adapter/session.py:29)、展開 toolsets(acp_adapter/session.py:129)。
  3. 客戶端發訊息/資源 → 資源轉換:201 把 ACP resource(檔案/圖片,受 acp_adapter/server.py:96 大小限制)轉成 OpenAI content parts,餵給 run_conversation:588
  4. agent 想改檔案時,工具呼叫經 build_edit_proposal:178 變成 EditProposal,經審批請求器(acp_adapter/edit_approval.py:51)彈給使用者確認。
  5. 工具執行受 acp_adapter/permissions.py 權限管控;每次操作經 acp_adapter/provenance.py:22 記 provenance。
  6. 串流 (stream) 輸出與事件(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 展示能看到「之前/之後」,而不是盲改:

python
@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 預設走 ask 而非 workspace_session,避免被「整個工作區都信任」的策略誤放行。

provenance 是 IDE 場景特有:訊息平台裡會話是線性線,IDE 裡會話會被壓縮、分叉、resume。build_session_provenance 沿 parent_session_id 往上走,數 end_reason == 'compression' 的層數,標出 sessionKindcompressionDepth,把內部 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(人審編輯)。和網關 (gateway) 層互補——網關接訊息平台,ACP 接 IDE。

非官方社群學習站,內容以 MIT 授權的 NousResearch/hermes-agent 原始碼為依據。