ACP-Protokoll
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
server.py Kopf:1-92— "ACP agent server — exposes Hermes Agent via the Agent Client Protocol"Ressourcen-Handling:96-150—_MAX_ACP_RESOURCE_BYTES,_resource_display_name,_is_text_resource/_is_image_resourceRessourcen-Text/Bild-Konvertierung:201-296—_format_resource_text/_resource_link_to_parts/_image_data_url(Ressource → OpenAI-Content-Parts)SessionState / SessionManager:159-175— ACP-Sitzungszustand und -Verwaltungcwd-Übersetzung:29-62—_translate_acp_cwd/_normalize_cwd_for_compare(Arbeitsverzeichnis des Editors ausrichten)Toolsets-Expansion:129-159—_expand_acp_enabled_toolsetsclass EditProposal:26-51— Edit-Vorschlag (Datei schreiben / Patch)build_edit_proposal:178-220— baut aus einem Werkzeugaufruf einen Vorschlag (write_file / patch_replace / patch_v4a)Approval-Requester:51-69—set_edit_approval_requester/ Token-Mechanismuspermissions.py— Werkzeug-Berechtigungsisolationprovenance:22-111—build_session_provenance/session_provenance_meta(Aktionen-Provenance)auth.py/entry.py/events.py__main__.py— ACP-Server-Starteinstieg (5 Zeilen)acp_registry/agent.json— Agent-Metadaten-Manifest (für Client-Discovery)acp_registry/icon.svg— Icon
Datenfluss
- Ein ACP-Client (Editor) entdeckt via
acp_registry/agent.jsonund startet den Hermes-ACP-Server (acp_adapter/__main__.py). - Der Client öffnet eine Sitzung →
SessionManager:175erzeugt eineSessionState, richtet cwd aus (acp_adapter/session.py:29) und klappt die Toolsets auf (acp_adapter/session.py:129). - Der Client sendet Nachrichten/Ressourcen →
Ressourcen-Konvertierung:201wandelt die ACP-Ressource (Datei/Bild, beschränkt durchacp_adapter/server.py:96) in OpenAI-Content-Parts und füttertrun_conversation:588. - Will der Agent eine Datei ändern, wird aus dem Werkzeugaufruf über
build_edit_proposal:178einEditProposal, das über den Approval-Requester (acp_adapter/edit_approval.py:51) dem Nutzer zur Bestätigung vorgelegt wird. - Die Werkzeugausführung wird durch
acp_adapter/permissions.pyberechtigt; jede Aktion wird überacp_adapter/provenance.py:22als Provenance festgehalten. - 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:
@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.jsonnagelthermes-agent[acp]==0.19.0fest. 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_backendeine neue Windows-Pfadform nicht abgedeckt, bekommt der Agent einen cwd, der nicht passt; allePath-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 nachbuild_edit_proposalendlos. Ob der Cancel auf Protokollebene dieses Warten erreicht, hängt davon ab, obevents.pyden Abbruch-Pfad abdeckt. - Provenance-Kette abgebrochen: Wird beim Kompressions-Split
parent_session_idfalsch geschrieben, kehrtbuild_session_provenancean der Bruchstellerootzurü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.