Agent Control Protocol (ACP)
Agent Harbor implements the Agent Control Protocol (ACP) for standardized communication between IDEs, CLI tools, and AI coding agents.
Overview
ACP is a JSON-RPC 2.0 based protocol that standardizes how clients communicate with AI coding agents. Agent Harbor acts as an access point (server) that:
- Routes sessions to downstream ACP-compliant agents
- Provides sandboxed execution environments
- Manages filesystem snapshots and workspaces
- Exposes Harbor-specific extensions for time-travel and branching
Roles and Transports
Access Point (Server): ah agent access-point exposes ACP over Unix domain socket and stdio. It routes sessions to downstream ACP agents and rewrites model lists with per-agent prefixes.
Client Tunnel: ah acp is a thin stdio/UDS/WebSocket tunnel used by IDEs and CLIs. It keeps stdout JSON-only and logs to files.
Commands
ah acp
Connect to an ACP access point:
ah acp [OPTIONS]Options:
--endpoint <URL|PATH>: Access point WS URL or UDS path (defaults to platform ACP socket path)--ws: Force WebSocket transport--uds: Force Unix socket transport--remote-server <URL>: Target Harbor REST server (resolves to<url>/acp/v1/connect)--session <ID>: Load and attach to an existing ACP session--daemonize <MODE>: Behavior when no access point is running:auto(default): Start daemon with idle timeout if missingnever: Run inline; no multi-client reusedisabled: Fail if no access point is running
--idle-timeout <SECS>: Idle shutdown timer when daemonized (default: 86400)
Examples:
# Use local default UDS; auto-start daemon if missing
ah acp
# Connect to remote WS access point
ah acp --endpoint wss://ah.example.com/acp/v1/connect
# Bridge to REST server without daemon auto-start
ah acp --remote-server https://ah.example.com --daemonize disabledah agent access-point
Run a local access point daemon:
ah agent access-point [OPTIONS]Options:
--acp-uds <PATH>: Enable ACP over Unix domain socket at PATH--acp-ws <yes|no>: Enable ACP over WebSocket at/acp/v1/connect(default: yes)--acp-agent-cmd <CMD>: Command to launch an ACP agent
Session Lifecycle
Session Creation
When a client sends session/new:
- Access point selects the downstream agent (by model prefix or default)
- Prepares a writable workspace using the filesystem snapshot system:
- Provider chosen automatically (ZFS, Btrfs, AgentFS, or Git)
- Working copy mounted so agent sees original repo path (CoW overlay) when supported
- Cleanup token recorded for teardown
- Session state stored: snapshot provider, working copy mode, exec path, cleanup token, sandbox policy
Sandboxed Execution
Commands from downstream agents run inside Harbor’s sandbox:
- Process isolation with PID limits
- Network disabled by default (opt-in via config)
- Filesystem illusion: paths match user’s repo path
- Build caches mounted read-only unless explicitly allowed
Command Execution
When the downstream agent sends terminal/create:
- Access point intercepts the request
- Command launched via Passthrough recorder inside session sandbox
- PTY output and metadata captured
- Client receives a follower command to attach to the session
- Multiple followers can attach simultaneously
- Exit codes come from the sandboxed process
Clean Shutdown
On client disconnect or idle timeout:
- All sandboxed terminals/processes terminated
- Workspace cleaned up via stored cleanup token
- Socket listeners closed; stale sockets removed on next launch
Model Discovery & Routing
On startup, the access point:
- Probes each downstream agent (
initialize+session/newprobe) - Collects their
availableModels - Advertises combined list with agent name prefixes (e.g.,
opencode/grok-code-fast-1)
When a client requests a prefixed model, the access point routes to that agent and strips the prefix before forwarding.
Harbor Extensions
Agent Harbor extends ACP with custom methods under the _ah/* namespace. These are advertised during initialize via the _meta.agent.harbor capability block.
Capability Advertisement
{
"agentCapabilities": {
"loadSession": true,
"_meta": {
"agent.harbor": {
"snapshots": {
"version": 1,
"supportsTimelineSeek": true,
"supportsBranching": true,
"supportsFollowPlayback": true
},
"pipelineIntrospection": {
"version": 1,
"supportsStepStreaming": true
},
"workspace": {
"version": 1,
"supportsDiffs": true
}
}
}
}
}Workspace Methods
_ah/workspace/info: Returns metadata about the Harbor-managed workspace (provider, working copy mode, exec path, disk usage).
_ah/workspace/list: Browse the workspace tree with optional filters (recursive, modifiedOnly).
_ah/workspace/diff: Fetch file diffs in unified format.
_ah/workspace/file: Fetch file metadata and content.
Snapshot Methods
_ah/snapshot_create: Create a manual snapshot of the current workspace with optional label and anchor.
_ah/snapshot_list: List snapshots with filtering (branchable, provider, createdAfter).
Branching Methods
_ah/branch_create: Create a new session from an existing snapshot or timeline moment. Supports launching multiple agents per branch.
_ah/branch_list, _ah/branch_delete: Enumerate and remove branches.
_ah/session_seek: Mount a read-only filesystem view for exploration at a specific snapshot.
Pipeline Introspection
_ah/tool_pipeline_list: Returns pipelines and steps detected for a specific execution.
_ah/tool_pipeline_stream: Stream stdout/stderr for a specific pipeline step with optional follow mode.
Multi-Agent Sessions
_ah/session/new: Launch multiple agents from one request. Each agent gets its own isolated ACP session.
Notifications
Harbor sends real-time notifications via session/update:
| Notification | Purpose |
|---|---|
harbor/snapshot_created | Snapshot captured (auto or manual) |
harbor/branch_created | New branch and sessions created |
harbor/branch_updated | Branch status changed (running, paused, merged) |
harbor/branch_deleted | Cleanup confirmation |
harbor/timeline_checkpoint | Recorder event for timeline markers |
harbor/pipeline_detected | New pipeline recorded |
harbor/pipeline_step_updated | Pipeline step progress update |
Configuration
ACP settings in ah.toml or environment:
| Key | Description |
|---|---|
acp.daemonize | auto (default), never, or disabled |
acp.socket-path | Unix socket path for access point |
acp.ws-url | WebSocket URL for access point |
acp.transport | websocket (default) or stdio |
Event Pipeline
For ACP agents in TaskManager context, events flow through a direct semantic path:
ACP Agent stdout (JSON-RPC)
│
▼
AcpAgentSession
│ Parses JSON-RPC directly
▼
acp_message_to_task_events()
│ Converts to TaskEvents
▼
TaskManagerMessage::SessionEvent
│
▼
LocalTaskManager / RestTaskManagerEnable with --task-manager-socket:
ah agent start --task-manager-socket /path/to/socketThis provides semantic events extracted directly from JSON-RPC without PTY parsing.