serveAcpStdio
Run an AcpServer over stdio, bridge HITL permissions, and register capability-gated builtin tools.
serveAcpStdio
serveAcpStdio(app, agentId, options?) is the primary entry point for serving a Maniac agent as an ACP-compliant subprocess. It constructs an AcpServer, wires an AgentSideConnection over ndjson stdio, and blocks until the transport closes.
import { serveAcpStdio } from "@maniac-ai/agents/acp";
await serveAcpStdio(app, "support", {
agentName: "support",
agentTitle: "Maniac Support",
agentVersion: "1.0.0"
});AcpServer lifecycle
AcpServer implements the SDK's Agent interface:
| ACP method | Maniac behavior |
|---|---|
initialize | Captures client capabilities for capability-gated tools |
session/new | Mints a Maniac thread keyed by the session id |
session/prompt | Runs Maniac.chatStream with a per-session TraceTranslator |
session/cancel | Aborts the in-flight prompt via AbortController |
| Permission requests | Bridges to AgentSideConnection.requestPermission; maps outcomes to ApprovalResponse and resumes via Maniac.resumeCheckpoint |
Construct AcpServer directly when you need custom transport wiring:
import { AcpServer } from "@maniac-ai/agents/acp";
const server = AcpServer.create(app, "support");
// hand server to your own AgentSideConnectionTraceTranslator
Each session owns a TraceTranslator that converts Maniac TraceEvents into ACP session/update notifications:
- Token deltas → assistant message chunks
- Tool calls →
tool_callupdates with kind heuristics (read,edit,execute, …) - Finish reasons →
stopReason(end_turn,max_tokens,refusal, …)
Feed every trace event from chatStream through translator.translate(event) and forward the returned notifications to the client.
createTranslatorState() resets per-session bookkeeping (announcedToolCalls, stopReason, …). The same JSON fixtures under packages/agents/tests/acp/fixtures/ exercise both Python and TypeScript translators for cross-language parity.
Capability-gated builtin tools
When the ACP client advertises matching capabilities during initialize, the server auto-registers builtin tools for the duration of each prompt turn:
| Tool | Capability | Purpose |
|---|---|---|
acp_read_text_file | filesystem read | Read workspace files through the client |
acp_write_text_file | filesystem write | Write workspace files through the client |
acp_run_command | terminal | Run shell commands in the client's environment |
These tools require an active ACP client context (withAcpClientContext / getAcpClientHandle). Calling them outside an ACP session returns a clear error.
HITL and checkpoints
When a run pauses for approval, the translator surfaces the pending state and the prompt resolves with an appropriate stopReason. The user's permission outcome becomes an ApprovalResponse list; Maniac.resumeCheckpoint continues the run on the same thread.
Import surface
import {
serveAcpStdio,
AcpServer,
TraceTranslator,
createTranslatorState,
getAcpClientHandle,
withAcpClientContext
} from "@maniac-ai/agents/acp";Protocol types (PromptRequest, SessionNotification, …) re-export from ./protocol.js for consumers building custom adapters.