ACP (Agent Client Protocol)
Castellan ships an ACP v1 stdio agent via castellan acp. Editors such as Zed can spawn Castellan as an external coordination agent — scheduler-primary runs that produce episodes, not chat transcripts.
MCP remains the primary Cursor integration path. See Cursor setup.
Capabilities
| Method | Status |
|---|---|
initialize | Protocol v1, camelCase agent capabilities |
session/new | Binds sessionId → castellan-memory acp_sessions |
session/fork | Fork session with parent lineage (parentSessionId persisted) |
session/prompt | Runs CastellanEngine + persist_episode_bundle; emits session/update stream |
session/resume | Restores checkpoint metadata (no chat replay) |
session/load | Replays episode metadata via session/update notifications |
session/cancel | Aborts in-flight prompt task |
session/close | Cancels + marks session closed |
permissions/request | Governance pipeline; returns needs_prompt for Prompt mode (editor UI). Set CASTELLAN_ACP_AUTO_DENY=1 in CI |
prompt | Deprecated alias for session/prompt |
Phase 3 (MOAT): mux-by-default when socket healthy; session/fork for parent-child lineage; EpisodeCheckpoint saved on every prompt.
Diagnostics
castellan acp doctor
Prints protocol version, agent capabilities, memory backend, mux health (mux_default_on, mux_effective, mux_socket_healthy), and env flags (CASTELLAN_MUX_AUTO, CASTELLAN_MUX_DISABLE, CASTELLAN_ACP_AUTO_DENY).
Zed smoke (5 steps)
- Build Castellan:
cargo build --release -p castellan-cli - Copy examples/zed-acp.json into your Zed settings agents list (adjust
commandpath). - Open a workspace with a
.castellan/directory (or let Castellan create one on first prompt). - Start the Castellan agent in Zed and send:
reach targetwith context plugingridworld. - Confirm the agent returns
stopReason: completed, ≥3session/updatenotifications, and.castellan/episodes/<goal_id>.jsonexists.
Mux episodes
Mux is the default when the multiplexer socket is healthy. Explicit "mux": true in prompt context forces mux; "mux": false opts out. Rollback env vars: CASTELLAN_MUX_AUTO=0 or CASTELLAN_MUX_DISABLE=1. ACP attaches pane_tree to persisted episodes for evolve flywheel compatibility.
Session fork
{"jsonrpc":"2.0","id":2,"method":"session/fork","params":{"sessionId":"<parent-id>"}}
Returns { "sessionId": "<child-id>", "parentSessionId": "<parent-id>" }. Child inherits cwd, plugin, and latest goal from parent.
Failure paths
| Symptom | Cause | Fix |
|---|---|---|
session/prompt hangs | No .castellan/ dir writable, or plugin missing | Run castellan doctor first; confirm --plugin name via castellan plugin list |
permissions/request always denied | CASTELLAN_ACP_AUTO_DENY=1 set (CI default) | Unset for interactive use, or handle the request explicitly in the editor |
Prompted MCP tools denied mid-session/prompt | Engine path uses headless prompter (fail closed) | Editor should approve via permissions/request, or set CASTELLAN_PERMISSION_PROMPT=allow for trusted CI, or mark tools allow in config |
session/load returns no messages | By design — episode metadata only, no chat replay | See Limitations below; use castellan replay --episode <path> for full JSON |
| Mux not attaching panes | Socket unhealthy | castellan acp doctor → check mux_socket_healthy; castellan multiplexer ensure |
Limitations
- No full chat transcript replay on
session/load— episode metadata only (MEMORY_ARCHITECTURE). - External editor MCP servers are bridged for
castellan_*tools only in Phase 2; shell/file tools remain editor-side. - crates.io publish for library crates is dry-run only until the API stabilizes.