On this page
On this page
Agent coordination
ACP agents bindings
Bound sessions
Mental model
- Chat surface - where people keep talking (Discord channel, Telegram topic, iMessage chat).
- ACP session - the durable Codex/Claude/Gemini runtime state OpenClaw routes to.
- Child thread/topic - an optional extra messaging surface created only by
--thread .... - Runtime workspace - the filesystem location (
cwd, repo checkout, backend workspace) where the harness runs. Independent of the chat surface.
Current-conversation binds
/acp spawn <harness> --bind here pins the current conversation to the
spawned ACP session - no child thread, same chat surface. OpenClaw keeps
owning transport, auth, safety, and delivery. Follow-up messages in that
conversation route to the same session; /new and /reset reset the session
in place; /acp close removes the binding.
Examples:
Binding rules and exclusivity
--bind hereand--thread ...are mutually exclusive.--bind hereonly works on channels that advertise current-conversation binding; OpenClaw returns a clear unsupported message otherwise. Bindings persist across gateway restarts.- On Discord,
spawnSessionsgates child thread creation for--thread auto|here- not--bind here. - If you spawn to a different ACP agent without
--cwd, OpenClaw inherits the target agent's workspace by default. Missing inherited paths (ENOENT/ENOTDIR) fall back to the backend default; other access errors (e.g.EACCES) surface as spawn errors. - Gateway management commands stay local in bound conversations -
/acp ...commands are handled by OpenClaw even when normal follow-up text routes to the bound ACP session;/statusand/sessionalso stay local whenever command handling is enabled for that surface.
Thread-bound sessions
When thread bindings are enabled for a channel adapter:
- OpenClaw binds a thread to a target ACP session.
- Follow-up messages in that thread route to the bound ACP session.
- ACP output is delivered back to the same thread.
/session unbind, close, archive, idle timeout, or max-age expiry removes the binding./session unbinddetaches only the current conversation and leaves the ACP session running./acp close,/acp cancel,/acp status,/status, and/sessionare Gateway commands, not prompts to the ACP harness.
Required feature flags for thread-bound ACP:
acp.enabled=trueacp.dispatch.enabledis on by default (setfalseto pause automatic ACP thread dispatch; explicitsessions_spawn({ runtime: "acp" })calls still work).- Channel-adapter thread session spawns enabled (default:
true):- Discord/Telegram:
session.threadBindings.spawnSessions=true
- Discord/Telegram:
Thread binding support is adapter-specific. If the active channel adapter does not support thread bindings, OpenClaw returns a clear unsupported/unavailable message.
Thread-supporting channels
- Any channel adapter that exposes session/thread binding capability.
- Current built-in support: Discord threads/channels, Telegram topics (forum topics in groups/supergroups and DM topics).
- Plugin channels can add support through the same binding interface.
Persistent channel bindings
For non-ephemeral workflows, configure persistent ACP bindings in top-level
bindings[] entries.
Binding model
bindings[].type"acp"Marks a persistent ACP conversation binding.
bindings[].matchobjectIdentifies the target conversation. Per-channel shapes:
- Discord channel/thread:
match.channel="discord"+match.peer.id="<channelOrThreadId>" - Slack channel/DM:
match.channel="slack"+match.peer.id="<channelId|channel:<channelId>|#<channelId>|userId|user:<userId>|slack:<userId>|<@userId>>". Prefer stable Slack ids; channel bindings also match replies inside that channel's threads. - Telegram forum topic:
match.channel="telegram"+match.peer.id="<chatId>:topic:<topicId>" - WhatsApp DM/group:
match.channel="whatsapp"+match.peer.id="<E.164|group JID>". Use E.164 numbers such as+15555550123for direct chats and WhatsApp group JIDs such as120363424282127706@g.usfor groups. - iMessage DM/group:
match.channel="imessage"+match.peer.id="<handle|chat_id:*|chat_guid:*|chat_identifier:*>". Preferchat_id:*for stable group bindings.
bindings[].agentIdstringThe owning OpenClaw agent id.
bindings[].acp.mode"persistent" | "oneshot"Optional ACP override.
bindings[].acp.labelstringOptional operator-facing label.
bindings[].acp.cwdstringOptional runtime working directory.
bindings[].acp.backendstringOptional backend override.
Runtime defaults per agent
Use agents.entries.*.runtime to define ACP defaults once per agent:
agents.entries.*.runtime.type="acp"agents.entries.*.runtime.acp.agent(harness id, e.g.codexorclaude)agents.entries.*.runtime.acp.backendagents.entries.*.runtime.acp.modeagents.entries.*.runtime.acp.cwd
Override precedence for ACP bound sessions:
bindings[].acp.*agents.entries.*.runtime.acp.*- Global ACP defaults (e.g.
acp.backend)
Configured bindings also forward the owning agent's explicit model and thinking
policy. For an agent with runtime.type: "acp", agents.entries.*.model.primary
selects the ACP harness model, even when its value also looks like a native
provider/model reference. OpenClaw-side calls, such as /btw and internal
utilities, use agents.defaults.model as their native default. Explicit native
session overrides and dedicated utility or subagent model settings still apply.
The selected native provider needs its own credentials; an ACP harness login
does not authenticate OpenClaw's native calls.
For existing configurations, this can change the native provider even when the
ACP primary is a valid native reference. openclaw doctor describes each ACP
agent's harness model and resolved native default without rewriting configuration.
Choose the native default in agents.defaults.model; native session, utility,
and subagent overrides remain available for their respective operations.
For native calls that support model fallback, omitted agent model.fallbacks
inherits agents.defaults.model.fallbacks. An explicit native fallback list
replaces that list, and fallbacks: [] disables it. These entries must be native
OpenClaw model references, not harness-only IDs. /btw uses its selected native
model without a model fallback chain.
Thinking uses the agent's thinkingDefault, then per-model
agents.defaults.models["provider/model"].params.thinking, then
agents.defaults.thinkingDefault. Without configured policy, the external
harness keeps its own defaults.
Changing a configured model or thinking value updates the existing session
before its next turn without replacing the conversation. Each option is saved
only after the harness accepts it; a rejected option returns an error and keeps
that option's previous selection. Model and thinking changes are independent,
not an atomic batch. Removing a default
uses any remaining configured policy; if none remains, OpenClaw retains the
session's last selection. Omission is not a backend reset. To change thinking
explicitly, use /acp set thinking <level> with a level supported by the harness.
For Codex ACP, off only omits a fresh session's startup override. Switching an
existing session to off is unsupported and returns an error without clearing
its current reasoning effort or conversation.
Example
Behavior
- OpenClaw creates the configured ACP session if needed after channel-specific admission and before use.
- Messages in that channel, topic, or chat route to the configured ACP session.
- Configured ACP bindings own their session route. Channel broadcast fan-out does not replace the configured ACP session for a matched binding.
- In bound conversations,
/newand/resetreset the same ACP session key in place. - Runtime bindings created by thread-bound spawns still apply where present.
- For cross-agent ACP spawns without an explicit
cwd, OpenClaw inherits the target agent workspace from agent config. - Missing inherited workspace paths fall back to the backend default cwd; non-missing access failures surface as spawn errors.