ACP Internals

The ACP adapter wraps Hermes’ synchronousAIAgentin an async JSON-RPC stdio server.

AIAgent

Key implementation files:

acp_adapter/entry.py acp_adapter/server.py acp_adapter/session.py acp_adapter/events.py acp_adapter/permissions.py acp_adapter/tools.py acp_adapter/auth.py acp_registry/agent.json

Boot flow​

hermes acp / hermes-acp / python -m acp_adapter  -> acp_adapter.entry.main()  -> parse --version / --check / --setup before server startup  -> load ~/.hermes/.env  -> configure stderr logging  -> construct HermesACPAgent  -> acp.run_agent(agent, use_unstable_protocol=True)

The Zed ACP Registry path launches the same adapter throughuvx –from ‘hermes-agent[acp]==' hermes-acp, pointed at thehermes-agentPyPI release.

uvx --from 'hermes-agent[acp]==<version>' hermes-acp hermes-agent

Stdout is reserved for ACP JSON-RPC transport. Human-readable logs go to stderr.

Major components​

HermesACPAgent​

HermesACPAgent

acp_adapter/server.pyimplements the ACP agent protocol.

acp_adapter/server.py

Responsibilities:

SessionManager​

SessionManager

acp_adapter/session.pytracks live ACP sessions.

acp_adapter/session.py

Each session stores:

session_id agent cwd model history cancel_event

The manager is thread-safe and supports:

Event bridge​

acp_adapter/events.pyconverts AIAgent callbacks into ACPsession_updateevents.

acp_adapter/events.py session_update

Bridged callbacks:

tool_progress_callback thinking_callback None step_callback step_callback

BecauseAIAgentruns in a worker thread while ACP I/O lives on the main event loop, the bridge uses:

AIAgent

asyncio.run_coroutine_threadsafe(...)

Permission bridge​

acp_adapter/permissions.pyadapts dangerous terminal approval prompts into ACP permission requests.

acp_adapter/permissions.py

Mapping:

allow_once once allow_always always deny

Timeouts and bridge failures deny by default.

Tool rendering helpers​

acp_adapter/tools.pymaps Hermes tools to ACP tool kinds and builds editor-facing content.

acp_adapter/tools.py

Examples:

patch write_file terminal read_file search_files

Session lifecycle​

new_session(cwd)  -> create SessionState  -> create AIAgent(platform="acp", enabled_toolsets=["hermes-acp"])  -> bind task_id/session_id to cwd overrideprompt(..., session_id)  -> extract text from ACP content blocks  -> reset cancel event  -> install callbacks + approval bridge  -> run AIAgent in ThreadPoolExecutor  -> update session history  -> emit final agent message chunk

Cancelation​

cancel(session_id):

cancel(session_id)

agent.interrupt() stop_reason="cancelled"

Forking​

fork_session()deep-copies message history into a new live session, preserving conversation state while giving the fork its own session ID and cwd.

fork_session()

Provider/auth behavior​

ACP does not implement its own auth store.

Instead it reuses Hermes’ runtime resolver:

acp_adapter/auth.py hermes_cli/runtime_provider.py

So ACP advertises and uses the currently configured Hermes provider/credentials. It also always advertises a terminal setup auth method (hermes-setup, args–setup) so first-run registry clients can open Hermes’ interactive model/provider configuration before starting a normal ACP session.

hermes-setup --setup

Working directory binding​

ACP sessions carry an editor cwd.

The session manager binds that cwd to the ACP session ID via task-scoped terminal/file overrides, so file and terminal tools operate relative to the editor workspace.

Duplicate same-name tool calls​

The event bridge tracks tool IDs FIFO per tool name, not just one ID per name. This is important for:

Without FIFO queues, completion events would attach to the wrong tool invocation.

Approval callback restoration​

ACP temporarily installs an approval callback on the terminal tool during prompt execution, then restores the previous callback afterward. This avoids leaving ACP session-specific approval handlers installed globally forever.

Current limitations​

~/.hermes/state.db session_search

tests/acp/ toolsets.py hermes-acp hermes_cli/main.py hermes acp pyproject.toml [acp] hermes-acp