Appearance
ACP Agents
Agent Client Protocol(ACP) 会话让 OpenClaw 通过 ACP 后端插件运行外部编程助手(例如 Pi、Claude Code、Codex、Cursor、Copilot、OpenClaw ACP、OpenCode、Gemini CLI 以及其他受支持的 ACPX 助手)。
如果你用自然语言告诉 OpenClaw"在 Codex 里运行这个"或"在 thread 里启动 Claude Code",OpenClaw 应该把请求路由到 ACP 运行时(而非原生子 agent 运行时)。
快速操作流程
实用的 /acp 操作手册:
- 启动一个会话:
/acp spawn codex --mode persistent --thread auto
- 在绑定的 thread 里工作(或明确指定会话 key)。
- 检查运行时状态:
/acp status
- 按需调整运行时选项:
/acp model <provider/model>/acp permissions <profile>/acp timeout <seconds>
- 向活跃会话发送指令,不替换上下文:
/acp steer tighten logging and continue
- 停止工作:
/acp cancel(停止当前轮次),或/acp close(关闭会话 + 移除绑定)
人类友好的快速上手
自然语言请求示例:
- "在这里开一个持久 Codex 会话放到 thread 里,保持专注。"
- "用 Claude Code ACP 单次会话跑这个,然后汇总结果。"
- "在 thread 里用 Gemini CLI 完成这个任务,后续跟进继续在同一 thread 里。"
OpenClaw 应该:
- 选择
runtime: "acp"。 - 解析请求的助手目标(
agentId,例如codex)。 - 如果请求 thread 绑定且当前频道支持,将 ACP 会话绑定到 thread。
- 将后续 thread 消息路由到同一 ACP 会话,直到取消焦点/关闭/过期。
ACP vs 子 Agent
需要外部助手运行时使用 ACP,需要 OpenClaw 原生委派运行时使用子 agent。
| 维度 | ACP 会话 | 子 Agent 运行 |
|---|---|---|
| 运行时 | ACP 后端插件(例如 acpx) | OpenClaw 原生子 agent 运行时 |
| 会话 key | agent:<agentId>:acp:<uuid> | agent:<agentId>:subagent:<uuid> |
| 主要命令 | /acp ... | /subagents ... |
| 启动工具 | sessions_spawn with runtime:"acp" | sessions_spawn(默认运行时) |
参见 Sub-agents。
Thread 绑定会话(频道无关)
当频道适配器启用了 thread 绑定功能时,ACP 会话可以绑定到 thread:
- OpenClaw 将 thread 绑定到目标 ACP 会话。
- 该 thread 的后续消息路由到绑定的 ACP 会话。
- ACP 输出发回同一 thread。
- 取消焦点/关闭/归档/空闲超时或最大年龄过期后移除绑定。
Thread 绑定支持因适配器而异。如果当前频道适配器不支持 thread 绑定,OpenClaw 会返回清晰的不支持/不可用提示。
Thread 绑定 ACP 所需的功能标志:
acp.enabled=trueacp.dispatch.enabled默认开启(设为false可暂停 ACP dispatch)- 频道适配器 ACP thread 启动标志已启用(适配器特定)
- Discord:
channels.discord.threadBindings.spawnAcpSessions=true - Telegram:
channels.telegram.threadBindings.spawnAcpSessions=true
- Discord:
支持 Thread 的频道
- 任何暴露了会话/thread 绑定能力的频道适配器。
- 当前内置支持:
- Discord threads/channels
- Telegram topics(群组/超级群组中的论坛主题以及 DM 主题)
- 插件频道可通过相同绑定接口添加支持。
频道专用设置
对于非临时工作流,在顶层 bindings[] 条目中配置持久 ACP 绑定。
绑定模型
bindings[].type="acp"标记持久 ACP 对话绑定。bindings[].match标识目标对话:- Discord 频道或 thread:
match.channel="discord"+match.peer.id="<channelOrThreadId>" - Telegram 论坛主题:
match.channel="telegram"+match.peer.id="<chatId>:topic:<topicId>"
- Discord 频道或 thread:
bindings[].agentId是所属 OpenClaw agent 的 id。- 可选的 ACP 覆盖配置在
bindings[].acp下:mode(persistent或oneshot)labelcwdbackend
每个 Agent 的运行时默认值
用 agents.list[].runtime 为每个 agent 定义一次 ACP 默认值:
agents.list[].runtime.type="acp"agents.list[].runtime.acp.agent(助手 id,例如codex或claude)agents.list[].runtime.acp.backendagents.list[].runtime.acp.modeagents.list[].runtime.acp.cwd
ACP 绑定会话的覆盖优先级:
bindings[].acp.*agents.list[].runtime.acp.*- 全局 ACP 默认值(例如
acp.backend)
配置示例:
json5
{
agents: {
list: [
{
id: "codex",
runtime: {
type: "acp",
acp: {
agent: "codex",
backend: "acpx",
mode: "persistent",
cwd: "/workspace/openclaw",
},
},
},
{
id: "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 } },
},
},
},
},
}行为说明:
- OpenClaw 在使用前确保已配置的 ACP 会话存在。
- 该频道或主题中的消息路由到已配置的 ACP 会话。
- 在绑定对话中,
/new和/reset就地重置同一 ACP 会话 key。 - 临时运行时绑定(例如通过 thread 焦点流程创建的)在有的地方仍然适用。
启动 ACP 会话(接口)
通过 sessions_spawn
在 agent 轮次或工具调用中使用 runtime: "acp" 启动 ACP 会话:
json
{
"task": "打开 repo 并汇总失败的测试",
"runtime": "acp",
"agentId": "codex",
"thread": true,
"mode": "session"
}注意事项:
runtime默认为subagent,ACP 会话必须显式设置runtime: "acp"。- 如果省略
agentId,配置了acp.defaultAgent时 OpenClaw 使用该值。 mode: "session"需要thread: true来保持持久绑定对话。
接口详情:
task(必填):发送到 ACP 会话的初始提示。runtime(ACP 必填):必须为"acp"。agentId(可选):ACP 目标助手 id。如设置了acp.defaultAgent则回退到该值。thread(可选,默认false):在支持的地方请求 thread 绑定流程。mode(可选):run(单次)或session(持久)。- 默认为
run - 如果
thread: true且省略了 mode,OpenClaw 可能根据运行时路径默认为持久行为 mode: "session"需要thread: true
- 默认为
cwd(可选):请求的运行时工作目录(由后端/运行时策略验证)。label(可选):在会话/横幅文字中面向操作员显示的标签。resumeSessionId(可选):恢复已有 ACP 会话而非创建新会话。agent 通过session/load重放对话历史。需要runtime: "acp"。streamTo(可选):"parent"将初始 ACP 运行进度摘要作为系统事件流式传回请求者会话。- 可用时,接受的响应包含
streamLogPath,指向会话范围的 JSONL 日志(<sessionId>.acp-stream.jsonl),你可以 tail 查看完整转发历史。
- 可用时,接受的响应包含
恢复已有会话
使用 resumeSessionId 继续之前的 ACP 会话而非重新开始。agent 通过 session/load 重放对话历史,从完整的上下文中继续。
json
{
"task": "从上次停下来的地方继续——修复剩余的测试失败",
"runtime": "acp",
"agentId": "codex",
"resumeSessionId": "<previous-session-id>"
}常见使用场景:
- 将 Codex 会话从笔记本电脑交接到手机——告诉你的 agent 从上次停下来的地方继续
- 继续你在 CLI 中交互式开始的编码会话,现在通过 agent 无头运行
- 接续因 gateway 重启或空闲超时而中断的工作
注意事项:
resumeSessionId需要runtime: "acp"——与子 agent 运行时一起使用时返回错误。resumeSessionId恢复上游 ACP 对话历史;thread和mode仍然正常适用于你创建的新 OpenClaw 会话,因此mode: "session"仍然需要thread: true。- 目标 agent 必须支持
session/load(Codex 和 Claude Code 都支持)。 - 如果找不到会话 ID,启动会以清晰的错误失败——不会静默回退到新会话。
操作员冒烟测试
在 gateway 部署后,当你想快速端到端验证 ACP spawn 真正正常工作时使用——不只是通过单元测试。
推荐步骤:
- 验证目标主机上已部署的 gateway 版本/commit。
- 确认已部署的源码包含
src/gateway/sessions-patch.ts中的 ACP 继承接受(subagent:* or acp:* sessions)。 - 向实时 agent 打开一个临时 ACPX 桥接会话(例如
jpclawhq上的razor(main))。 - 让该 agent 调用
sessions_spawn,参数为:runtime: "acp"agentId: "codex"mode: "run"- task:
Reply with exactly LIVE-ACP-SPAWN-OK
- 验证 agent 报告:
accepted=yes- 真实的
childSessionKey - 没有验证器错误
- 清理临时 ACPX 桥接会话。
发给实时 agent 的示例提示:
text
Use the sessions_spawn tool now with runtime: "acp", agentId: "codex", and mode: "run".
Set the task to: "Reply with exactly LIVE-ACP-SPAWN-OK".
Then report only: accepted=<yes/no>; childSessionKey=<value or none>; error=<exact text or none>.注意事项:
- 基础测试保持
mode: "run",除非你刻意测试 thread 绑定持久 ACP 会话。 - 基础测试不要求
streamTo: "parent",该路径依赖请求者/会话能力,是单独的集成检查。 - Thread 绑定
mode: "session"测试作为第二轮更丰富的集成测试,从真实 Discord thread 或 Telegram 主题进行。
沙箱兼容性
ACP 会话当前运行在宿主机运行时,不在 OpenClaw 沙箱内。
当前限制:
- 如果请求者会话处于沙箱中,
sessions_spawn({ runtime: "acp" })和/acp spawn都会被阻止。- 错误:
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".
- 错误:
需要沙箱强制执行时使用 runtime: "subagent"。
通过 /acp 命令
需要从聊天中进行明确操作员控制时使用 /acp spawn。
text
/acp spawn codex --mode persistent --thread auto
/acp spawn codex --mode oneshot --thread off
/acp spawn codex --thread here关键标志:
--mode persistent|oneshot--thread auto|here|off--cwd <absolute-path>--label <name>
参见 Slash Commands。
会话目标解析
大多数 /acp 操作接受可选的会话目标(session-key、session-id 或 session-label)。
解析顺序:
- 显式目标参数(
/acp steer的--session)- 尝试 key
- 然后 UUID 形式的 session id
- 然后 label
- 当前 thread 绑定(如果此对话/thread 绑定到 ACP 会话)
- 当前请求者会话回退
如果找不到目标,OpenClaw 返回清晰错误(Unable to resolve session target: ...)。
Thread 启动模式
/acp spawn 支持 --thread auto|here|off。
| 模式 | 行为 |
|---|---|
auto | 在活跃 thread 中:绑定该 thread。在 thread 外:在支持的地方创建/绑定子 thread。 |
here | 要求当前活跃 thread;不在 thread 中则失败。 |
off | 不绑定。会话以未绑定状态启动。 |
注意事项:
- 在不支持 thread 绑定的平台上,默认行为实际上是
off。 - Thread 绑定启动需要频道策略支持:
- Discord:
channels.discord.threadBindings.spawnAcpSessions=true - Telegram:
channels.telegram.threadBindings.spawnAcpSessions=true
- Discord:
ACP 控制命令
可用命令族:
/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 显示有效的运行时选项,以及可用时的运行时级别和后端级别会话标识符。
部分控制依赖后端能力。如果后端不支持某个控制,OpenClaw 返回清晰的不支持控制错误。
ACP 命令速查表
| 命令 | 作用 | 示例 |
|---|---|---|
/acp spawn | 创建 ACP 会话;可选 thread 绑定。 | /acp spawn codex --mode persistent --thread auto --cwd /repo |
/acp cancel | 取消目标会话的进行中轮次。 | /acp cancel agent:codex:acp:<uuid> |
/acp steer | 向运行中的会话发送指导指令。 | /acp steer --session support inbox prioritize failing tests |
/acp close | 关闭会话并解除 thread 目标绑定。 | /acp close |
/acp status | 显示后端、模式、状态、运行时选项、能力。 | /acp status |
/acp set-mode | 为目标会话设置运行时模式。 | /acp set-mode plan |
/acp set | 通用运行时配置选项写入。 | /acp set model openai/gpt-5.2 |
/acp cwd | 设置运行时工作目录覆盖。 | /acp cwd /Users/user/Projects/repo |
/acp permissions | 设置审批策略配置。 | /acp permissions strict |
/acp timeout | 设置运行时超时(秒)。 | /acp timeout 120 |
/acp model | 设置运行时模型覆盖。 | /acp model anthropic/claude-opus-4-6 |
/acp reset-options | 移除会话运行时选项覆盖。 | /acp reset-options |
/acp sessions | 从存储中列出最近的 ACP 会话。 | /acp sessions |
/acp doctor | 后端健康状态、能力、可操作修复建议。 | /acp doctor |
/acp install | 打印确定性安装和启用步骤。 | /acp install |
/acp sessions 从当前绑定或请求者会话的存储中读取。接受 session-key、session-id 或 session-label token 的命令通过 gateway 会话发现解析目标,包括自定义的每 agent session.store 根目录。
运行时选项映射
/acp 提供便捷命令和通用设置器。
等效操作:
/acp model <id>映射到运行时配置 keymodel。/acp permissions <profile>映射到运行时配置 keyapproval_policy。/acp timeout <seconds>映射到运行时配置 keytimeout。/acp cwd <path>直接更新运行时 cwd 覆盖。/acp set <key> <value>是通用路径。- 特殊情况:
key=cwd使用 cwd 覆盖路径。
- 特殊情况:
/acp reset-options清除目标会话的所有运行时覆盖。
acpx 助手支持(当前)
当前 acpx 内置助手别名:
claudecodexcopilotcursor(Cursor CLI:cursor-agent acp)droidgeminiiflowkilocodekimikiroopenclawopencodepiqwen
OpenClaw 使用 acpx 后端时,优先使用这些值作为 agentId,除非你的 acpx 配置定义了自定义 agent 别名。 如果你的本地 Cursor 安装仍将 ACP 暴露为 agent acp,在 acpx 配置中覆盖 cursor agent 命令,而不是更改内置默认值。
直接使用 acpx CLI 也可以通过 --agent <command> 指定任意适配器,但这是 acpx CLI 的原始转义接口(不是普通的 OpenClaw agentId 路径)。
必要配置
核心 ACP 基础配置:
json5
{
acp: {
enabled: true,
// 可选。默认为 true;设为 false 可暂停 ACP dispatch,同时保留 /acp 控制。
dispatch: { enabled: true },
backend: "acpx",
defaultAgent: "codex",
allowedAgents: [
"claude",
"codex",
"copilot",
"cursor",
"droid",
"gemini",
"iflow",
"kilocode",
"kimi",
"kiro",
"openclaw",
"opencode",
"pi",
"qwen",
],
maxConcurrentSessions: 8,
stream: {
coalesceIdleMs: 300,
maxChunkChars: 1200,
},
runtime: {
ttlMinutes: 120,
},
},
}Thread 绑定配置因频道适配器而异,Discord 示例:
json5
{
session: {
threadBindings: {
enabled: true,
idleHours: 24,
maxAgeHours: 0,
},
},
channels: {
discord: {
threadBindings: {
enabled: true,
spawnAcpSessions: true,
},
},
},
}如果 thread 绑定 ACP spawn 不工作,先验证适配器功能标志:
- Discord:
channels.discord.threadBindings.spawnAcpSessions=true
参见 配置参考。
acpx 后端插件设置
安装并启用插件:
bash
openclaw plugins install acpx
openclaw config set plugins.entries.acpx.enabled true开发时本地工作区安装:
bash
openclaw plugins install ./extensions/acpx然后验证后端健康状态:
text
/acp doctoracpx 命令和版本配置
默认情况下,内置 acpx 后端插件(acpx)使用插件本地固定的二进制文件:
- 命令默认为
extensions/acpx/node_modules/.bin/acpx。 - 期望版本默认为扩展固定版本。
- 启动时立即将 ACP 后端注册为未就绪状态。
- 后台 ensure 任务验证
acpx --version。 - 如果插件本地二进制文件缺失或版本不匹配,运行:
npm install --omit=dev --no-save acpx@<pinned>并重新验证。
可在插件配置中覆盖命令/版本:
json
{
"plugins": {
"entries": {
"acpx": {
"enabled": true,
"config": {
"command": "../acpx/dist/cli.js",
"expectedVersion": "any"
}
}
}
}
}注意事项:
command接受绝对路径、相对路径或命令名称(acpx)。- 相对路径从 OpenClaw 工作区目录解析。
expectedVersion: "any"禁用严格版本匹配。- 当
command指向自定义二进制/路径时,插件本地自动安装被禁用。 - OpenClaw 启动时不会阻塞,后台运行后端健康检查。
参见 Plugins。
权限配置
ACP 会话以非交互方式运行——没有 TTY 来批准或拒绝文件写入和 shell 执行权限提示。acpx 插件提供两个控制权限处理方式的配置 key:
permissionMode
控制助手 agent 无需提示即可执行哪些操作。
| 值 | 行为 |
|---|---|
approve-all | 自动批准所有文件写入和 shell 命令。 |
approve-reads | 自动批准读取;写入和执行需要提示。 |
deny-all | 拒绝所有权限提示。 |
nonInteractivePermissions
控制当本应显示权限提示但没有可用交互式 TTY 时(ACP 会话始终如此)的行为。
| 值 | 行为 |
|---|---|
fail | 以 AcpRuntimeError 中止会话。(默认) |
deny | 静默拒绝权限并继续(优雅降级)。 |
配置方式
通过插件配置设置:
bash
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。在非交互式 ACP 会话中,任何触发权限提示的写入或执行都可能以AcpRuntimeError: Permission prompt unavailable in non-interactive mode失败。如果需要限制权限,将
nonInteractivePermissions设为deny,这样会话优雅降级而不是崩溃。
故障排查
| 症状 | 可能原因 | 修复方法 |
|---|---|---|
ACP runtime backend is not configured | 后端插件缺失或已禁用。 | 安装并启用后端插件,然后运行 /acp doctor。 |
ACP is disabled by policy (acp.enabled=false) | ACP 全局禁用。 | 设置 acp.enabled=true。 |
ACP dispatch is disabled by policy (acp.dispatch.enabled=false) | 普通 thread 消息的 dispatch 已禁用。 | 设置 acp.dispatch.enabled=true。 |
ACP agent "<id>" is not allowed by policy | Agent 不在许可名单中。 | 使用许可的 agentId 或更新 acp.allowedAgents。 |
Unable to resolve session target: ... | 错误的 key/id/label token。 | 运行 /acp sessions,复制精确的 key/label,重试。 |
--thread here requires running /acp spawn inside an active ... thread | --thread here 在 thread 上下文外使用。 | 移到目标 thread 或使用 --thread auto/off。 |
Only <user-id> can rebind this thread. | 另一用户拥有 thread 绑定。 | 以所有者身份重新绑定,或使用不同 thread。 |
Thread bindings are unavailable for <channel>. | 适配器缺少 thread 绑定能力。 | 使用 --thread off 或移到支持的适配器/频道。 |
Sandboxed sessions cannot spawn ACP sessions ... | ACP 运行时在宿主机上;请求者会话处于沙箱中。 | 从沙箱会话中使用 runtime="subagent",或从非沙箱会话发起 ACP spawn。 |
sessions_spawn sandbox="require" is unsupported for runtime="acp" ... | ACP 运行时请求了 sandbox="require"。 | 使用 runtime="subagent" 强制沙箱,或对非沙箱会话使用 ACP with sandbox="inherit"。 |
| 绑定会话缺少 ACP 元数据 | 过期/已删除的 ACP 会话元数据。 | 用 /acp spawn 重新创建,然后重新绑定/聚焦 thread。 |
AcpRuntimeError: Permission prompt unavailable in non-interactive mode | permissionMode 阻止了非交互式 ACP 会话中的写入/执行。 | 将 plugins.entries.acpx.config.permissionMode 设为 approve-all 并重启 gateway。参见权限配置。 |
| ACP 会话提前以很少输出失败 | 权限提示被 permissionMode/nonInteractivePermissions 阻止。 | 检查 gateway 日志中的 AcpRuntimeError。完全权限设 permissionMode=approve-all;优雅降级设 nonInteractivePermissions=deny。 |
| ACP 会话在完成工作后无限期停滞 | 助手进程已完成但 ACP 会话未报告完成。 | 用 ps aux | grep acpx 监控;手动终止残留进程。 |