> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mibyanai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ACP Internals

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

The ACP adapter wraps Mibyan' 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

```text theme={null}
mibyan acp / mibyan-acp / python -m acp_adapter
  -> acp_adapter.entry.main()
  -> parse --version / --check / --setup before server startup
  -> load ~/.mibyan/.env
  -> configure stderr logging
  -> construct MibyanACPAgent
  -> acp.run_agent(agent, use_unstable_protocol=True)
```

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

## Major components

### `MibyanACPAgent`

`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`

Every ACP tool call reaches a terminal status: `tool.completed` closes the call with its own
result (`completed` / `failed`), the `step_callback` `prev_tools` pass is only a fallback for
runtimes that never project a completion, and anything still open when the turn ends —
a denied or blocked call, an interrupted one — is marked `failed` before the response is
returned.

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

```python theme={null}
asyncio.run_coroutine_threadsafe(...)
```

### Permission bridge

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

Mapping:

* `allow_once` -> Mibyan `once`
* `allow_always` -> Mibyan `always`
* reject options -> Mibyan `deny`

Timeouts and bridge failures deny by default.

### Tool rendering helpers

`acp_adapter/tools.py` maps Mibyan 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

```text theme={null}
new_session(cwd)
  -> create SessionState
  -> create AIAgent(platform="acp", enabled_toolsets=<_get_platform_tools(config, "acp"), as on the
                   gateway: platform_toolsets.acp (default mibyan-acp) plus the resolver's extras
                   such as plugin toolsets, with its admitted MCP servers keyed mcp-<server>>,
                   disabled_toolsets=<agent.disabled_toolsets>)
  -> 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
```

A turn that ends in a terminal failure (provider refusal, non-retryable error, exhausted
retries, interrupt before any reply) is closed by the core loop with a Mibyan-authored
assistant row ("Your request was not processed…" / "This turn did not complete…") so the
durable transcript never ends on an open `user` row. Without it the next prompt would be
merged into the failed request and replayed. Context-overflow failures are exempt: their
repair is session rotation, not another row.

### 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

ACP does not implement its own auth store.

Instead it reuses Mibyan' runtime resolver:

* `acp_adapter/auth.py`
* `mibyan_cli/runtime_provider.py`

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

## 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:

* 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

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

* ACP sessions are persisted to the shared `~/.mibyan/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

## Related files

* `tests/acp_adapter/` — ACP test suite
* `toolsets.py` — `mibyan-acp` toolset definition
* `mibyan_cli/main.py` — `mibyan acp` CLI subcommand
* `pyproject.toml` — `[acp]` optional dependency + `mibyan-acp` script


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.