ACP agents bindings
Bind a conversation or thread to an ACP session, and configure persistent bindings[] entries
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:
/codex bind # native Codex bind, route future messages here
/codex model gpt-5.4 # tune the bound native Codex thread
/codex stop # control the active native Codex turn
/acp spawn codex --bind here # explicit ACP fallback for Codex
/acp spawn codex --thread auto # may create a child thread/topic and bind there
/acp spawn codex --bind here --cwd /workspace/repo # same chat binding, Codex runs in /workspace/repoBinding 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
Marks a persistent ACP conversation binding.
Identifies 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="". Use E.164 numbers such as+15555550123for direct chats and WhatsApp group JIDs such as[email protected]for groups. - iMessage DM/group:
match.channel="imessage"+match.peer.id="<handle|chat_id:*|chat_guid:*|chat_identifier:*>". Preferchat_id:*for stable group bindings.
The owning OpenClaw agent id.
Optional ACP override.
Optional operator-facing label.
Optional runtime working directory.
Optional 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
{
agents: {
ownership: "explicit",
entries: {
codex: {
runtime: {
type: "acp",
acp: {
agent: "codex",
backend: "acpx",
mode: "persistent",
cwd: "/workspace/openclaw",
},
},
},
claude: {
runtime: {
type: "acp",
acp: { agent: "claude", backend: "acpx", mode: "persistent" },
},
},
},
},
bindings: [
{
type: "acp",
agentId: "codex",
match: {
channel: "discord",
accountId: "default",
peer: { kind: "channel", id: "222222222222222222" },
},
acp: { label: "codex-main" },
},
{
type: "acp",
agentId: "claude",
match: {
channel: "telegram",
accountId: "default",
peer: { kind: "group", id: "-1001234567890:topic:42" },
},
acp: { cwd: "/workspace/repo-b" },
},
{
type: "route",
agentId: "main",
match: { channel: "discord", accountId: "default" },
},
{
type: "route",
agentId: "main",
match: { channel: "telegram", accountId: "default" },
},
],
channels: {
discord: {
guilds: {
"111111111111111111": {
channels: {
"222222222222222222": { requireMention: false },
},
},
},
},
telegram: {
groups: {
"-1001234567890": {
topics: { "42": { requireMention: false } },
},
},
},
},
}Behavior
- OpenClaw ensures the configured ACP session exists 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.