Delegation backend: ACP

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.

Turn the backend on

  1. Install the backend's bundle in the profile Oda runs. The backend registers under the name acp. Bundles are managed on the Plugins page in the sidebar; see Plugins and bundles.
  2. Add a delegation tool for it in the profile, with its own name. Oda reaches a backend only through a delegation tool you compose: installing the bundle makes the backend available on this computer, but the model can use only what a delegation tool offers. The delegation call itself is on Delegating work to subagents.
  3. Set the backend's values, if you need to: the program it starts, its arguments, its folder and its permission policy. The settings are below.

The backend's settings

SettingDefaultWhat it does
providerNameacpThe name the backend registers under and is reached by.
commandrequiredThe program each run starts. There is no default; a row without it is refused when the backend loads.
argsemptyThe arguments passed to the program.
cwdthe chat's directoryThe folder the run works in. When left out, the run uses the parent chat's directory.
envemptyExtra environment entries for the run. Credential-shaped values from this computer are removed first, and your entries are added on top.
permissionrejectHow the run's permission requests are answered; the two values are below.
disposeEofGraceMs6000How long the run's input is left open at the end before the app moves on to stopping the process.
disposeGraceMs3000How 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.

Choose a permission policy

A delegated run has nobody to ask, so permission decides in advance how it treats the requests that would normally go to a person.

ValueWhat the run does
reject (default)Denies the run's permission requests.
allowAccepts 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.

The unattended boundary

How a run behaves

An ACP run settles with one of five stop reasons:

Stop reasonWhen
completedThe run finished its turn; its final text comes back.
max-tokensThe run reached its token cap before it could finish.
refusalThe run declined the task.
abortedThe run was cancelled.
errorThe run ended for any other reason.

When a run fails

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.

StageWhere the run stopped
initializeBefore the run was set up; the setup handshake had not finished.
new-sessionWhile the run's session was being created.
promptWhile the task was running.
processThe run's process ended or could not be watched.
teardownWhile the run was being cleaned up.
CategoryWhat it points at
protocolThe protocol conversation with the child program failed.
configurationSomething in the backend's configuration was wrong.
transportTalking to the run's process failed.
process-startThe run's process could not be started.
process-exitThe run's process ended unexpectedly.
remote-limitThe run reported one of its own limits, such as its turn cap.
unknownNo 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.

Limits to plan around

How this backend compares with the others is on Choosing and enabling a delegation backend.

Questions, answered

What program does the ACP backend start?

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.

What does the 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.

Who answers the run's permission requests?

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>).

What happens during the run's setup?

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.

How can an ACP run end?

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.

What does a 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.

Does a failed ACP run keep its partial work?

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.

What happens to the run's process when it ends?

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.

Why does the chat receive only the run's final text?

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.

What is left out of a failure line?

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.