Skip to content

ACP-Protokoll

源码版本v2026.7.20

Verantwortung

ACP (Agent Client Protocol) ist das Standardprotokoll, über das Editor/IDE mit dem Agenten kommunizieren. acp_adapter/ stellt Hermes als ACP-Server bereit, sodass ACP-fähige Clients (Zed, VS-Code-Erweiterungen u. a.) Hermes direkt antreiben können: Sitzungen (sessions) verwalten, Ressourcen (Dateien/Bilder) lesen/schreiben, Edits genehmigen, Provenance nachverfolgen, Werkzeuge (tools) nach Berechtigungen isolieren. Damit ist Hermes nicht nur Nachrichtenplattform, sondern auch in Entwickler-Workflows eingebettet.

Designmotiv

Hermes war ursprünglich für Nachrichtenplattformen entworfen — die Gateway-Schicht (gateway layer) dockt lange Konversationen wie Telegram/Discord an. Eine IDE ist aber etwas anderes: Das Arbeitsverzeichnis wird vom Editor geöffnet, cwd muss dem Editor folgen; eine Datei darf nicht einfach vom Agenten geändert werden, sondern muss dem Nutzer vorgelegt werden; zwischen Sitzungen muss sich nachverfolgen lassen, «diese wurde aus welcher komprimiert». Die ACP-Schicht übersetzt diese IDE-spezifischen Zwänge in bereits vorhandene Hermes-Primitiven. Der Code schreibt die Agent-Schleife nicht neu, sondern bindet den ACP-Nachrichtenstrom an run_conversation, wandelt ACP-Ressourcen in OpenAI-Content-Parts um und formt den Datei-schreibenden Werkzeugaufruf in eine EditProposal mit menschlicher Prüfung um. Kern ist «adaptieren, nicht neu schreiben».

Schlüsseldateien

Datenfluss

  1. Ein ACP-Client (Editor) entdeckt via acp_registry/agent.json und startet den Hermes-ACP-Server (acp_adapter/__main__.py).
  2. Der Client öffnet eine Sitzung → SessionManager:175 erzeugt eine SessionState, richtet cwd aus (acp_adapter/session.py:29) und klappt die Toolsets auf (acp_adapter/session.py:129).
  3. Der Client sendet Nachrichten/Ressourcen → Ressourcen-Konvertierung:201 wandelt die ACP-Ressource (Datei/Bild, beschränkt durch acp_adapter/server.py:96) in OpenAI-Content-Parts und füttert run_conversation:588.
  4. Will der Agent eine Datei ändern, wird aus dem Werkzeugaufruf über build_edit_proposal:178 ein EditProposal, das über den Approval-Requester (acp_adapter/edit_approval.py:51) dem Nutzer zur Bestätigung vorgelegt wird.
  5. Die Werkzeugausführung wird durch acp_adapter/permissions.py berechtigt; jede Aktion wird über acp_adapter/provenance.py:22 als Provenance festgehalten.
  6. Streaming-Output (streaming output) und Events (acp_adapter/events.py) werden an den Client zurückgesendet.

acp_registry/agent.json ist die Visitenkarte, die der Client beim ersten Kennenlernen von Hermes sieht: Version, Distributionsform (uvx), Startbefehl. Diese Vertragsschicht muss mit dem tatsächlichen Binärformat übereinstimmen, sonst installiert der Client eine falsche Version und es läuft nicht.

cwd-Übersetzung ist die größte Stolperfalle im ACP-Szenario: Ein Windows-Client lässt Hermes in WSL laufen, der Workspace ist aber E:\Projects oder ein UNC-Pfad \\wsl.localhost\.... _translate_acp_cwd vereinheitlicht das zu POSIX, sonst passen alle Path-Operationen im Agenten nicht zusammen.

Edit-Vorschläge sind frozen dataclasses; entscheidend ist old_text_proposal_for_write_file liest zuerst den bestehenden Dateiinhalt, sodass der Diff «vorher/nachher» zeigt statt blind zu ändern:

python
@dataclass(frozen=True)
class EditProposal:
    tool_name: str
    path: str
    old_text: str | None
    new_text: str
    arguments: dict[str, Any]

Der Approval-Requester ist über ein ContextVar gebunden, nicht über eine globale Variable; mehrere parallele ACP-Sitzungen haben je ihren eigenen Requester und stören sich nicht. .env / id_rsa gehen standardmäßig über ask statt workspace_session, damit sie nicht von einer «dem gesamten Workspace vertrauen»-Strategie versehentlich freigegeben werden.

Provenance ist IDE-spezifisch: In Nachrichtenplattformen sind Sitzungen linear; in der IDE werden Sitzungen komprimiert, abgespalten und resumpt. build_session_provenance läuft entlang parent_session_id nach oben, zählt die Ebenen mit end_reason == 'compression', markiert sessionKind und compressionDepth und legt die interne Hermes-Session-ID zusammen mit der äußeren ACP-Session-ID in _meta.hermes.sessionProvenance.

Grenzen und Fehler

  • Handshake-Version passt nicht: agent.json nagelt hermes-agent[acp]==0.19.0 fest. Steigt Hermes auf 0.20, hat der Client noch das alte Manifest im Cache und Server und Client-Schema passen nicht zusammen; fehlt im InitializeResponse ein Feld, schlägt der Handshake fehl.
  • WSL-cwd-Übersetzung übersehen: Hat translate_cwd_for_wsl_backend eine neue Windows-Pfadform nicht abgedeckt, bekommt der Agent einen cwd, der nicht passt; alle Path-Operationen laufen schief — aber das bricht nicht sofort, sondern explodiert erst beim ersten Datei-Schreiben mit «Verzeichnis nicht gefunden».
  • Approval-Requester verklemmt: Freigabe läuft über ContextVar + Nutzer-Callback; bleibt der Client-Event-Loop hängen und schickt keinen ACK, hängt das Warten nach build_edit_proposal endlos. Ob der Cancel auf Protokollebene dieses Warten erreicht, hängt davon ab, ob events.py den Abbruch-Pfad abdeckt.
  • Provenance-Kette abgebrochen: Wird beim Kompressions-Split parent_session_id falsch geschrieben, kehrt build_session_provenance an der Bruchstelle root zurück; der Client zeigt eine Continuation als neue Sitzung, und die Historie wirkt «verloren».

Zusammenfassung

ACP bettet Hermes in Editor-Workflows ein: Sitzungsverwaltung, Ressourcen-Lesen/Schreiben, Edit-Genehmigung, Berechtigungs-Isolation, Provenance. Der Kern ist server.py (Protokoll-Adapter (adapter)) + session.py (Sitzung) + edit_approval.py (menschliche Edit-Prüfung). Komplementär zum Gateway – das Gateway bindet Nachrichtenplattformen an, ACP bindet die IDE an.

Inoffizielle Community-Lernseite. Basiert auf dem MIT-lizenzierten NousResearch/hermes-agent-Quellcode.