Agent coordination
ACP agents delivery model
Delivery model
ACP sessions can be either interactive workspaces or parent-owned background work. The delivery path depends on that shape.
Interactive ACP sessions
Interactive sessions are meant to keep talking on a visible chat surface:
/acp spawn ... --bind herebinds the current conversation to the ACP session./acp spawn ... --thread ...binds a channel thread/topic to the ACP session.- Persistent configured
bindings[].type="acp"route matching conversations to the same ACP session.
Follow-up messages in the bound conversation route directly to the ACP session, and ACP output is delivered back to that same channel/thread/topic.
When an ACP agent requests structured input during a delivered turn, OpenClaw presents supported form fields as transient Gateway questions in batches of up to three. Single- and multi-select fields support up to four choices. URL requests show the literal HTTP(S) URL with explicit Continue and Decline choices; OpenClaw does not fetch or open it. Explicitly secret fields use a warned, ephemeral text-reply prompt and are never stored in a Gateway question record. Malformed or unsupported requests produce a visible explanation and are declined instead of returning empty answers.
What OpenClaw sends to the harness:
- Normal bound follow-ups are sent as prompt text, plus attachments only when the harness/backend supports them.
/acpmanagement commands and local Gateway commands are intercepted before ACP dispatch.- Runtime-generated completion events are materialized per target. OpenClaw agents get OpenClaw's internal runtime-context envelope; external ACP harnesses get a plain prompt with the child result and instruction. The raw
<<<BEGIN_OPENCLAW_INTERNAL_CONTEXT>>>envelope should never be sent to external harnesses or persisted as ACP user transcript text. - ACP transcript entries use the user-visible trigger text or the plain completion prompt. Internal event metadata stays structured in OpenClaw where possible and is not treated as user-authored chat content.
Parent-owned one-shot ACP sessions
One-shot ACP sessions spawned by another agent run are background children, similar to sub-agents:
- The parent asks for work with
sessions_spawn({ runtime: "acp", mode: "run" }). - The child runs in its own ACP harness session.
- Child turns run on the same background lane used by native sub-agent spawns, so a slow ACP harness does not block unrelated main-session work.
- Completion reports back through the task-completion announce path. OpenClaw converts internal completion metadata into a plain ACP prompt before sending it to an external harness, so harnesses do not see OpenClaw-only runtime context markers.
- The parent rewrites the child result in normal assistant voice when a user-facing reply is useful.
Do not treat this path as a peer-to-peer chat between parent and child. The child already has a completion channel back to the parent.
sessions_send and A2A delivery
sessions_send can target another session after spawn. For normal peer
sessions, OpenClaw uses an agent-to-agent (A2A) follow-up path after
injecting the message:
- Wait for the target session's reply.
- Optionally let requester and target exchange a bounded number of follow-up turns.
- Ask the target to produce an announce message.
- Deliver that announce to the visible channel or thread.
That A2A path is a fallback for peer sends where the sender needs a
visible follow-up. It stays enabled when an unrelated session can see and
message an ACP target, for example under broad tools.sessions.visibility
settings.
OpenClaw skips the A2A follow-up only when the requester is the parent of
its own parent-owned one-shot ACP child. In that case, running A2A on top
of task completion can wake the parent with the child's result, forward
the parent's reply back into the child, and create a parent/child echo
loop. Accepted sessions_send results report target admission separately
from announcement delivery: targetDisposition is queued or steered,
while delivery.status is pending or skipped. For this owned-child case,
delivery.status="skipped" because the completion path is already responsible
for the result.
Resume an existing session
Use resumeSessionId to continue a previous ACP session instead of
starting fresh. The agent replays its conversation history via
session/load, so it picks up with full context of what came before.
{ "task": "Continue where we left off - fix the remaining test failures", "runtime": "acp", "agentId": "codex", "resumeSessionId": "<previous-session-id>"}Common use cases:
- Hand off a Codex session from your laptop to your phone - tell your agent to pick up where you left off.
- Continue a coding session you started interactively in the CLI, now headlessly through your agent.
- Pick up work that was interrupted by a gateway restart or idle timeout.
Notes:
resumeSessionIdonly applies whenruntime: "acp"; the default sub-agent runtime ignores this ACP-only field.streamToonly applies whenruntime: "acp"; the default sub-agent runtime ignores this ACP-only field.resumeSessionIdis a host-local ACP/harness resume id, not an OpenClaw channel session key; OpenClaw still checks ACP spawn policy and target agent policy before dispatch, while the ACP backend or harness owns authorization for loading that upstream id.resumeSessionIdrestores the upstream ACP conversation history;threadandmodestill apply normally to the new OpenClaw session you are creating, somode: "session"still requiresthread: true.- The target agent must support
session/load(Codex and Claude Code do). - If the session id is not found, the spawn fails with a clear error - no silent fallback to a new session.
Post-deploy smoke test
After a gateway deploy, run a live end-to-end check rather than trusting unit tests:
- Verify the deployed gateway version and commit on the target host.
- Open a temporary ACPX bridge session to a live agent.
- Ask that agent to call
sessions_spawnwithruntime: "acp",agentId: "codex",mode: "run", and taskReply with exactly LIVE-ACP-SPAWN-OK. - Verify
accepted=yes, a realchildSessionKey, and no validator error. - Clean up the temporary bridge session.
Keep the gate on mode: "run" and skip streamTo: "parent" -
thread-bound mode: "session" and stream-relay paths are separate richer
integration passes.
Sandbox compatibility
ACP sessions currently run on the host runtime, not inside the OpenClaw sandbox.
Current limitations:
- If the requester session is sandboxed, ACP spawns are blocked for both
sessions_spawn({ runtime: "acp" })and/acp spawn. sessions_spawnwithruntime: "acp"does not supportsandbox: "require".