Academy → Developer GuideOfficial documentation · Arabic guidance

ACP Internals

بنية ACP من الداخل

Advanced3 min readLesson 21 question✓ 2026-08-18
Before you read

What this page is, and what it holds.

This page covers ACP Internals. You will use hermes acp here; about 3 minutes to read. An interface exposed on the network needs authentication, even on your own machine.

9sections
3code examples
0tables
1commands
576source words
The official one-line description

How the ACP adapter works: lifecycle, sessions, event bridge, approvals, and tool rendering

What you will be able to do

Outcomes taken from this page, not a template.

  • Understand what التشغيل البرمجي is and when you need it.
  • Run hermes acp and understand what happens next.
  • Know the common mistake before you hit it.
Identifiers you will meet

Exactly as they appear in Hermes.

Commands
  • hermes acp
Page map

Jump to the part you need.

  1. 01Boot flow
  2. 02Major components
  3. 03Session lifecycle
  4. 04Provider/auth behavior
  5. 05Working directory binding
  6. 06Duplicate same-name tool calls
  7. 07Approval callback restoration
  8. 08Current limitations
  9. 09Related files
The full official page

Nothing summarised away.

The documentation body below is reproduced from the official source so commands and identifiers stay exact. Each section carries a short note describing what it contains.

The ACP adapter wraps Hermes' synchronous AIAgent in an async JSON-RPC stdio server.

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

Boot flow

Commands you type in a terminal. Understand what one does before copying it. Commands here: hermes acp.

Text7 lines
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)

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

Major components

Explains the idea itself. Read it slowly; the later sections build on it.

HermesACPAgent

acp_adapter/server.py implements the ACP agent protocol.

Responsibilities:

  • initialize / authenticate
  • new/load/resume/fork/list/cancel session methods
  • prompt execution
  • session model switching
  • wiring sync AIAgent callbacks into ACP async notifications

SessionManager

acp_adapter/session.py tracks live ACP sessions.

Each session stores:

  • session_id
  • agent
  • cwd
  • model
  • history
  • cancel_event

The manager is thread-safe and supports:

  • create
  • get
  • remove
  • fork
  • list
  • cleanup
  • cwd updates

Event bridge

acp_adapter/events.py converts AIAgent callbacks into ACP session_update events.

Bridged callbacks:

  • tool_progress_callback
  • thinking_callback (currently set to None in the ACP bridge — reasoning is forwarded through step_callback instead)
  • step_callback

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

Python1 line
asyncio.run_coroutine_threadsafe(...)

Permission bridge

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

Mapping:

  • allow_once -> Hermes once
  • allow_always -> Hermes always
  • reject options -> Hermes deny

Timeouts and bridge failures deny by default.

Tool rendering helpers

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

Examples:

  • patch / write_file -> file diffs
  • terminal -> shell command text
  • read_file / search_files -> text previews
  • large results -> truncated text blocks for UI safety

Session lifecycle

Explains the idea itself. Read it slowly; the later sections build on it.

Text12 lines
new_session(cwd)
  -> create SessionState
  -> create AIAgent(platform="acp", enabled_toolsets=["hermes-acp"])
  -> bind task_id/session_id to cwd override

prompt(..., 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):

  • sets the session cancel event
  • calls agent.interrupt() when available
  • causes the prompt response to return 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.

Provider/auth behavior

Explains the idea itself. Read it slowly; the later sections build on it.

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 ACP clients can open Hermes' interactive model/provider configuration before starting a normal ACP session.

Working directory binding

Explains the idea itself. Read it slowly; the later sections build on it.

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

Explains the idea itself. Read it slowly; the later sections build on it.

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

  • parallel same-name calls
  • repeated same-name calls in one step

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

Approval callback restoration

Explains the idea itself. Read it slowly; the later sections build on it.

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

Explains the idea itself. Read it slowly; the later sections build on it.

  • ACP sessions are persisted to the shared ~/.hermes/state.db (SessionDB) and transparently restored across process restarts; they appear in session_search
  • non-text prompt blocks are currently ignored for request text extraction
  • editor-specific UX varies by ACP client implementation
Knowledge check

1 question answered by this page alone.

Every option is a real identifier from the Hermes documentation. The wrong ones are real too, just from other pages.

1. Which of these headings does not appear in this lesson?