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 时使用此流程:

  1. 生成会话:
    • /acp spawn codex --mode persistent --thread auto
  2. 在绑定的 thread 中工作(或显式 targeting 该 session key)。
  3. 检查运行时状态:
    • /acp status
  4. 根据需要调整运行时选项:
    • /acp model <provider/model>
    • /acp permissions <profile>
    • /acp timeout <seconds>
  5. 在不替换 context 的情况下 nudge 活动会话:
    • /acp steer tighten logging and continue
  6. 停止工作:
    • /acp cancel(停止当前 turn),或
    • /acp close(关闭会话 + 移除 bindings)

人类快速入门

自然请求示例:

  • "在这里的 thread 中启动一个持久的 Codex 会话并保持专注。"
  • "将此作为一次性 Claude Code ACP 会话运行并总结结果。"
  • "在 thread 中使用 Gemini CLI 执行此任务,然后在同一 thread 中继续后续操作。"

OpenClaw 应该做什么:

  1. 选择 runtime: "acp"
  2. 解析请求的 harness target(agentId,例如 codex)。
  3. 如果请求了 thread binding 且当前 channel 支持,将 ACP 会话绑定到 thread。
  4. 将后续 thread 消息路由到同一个 ACP 会话,直到 unfocused/closed/expired。

ACP 与 sub-agents

当你想要外部 harness 运行时使用 ACP。当你想要 OpenClaw 原生 delegated runs 时使用 sub-agents。

AreaACP sessionSub-agent run
RuntimeACP backend plugin (例如 acpx)OpenClaw native sub-agent runtime
Session keyagent:<agentId>:acp:<uuid>agent:<agentId>:subagent:<uuid>
Main commands/acp .../subagents ...
Spawn toolsessions_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=true
  • acp.dispatch.enabled 默认开启(设置为 false 暂停 ACP dispatch)
  • Channel-adapter ACP thread-spawn flag 启用(adapter 特定)
    • Discord: channels.discord.threadBindings.spawnAcpSessions=true

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_spawn with runtime: "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>

Slash Commands

Session target resolution

大多数 /acp actions 接受可选的 session target(session-keysession-idsession-label)。

Resolution order:

  1. 显式 target 参数(或 /acp steer--session
    • 尝试 key
    • 然后 UUID-shaped session id
    • 然后 label
  2. 当前 thread binding(如果此 conversation/thread 绑定到 ACP 会话)
  3. 当前 requester session fallback

如果没有 target 解析,OpenClaw 返回清晰的错误(Unable to resolve session target: ...)。

Spawn thread modes

/acp spawn 支持 --thread auto|here|off

ModeBehavior
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

CommandWhat it doesExample
/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 setGeneric 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 doctorBackend 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 key model
  • /acp permissions <profile> 映射到 runtime config key approval_policy
  • /acp timeout <seconds> 映射到 runtime config key timeout
  • /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:

  • pi
  • claude
  • codex
  • opencode
  • gemini
  • kimi

当 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

Configuration Reference

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:

  1. Command 默认为 extensions/acpx/node_modules/.bin/acpx
  2. Expected version 默认为 extension pin。
  3. Startup registers ACP backend immediately as not-ready。
  4. A background ensure job verifies acpx --version
  5. 如果 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。

ValueBehavior
approve-allAuto-approve 所有 file writes 和 shell commands。
approve-readsAuto-approve reads only;writes 和 exec 需要 prompts。
deny-allDeny 所有 permission prompts。

nonInteractivePermissions

控制当 permission prompt 会被显示但没有 interactive TTY 可用时会发生什么(这在 ACP 会话中总是如此)。

ValueBehavior
failAcpRuntimeError 中止会话。(default)
denySilently 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-readsnonInteractivePermissions=fail。在 non-interactive ACP 会话中,任何触发 permission prompt 的 write 或 exec 都可能失败并显示 AcpRuntimeError: Permission prompt unavailable in non-interactive mode

如果你需要限制 permissions,将 nonInteractivePermissions 设置为 deny 以便会话 graceful degradation 而不是崩溃。

Troubleshooting

SymptomLikely causeFix
ACP runtime backend is not configuredBackend 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 policyAgent 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 sessionStale/deleted ACP session metadata。Recreate with /acp spawn, then rebind/focus thread。
AcpRuntimeError: Permission prompt unavailable in non-interactive modepermissionMode 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 outputPermission prompts are blocked by permissionMode/nonInteractivePermissionsCheck gateway logs for AcpRuntimeError. For full permissions, set permissionMode=approve-all; for graceful degradation, set nonInteractivePermissions=deny
ACP session stalls indefinitely after completing workHarness process finished but ACP session did not report completion。Monitor with ps aux | grep acpx; kill stale processes manually。