Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ npm run lint:fix # biome check --write
- `src/core/types.ts` — Core interfaces (AgentAdapter, AgentSession, etc.)
- `src/adapters/claude-code.ts` — Claude Code adapter (reads ~/.claude/, cross-refs PIDs)
- `src/adapters/codex.ts` — Codex CLI adapter (reads ~/.codex/sessions/, cross-refs PIDs)
- `src/adapters/codex-acp.ts` — Codex via ACP transport (uses @zed-industries/codex-acp bridge)
- `src/adapters/acp/acp-client.ts` — Generic ACP client (spawns agent, manages connection via ACP SDK)
- `src/adapters/acp/acp-adapter.ts` — Generic ACP-backed AgentAdapter implementation
- `src/adapters/openclaw.ts` — OpenClaw gateway adapter (WebSocket RPC)
- `src/adapters/opencode.ts` — OpenCode adapter (reads ~/.local/share/opencode/storage/, cross-refs PIDs)
- `src/adapters/pi.ts` — Pi coding agent adapter (reads ~/.pi/, cross-refs PIDs)
Expand Down
85 changes: 85 additions & 0 deletions docs/adr/adr-001-agentctl-adopts-acp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
title: "ADR-001 — agentctl adopts ACP as primary agent interface"
date: 2026-03-09
status: accepted
deciders: Charlie
tags: [type/adr, domain/agentctl]
---

# ADR-001: agentctl adopts ACP as primary agent interface

## Status
**Accepted** — 2026-03-09

## Context

agentctl (v1.6.0) currently maintains bespoke adapters for each coding agent runtime: Claude Code, Codex, OpenCode, Pi, Pi Rust. Each adapter handles launch, resume, PTY management, output parsing, and lifecycle detection independently. This approach has worked but creates a growing maintenance burden — every new runtime needs a new adapter, and each adapter re-solves the same problems (session management, structured output, permission mediation, crash recovery).

Meanwhile, the **Agent Client Protocol (ACP)** has emerged as a standard for structured agent-to-agent communication, and **ACPx** (github.com/openclaw/acpx) provides a mature headless ACP client runtime with persistent sessions, cooperative cancel, filesystem/terminal callbacks, and a growing registry of ACP-capable agent bridges.

Research ([acpx-vs-agentctl analysis](obsidian://open?vault=My%20Notes&file=Projects%2Fresearch%2Facpx-vs-agentctl)) confirms:
- ACPx handles the **transport/session/protocol layer** well (structured JSON-RPC, no PTY scraping)
- agentctl's differentiation is the **supervision/orchestration layer** (daemon, fleet discovery, worktrees, locks, fuses, metrics, event routing)
- There is meaningful overlap in launch/resume/lifecycle plumbing that should not be maintained in two places

## Decision

**agentctl will adopt ACP as its primary agent interface strategy.**

### Principles

1. **Ride on ACP, don't fight it.** agentctl's CLI and internal APIs should align with ACP primitives (sessions, prompts, cancel, permissions). Where ACP provides a clean abstraction, use it rather than reinventing.

2. **Adapters become thin ACP integration layers.** For agents with existing ACP bridges (Claude Code, Codex, OpenCode, Pi), adapters should delegate launch/session/lifecycle to ACP (via ACPx or direct ACP client) and only add agentctl-specific concerns (locks, metrics, hooks, worktree management).

3. **Build ACP clients for harnesses that lack them.** If a runtime doesn't have an ACP bridge, agentctl's contribution is to build one — potentially releasing it upstream or as a standalone package — rather than building yet another bespoke PTY-scraping adapter.

4. **Supervision stays in agentctl.** ACP/ACPx handles single-session lifecycle. agentctl handles multi-session fleet supervision: daemon, discovery, worktree orchestration, locks, fuses, metrics, webhooks, and operator UX. This is the durable differentiation.

5. **Contribute upstream where it benefits the ecosystem.** Generic improvements to ACP session management, error handling, or agent bridges should be contributed to ACPx or relevant ACP adapter repos rather than kept proprietary.

### What changes

| Area | Before | After |
|------|--------|-------|
| Agent launch/resume | Each adapter implements PTY spawn + output parsing | Delegate to ACP session (via ACPx or embedded ACP client) |
| Structured output | PTY scraping + regex | ACP JSON-RPC stream |
| Session persistence | agentctl-managed state files | ACP session model (ACPx handles persistence) |
| Permission mediation | N/A (PTY auto-approve or manual) | ACP permission callbacks with policy |
| New runtime support | Write a full adapter (~500-800 LOC) | Write or find an ACP bridge (~100-200 LOC), thin agentctl config |
| Crash recovery | Per-adapter process detection | ACP reconnect / session load |

### What stays the same

- Daemon supervision architecture
- Fleet discovery (`agentctl list`)
- Worktree management and sweeps
- Directory locks and fuses
- Prometheus metrics
- Webhook/callback hooks
- OrgLoop integration
- CLI UX and operator experience

## Consequences

**Positive:**
- Dramatically reduced adapter maintenance surface
- Structured agent output without PTY scraping
- New runtime support becomes trivial (find/build ACP bridge, add config)
- Better crash recovery via ACP session model
- Community alignment — contributing to ACP ecosystem instead of maintaining parallel infrastructure

**Negative:**
- ACP/ACPx is still alpha — API surface may shift
- Temporary dual-path: existing adapters work today, ACP migration is incremental
- Dependency on external project for protocol layer (mitigated: ACPx is MIT, we can fork if abandoned)

**Risks:**
- ACPx development could stall (mitigation: agentctl can embed ACP client directly)
- ACP protocol may not cover all edge cases bespoke adapters handle today (mitigation: contribute missing capabilities upstream)

## References
- [ACPx vs agentctl analysis](obsidian://open?vault=My%20Notes&file=Projects%2Fresearch%2Facpx-vs-agentctl)
- [ACPx repo](https://github.com/openclaw/acpx)
- [ACP specification](https://github.com/AgenClientProtocol/acp)
- [agentctl repo](https://github.com/OrgLoop/agentctl)
20 changes: 20 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"node": ">=20"
},
"dependencies": {
"@agentclientprotocol/sdk": "^0.14.1",
"@types/node": "^25.2.3",
"commander": "^14.0.3",
"tsx": "^4.21.0",
Expand Down
Loading