ACP is one of the delegation backends DataMind Oda can hand a task to: it runs one self-contained task in a child agent program that speaks the Agent Client Protocol over the run's standard input and output. The program is named in the backend's command setting, and it runs unattended. Use this backend when the child program is one you supply; Choosing and enabling a delegation backend covers the other backends and how the choice is made.
acp. Bundles are managed on the Plugins page in the sidebar; see Plugins and bundles.| Setting | Default | What it does |
|---|---|---|
providerName | acp | The name the backend registers under and is reached by. |
command | required | The program each run starts. There is no default; a row without it is refused when the backend loads. |
args | empty | The arguments passed to the program. |
cwd | the chat's directory | The folder the run works in. When left out, the run uses the parent chat's directory. |
env | empty | Extra environment entries for the run. Credential-shaped values from this computer are removed first, and your entries are added on top. |
permission | reject | How the run's permission requests are answered; the two values are below. |
disposeEofGraceMs | 6000 | How long the run's input is left open at the end before the app moves on to stopping the process. |
disposeGraceMs | 3000 | How long the process has to end on its own after it is asked to stop, before it is forced to stop. |
Only command is required; every other value has a default. A value the backend does not accept is refused when the backend loads, so a mistake shows up before the first delegation. A delegation that ends up with no folder to work in is refused before the run starts.
A delegated run has nobody to ask, so permission decides in advance how it treats the requests that would normally go to a person.
| Value | What the run does |
|---|---|
reject (default) | Denies the run's permission requests. |
allow | Accepts the first allow-once or allow-always option a request offers; when a request offers neither, it is answered as cancelled. |
How a delegated run's permissions start out is on Subagent permissions and sandboxing.
ACP unattended decision (policy: <policy>; request: <request>; decision: <decision>).cwd names, or the chat's directory when that is left out, and each run is one fresh process.aborted, and its process goes through the same cleanup as any other ending.run_in_background starts the run as a job and you collect the result later; see Background subagents and job collection.An ACP run settles with one of five stop reasons:
| Stop reason | When |
|---|---|
completed | The run finished its turn; its final text comes back. |
max-tokens | The run reached its token cap before it could finish. |
refusal | The run declined the task. |
aborted | The run was cancelled. |
error | The run ended for any other reason. |
A failed run reports one safe fact: Subagent failure (provider: ACP; stage: <stage>; category: <category>; .. The line adds ; stop reason: <reason>, ; exit code: <n> or ; signal: <s> when there is one. The stage says where the run stopped, and the category says what kind of problem it was.
| Stage | Where the run stopped |
|---|---|
initialize | Before the run was set up; the setup handshake had not finished. |
new-session | While the run's session was being created. |
prompt | While the task was running. |
process | The run's process ended or could not be watched. |
teardown | While the run was being cleaned up. |
| Category | What it points at |
|---|---|
protocol | The protocol conversation with the child program failed. |
configuration | Something in the backend's configuration was wrong. |
transport | Talking to the run's process failed. |
process-start | The run's process could not be started. |
process-exit | The run's process ended unexpectedly. |
remote-limit | The run reported one of its own limits, such as its turn cap. |
unknown | No more specific category applied. |
What the chat shows around a failure: the failed step reads Error: subagent run failed, then the Diagnostic: line above, then any text the run had produced under Partial output before the run ended:.
The fact is built to be safe to show: raw output, file contents, paths, environment values, credentials and protocol payloads are kept out of it and stay in the app's own logs. What the chat shows around it, and what to do, is on Subagent failures and diagnostics.
How this backend compares with the others is on Choosing and enabling a delegation backend.
The one you name in command. Each run starts that program as a new child process and talks to it over the Agent Client Protocol; args passes it arguments, and env adds environment entries. There is no default, and a row without command is refused when the backend loads.
allow permission policy let a run do?When the run asks for a permission, the first allow-once or allow-always option it offers is chosen, so the request succeeds. A request that offers neither option is answered as cancelled. The default, reject, denies these requests instead.
The policy, not a person. The run never reaches you: its requests are answered in advance, and every decision is recorded as a fact, ACP unattended decision (policy: <policy>; request: <request>; decision: <decision>).
Oda resolves the working directory, starts the program and completes a setup handshake with it; the task is sent only after that handshake succeeds. A failure during setup ends the run before any task runs, and the failure fact names a stage such as initialize or new-session.
With one of five stop reasons: completed when it finished its turn, max-tokens when it reached its token cap, refusal when it declined the task, aborted when it was cancelled, and error when it ended for any other reason. Only completed returns the run's final text; the other endings are reported with the diagnostic described above.
Subagent failure (provider: ACP; . . . ) line tell me?It is the safe failure fact for a delegated run: the stage where the run stopped and a category for the kind of problem. The line adds ; stop reason: <reason>, an exit code or a signal when there is one. The full catalogue of failures and what to do is on Subagent failures and diagnostics.
Yes, when it produced any: the text the run had produced before it failed appears under Partial output before the run ended:, below the failed step's Diagnostic: line.
Oda cleans it up in stages: the run's input is closed, the run gets a window to end on its own (six seconds by default), it is asked to stop, and it gets one more window (three seconds by default) before it is forced to stop. The cleanup runs once, however often it is asked for; the two windows are the disposeEofGraceMs and disposeGraceMs settings.
That is the backend's contract: only the text the run commits as its answer is collected. The run's reasoning, tool calls and plans stay in the run and never reach the chat, so the result is the answer, not a transcript of the work.
Raw output, file contents, paths, environment values, credentials and protocol payloads. The fact carries only safe fields such as the stage, the category and, when there is one, a stop reason, an exit code or a signal; the rest stays in the app's own logs.