ACP Agents
ACP agents
Agent Client Protocol (ACP) 会话让 OpenClaw 可以通过 ACP 后端插件运行外部 coding harnesses(例如 Pi、Claude Code、Codex、OpenCode 和 Gemini CLI)。
如果你用自然语言要求 OpenClaw "在 Codex 中运行这个" 或 "在 thread 中启动 Claude Code",OpenClaw 应该将该请求路由到 ACP 运行时(而不是原生 sub-agent 运行时)。
快速操作员流程
当你想要实用的 /acp runbook 时使用此流程:
- 生成会话:
/acp spawn codex --mode persistent --thread auto
- 在绑定的 thread 中工作(或显式 targeting 该 session key)。
- 检查运行时状态:
/acp status
- 根据需要调整运行时选项:
/acp model <provider/model>/acp permissions <profile>/acp timeout <seconds>
- 在不替换 context 的情况下 nudge 活动会话:
/acp steer tighten logging and continue
- 停止工作:
/acp cancel(停止当前 turn),或/acp close(关闭会话 + 移除 bindings)
人类快速入门
自然请求示例:
- "在这里的 thread 中启动一个持久的 Codex 会话并保持专注。"
- "将此作为一次性 Claude Code ACP 会话运行并总结结果。"
- "在 thread 中使用 Gemini CLI 执行此任务,然后在同一 thread 中继续后续操作。"
OpenClaw 应该做什么:
- 选择
runtime: "acp"。 - 解析请求的 harness target(
agentId,例如codex)。 - 如果请求了 thread binding 且当前 channel 支持,将 ACP 会话绑定到 thread。
- 将后续 thread 消息路由到同一个 ACP 会话,直到 unfocused/closed/expired。
ACP 与 sub-agents
当你想要外部 harness 运行时使用 ACP。当你想要 OpenClaw 原生 delegated runs 时使用 sub-agents。
| Area | ACP session | Sub-agent run |
|---|---|---|
| Runtime | ACP backend plugin (例如 acpx) | OpenClaw native sub-agent runtime |
| Session key | agent:<agentId>:acp:<uuid> | agent:<agentId>:subagent:<uuid> |
| Main commands | /acp ... | /subagents ... |
| Spawn tool | sessions_spawn with runtime:"acp" | sessions_spawn (default runtime) |
另见 Sub-agents。
Thread-bound sessions(channel-agnostic)
当 channel adapter 启用 thread bindings 时,ACP 会话可以绑定到 threads:
- OpenClaw 将 thread 绑定到目标 ACP 会话。
- 该 thread 中的后续消息路由到绑定的 ACP 会话。
- ACP 输出返回到同一个 thread。
- Unfocus/close/archive/idle-timeout 或 max-age expiry 移除 binding。
Thread binding 支持是 adapter 特定的。如果活动 channel adapter 不支持 thread bindings,OpenClaw 返回清晰的 unsupported/unavailable 消息。
Thread-bound ACP 所需的 feature flags:
acp.enabled=trueacp.dispatch.enabled默认开启(设置为false暂停 ACP dispatch)- Channel-adapter ACP thread-spawn flag 启用(adapter 特定)
- Discord:
channels.discord.threadBindings.spawnAcpSessions=true
- Discord:
Thread supporting channels
- 任何暴露 session/thread binding capability 的 channel adapter。
- 当前内置支持:Discord。
- Plugin channels 可以通过相同的 binding interface 添加支持。
启动 ACP 会话(interfaces)
从 sessions_spawn
使用 runtime: "acp" 从 agent turn 或 tool call 启动 ACP 会话。
{
"task": "打开 repo 并总结失败的测试",
"runtime": "acp",
"agentId": "codex",
"thread": true,
"mode": "session"
}
注意:
runtime默认为subagent,因此对于 ACP 会话显式设置runtime: "acp"。- 如果省略
agentId,OpenClaw 使用配置好的acp.defaultAgent。 mode: "session"需要thread: true以保持持久的 bound conversation。
Interface 详情:
task(必需):发送到 ACP 会话的初始 prompt。runtime(ACP 必需):必须为"acp"。agentId(可选):ACP target harness id。如果设置了则回退到acp.defaultAgent。thread(可选,默认false):在支持的地方请求 thread binding flow。mode(可选):run(one-shot)或session(persistent)。- 默认是
run - 如果
thread: true且省略 mode,OpenClaw 可能根据 runtime path 默认为 persistent behavior mode: "session"需要thread: true
- 默认是
cwd(可选):请求的 runtime working directory(由 backend/runtime policy 验证)。label(可选):operator-facing label 用于 session/banner 文本。
Sandbox 兼容性
ACP 会话当前在 host runtime 上运行,不在 OpenClaw sandbox 内。
当前限制:
- 如果 requester session 是 sandboxed,ACP spawns 被阻止。
- 错误:
Sandboxed sessions cannot spawn ACP sessions because runtime="acp" runs on the host. Use runtime="subagent" from sandboxed sessions.
- 错误:
sessions_spawnwithruntime: "acp"不支持sandbox: "require"。- 错误:
sessions_spawn sandbox="require" is unsupported for runtime="acp" because ACP sessions run outside the sandbox. Use runtime="subagent" or sandbox="inherit".
- 错误:
当你需要 sandbox-enforced execution 时使用 runtime: "subagent"。
从 /acp command
当需要时,使用 /acp spawn 从 chat 进行显式 operator control。
/acp spawn codex --mode persistent --thread auto
/acp spawn codex --mode oneshot --thread off
/acp spawn codex --thread here
关键 flags:
--mode persistent|oneshot--thread auto|here|off--cwd <absolute-path>--label <name>
Session target resolution
大多数 /acp actions 接受可选的 session target(session-key、session-id 或 session-label)。
Resolution order:
- 显式 target 参数(或
/acp steer的--session)- 尝试 key
- 然后 UUID-shaped session id
- 然后 label
- 当前 thread binding(如果此 conversation/thread 绑定到 ACP 会话)
- 当前 requester session fallback
如果没有 target 解析,OpenClaw 返回清晰的错误(Unable to resolve session target: ...)。
Spawn thread modes
/acp spawn 支持 --thread auto|here|off。
| Mode | Behavior |
|---|---|
auto | 在活动 thread 中:绑定该 thread。在 thread 外:在支持时创建/绑定 child thread。 |
here | 需要当前活动 thread;如果不在 thread 中则失败。 |
off | 无 binding。会话启动时 unbound。 |
注意:
- 在非 thread binding surfaces 上,默认 behavior 实际上是
off。 - Thread-bound spawn 需要 channel policy 支持(对于 Discord:
channels.discord.threadBindings.spawnAcpSessions=true)。
ACP controls
可用 command family:
/acp spawn/acp cancel/acp steer/acp close/acp status/acp set-mode/acp set/acp cwd/acp permissions/acp timeout/acp model/acp reset-options/acp sessions/acp doctor/acp install
/acp status 显示有效的 runtime options,并在可用时显示 runtime-level 和 backend-level session identifiers。
一些 controls 依赖于 backend capabilities。如果 backend 不支持某个 control,OpenClaw 返回清晰的 unsupported-control 错误。
ACP command cookbook
| Command | What it does | Example |
|---|---|---|
/acp spawn | 创建 ACP 会话;可选 thread bind。 | /acp spawn codex --mode persistent --thread auto --cwd /repo |
/acp cancel | 取消 target session 的 in-flight turn。 | /acp cancel agent:codex:acp:<uuid> |
/acp steer | 向运行中的会话发送 steer instruction。 | /acp steer --session support inbox prioritize failing tests |
/acp close | 关闭会话并 unbind thread targets。 | /acp close |
/acp status | 显示 backend、mode、state、runtime options、capabilities。 | /acp status |
/acp set-mode | 为 target session 设置 runtime mode。 | /acp set-mode plan |
/acp set | Generic runtime config option write。 | /acp set model openai/gpt-5.2 |
/acp cwd | 设置 runtime working directory override。 | /acp cwd /Users/user/Projects/repo |
/acp permissions | 设置 approval policy profile。 | /acp permissions strict |
/acp timeout | 设置 runtime timeout(seconds)。 | /acp timeout 120 |
/acp model | 设置 runtime model override。 | /acp model anthropic/claude-opus-4-5 |
/acp reset-options | 移除 target session 的所有 runtime option overrides。 | /acp reset-options |
/acp sessions | 从 store 列出最近的 ACP 会话。 | /acp sessions |
/acp doctor | Backend health、capabilities、actionable fixes。 | /acp doctor |
/acp install | 打印 deterministic install and enable steps。 | /acp install |
Runtime options mapping
/acp 有 convenience commands 和 generic setter。
等效操作:
/acp model <id>映射到 runtime config keymodel。/acp permissions <profile>映射到 runtime config keyapproval_policy。/acp timeout <seconds>映射到 runtime config keytimeout。/acp cwd <path>直接更新 runtime cwd override。/acp set <key> <value>是 generic path。- 特殊情况:
key=cwd使用 cwd override path。
- 特殊情况:
/acp reset-options清除 target session 的所有 runtime overrides。
acpx harness support(current)
当前 acpx 内置 harness aliases:
piclaudecodexopencodegeminikimi
当 OpenClaw 使用 acpx backend 时,优先使用这些值作为 agentId,除非你的 acpx config 定义了自定义 agent aliases。
Direct acpx CLI usage 也可以通过 --agent <command> targeting 任意 adapters,但该 raw escape hatch 是 acpx CLI feature(不是正常的 OpenClaw agentId path)。
必需配置
Core ACP baseline:
{
acp: {
enabled: true,
// 可选。默认为 true;设置为 false 暂停 ACP dispatch 同时保持 /acp controls。
dispatch: { enabled: true },
backend: "acpx",
defaultAgent: "codex",
allowedAgents: ["pi", "claude", "codex", "opencode", "gemini", "kimi"],
maxConcurrentSessions: 8,
stream: {
coalesceIdleMs: 300,
maxChunkChars: 1200,
},
runtime: {
ttlMinutes: 120,
},
},
}
Thread binding config 是 channel-adapter 特定的。Discord 示例:
{
session: {
threadBindings: {
enabled: true,
idleHours: 24,
maxAgeHours: 0,
},
},
channels: {
discord: {
threadBindings: {
enabled: true,
spawnAcpSessions: true,
},
},
},
}
如果 thread-bound ACP spawn 不工作,首先验证 adapter feature flag:
- Discord:
channels.discord.threadBindings.spawnAcpSessions=true
acpx backend 的 Plugin setup
安装并启用插件:
openclaw plugins install acpx
openclaw config set plugins.entries.acpx.enabled true
开发期间的本地 workspace install:
openclaw plugins install ./extensions/acpx
然后验证 backend health:
/acp doctor
acpx command 和 version configuration
默认情况下,acpx 插件(发布为 @openclaw/acpx)使用 plugin-local pinned binary:
- Command 默认为
extensions/acpx/node_modules/.bin/acpx。 - Expected version 默认为 extension pin。
- Startup registers ACP backend immediately as not-ready。
- A background ensure job verifies
acpx --version。 - 如果 plugin-local binary 缺失或不匹配,它运行:
npm install --omit=dev --no-save acpx@<pinned>并重新验证。
你可以在 plugin config 中覆盖 command/version:
{
"plugins": {
"entries": {
"acpx": {
"enabled": true,
"config": {
"command": "../acpx/dist/cli.js",
"expectedVersion": "any"
}
}
}
}
}
注意:
command接受绝对路径、相对路径或 command name(acpx)。- 相对路径从 OpenClaw workspace directory 解析。
expectedVersion: "any"禁用 strict version matching。- 当
command指向自定义 binary/path 时,plugin-local auto-install 被禁用。 - OpenClaw startup 在 backend health check 运行时保持非阻塞。
见 Plugins。
Permission configuration
ACP 会话以 non-interactive 方式运行——没有 TTY 来 approve 或 deny file-write 和 shell-exec permission prompts。acpx 插件提供两个 config keys 来控制 permissions 的处理方式:
permissionMode
控制 harness agent 可以在不 prompting 的情况下执行哪些 operations。
| Value | Behavior |
|---|---|
approve-all | Auto-approve 所有 file writes 和 shell commands。 |
approve-reads | Auto-approve reads only;writes 和 exec 需要 prompts。 |
deny-all | Deny 所有 permission prompts。 |
nonInteractivePermissions
控制当 permission prompt 会被显示但没有 interactive TTY 可用时会发生什么(这在 ACP 会话中总是如此)。
| Value | Behavior |
|---|---|
fail | 用 AcpRuntimeError 中止会话。(default) |
deny | Silently deny permission 并继续(graceful degradation)。 |
Configuration
通过 plugin config 设置:
openclaw config set plugins.entries.acpx.config.permissionMode approve-all
openclaw config set plugins.entries.acpx.config.nonInteractivePermissions fail
更改这些值后重启 gateway。
重要: OpenClaw 当前默认为
permissionMode=approve-reads和nonInteractivePermissions=fail。在 non-interactive ACP 会话中,任何触发 permission prompt 的 write 或 exec 都可能失败并显示AcpRuntimeError: Permission prompt unavailable in non-interactive mode。如果你需要限制 permissions,将
nonInteractivePermissions设置为deny以便会话 graceful degradation 而不是崩溃。
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
ACP runtime backend is not configured | Backend plugin missing or disabled. | Install and enable backend plugin,然后运行 /acp doctor。 |
ACP is disabled by policy (acp.enabled=false) | ACP globally disabled. | Set acp.enabled=true。 |
ACP dispatch is disabled by policy (acp.dispatch.enabled=false) | Dispatch from normal thread messages disabled. | Set acp.dispatch.enabled=true。 |
ACP agent "<id>" is not allowed by policy | Agent not in allowlist. | Use allowed agentId or update acp.allowedAgents。 |
Unable to resolve session target: ... | Bad key/id/label token. | Run /acp sessions, copy exact key/label, retry。 |
--thread here requires running /acp spawn inside an active ... thread | --thread here used outside a thread context. | Move to target thread or use --thread auto/off。 |
Only <user-id> can rebind this thread. | Another user owns thread binding. | Rebind as owner or use a different thread。 |
Thread bindings are unavailable for <channel>. | Adapter lacks thread binding capability. | Use --thread off or move to supported adapter/channel。 |
Sandboxed sessions cannot spawn ACP sessions ... | ACP runtime is host-side; requester session is sandboxed. | Use runtime="subagent" from sandboxed sessions, or run ACP spawn from a non-sandboxed session。 |
sessions_spawn sandbox="require" is unsupported for runtime="acp" ... | sandbox="require" requested for ACP runtime. | Use runtime="subagent" for required sandboxing, or use ACP with sandbox="inherit" from a non-sandboxed session。 |
| Missing ACP metadata for bound session | Stale/deleted ACP session metadata。 | Recreate with /acp spawn, then rebind/focus thread。 |
AcpRuntimeError: Permission prompt unavailable in non-interactive mode | permissionMode blocks writes/exec in non-interactive ACP session。 | Set plugins.entries.acpx.config.permissionMode to approve-all and restart gateway. See Permission configuration。 |
| ACP session fails early with little output | Permission prompts are blocked by permissionMode/nonInteractivePermissions。 | Check gateway logs for AcpRuntimeError. For full permissions, set permissionMode=approve-all; for graceful degradation, set nonInteractivePermissions=deny。 |
| ACP session stalls indefinitely after completing work | Harness process finished but ACP session did not report completion。 | Monitor with ps aux | grep acpx; kill stale processes manually。 |