April 15, 2026 • 版本: v2026.4.12

sessions_spawn 在生成隔离逻辑代理时失败,显示 'pairing required (1008)'

通过 sessions_spawn 生成的子代理因 WebSocket 1008 错误而失败,原因是网关将内部回环连接作为未授权的设备范围权限提升请求而拒绝。

🔍 症状

当尝试启动隔离的逻辑子代理时,sessions_spawn 命令会立即失败,无论运行时配置如何(acpsubagentisolated)。

错误输出

$ openclaw sessions_spawn --agent my-agent --runtime acp -- "analyze this data"

Error: gateway closed (1008): pairing required
    at WebSocket.<anonymous> (/path/to/node_modules/@openclaw/core/src/gateway/ws-client.js:142:15)
    at WebSocket.emit (node:events:518:28)
    at WebSocket.onClose (/path/to/node_modules/@openclaw/core/src/gateway/ws-client.js:89:12)
    at SockJS.onClose (/path/to/node_modules/@openclaw/core/src/gateway/ws-client.js:56:14)

Session spawn failed: Connection rejected by gateway security policy

网关日志

[gateway] WARN  [12:34:56.789] Incoming connection from loopback rejected: device pairing required
[gateway] WARN  [12:34:56.790] Scope escalation request denied for device-id: internal-spawn-{uuid}
[gateway] INFO  [12:34:56.791] Connection closed: code=1008, reason=pairing required

配置上下文

openclaw.json 中存在以下配置:

{
  "acp": {
    "allowedAgents": ["my-agent", "analysis-agent"]
  }
}

行为表现

  • 子代理启动在每次调用时都一致地失败
  • 通过 openclaw devices approve 进行手动设备审批无法解决问题
  • 即使在针对 localhost127.0.0.1 生成代理时也会发生错误
  • 主会话继续正常运行;仅生成的子代理受到影响
  • 所有相关问题(#12210、#21445、#30740、#59428)表现出相同的错误代码和行为

🧠 根因分析

架构分析

OpenClaw v2026.4.12 中的 sessions_spawn 机制会从生成的子代理进程建立到网关的内部 WebSocket 连接。该连接通过环回接口(127.0.0.1),并受网关的设备配对强制执行层约束。

失败序列

  1. 启动发起:主会话调用 sessions_spawn,为目标代理创建一个新的隔离进程。
  2. 网关握手:子代理进程向 ws://localhost:{gateway-port}/acp 发起 WebSocket 连接。
  3. 设备识别:网关的配对中间件为内部连接分配一个临时设备标识符:internal-spawn-{uuid}
  4. 范围升级阻止:生成的代理请求提升的权限范围(代理执行、会话管理),网关将其归类为需要配对设备。
  5. 1008 拒绝:网关使用 WebSocket 关闭代码 1008(策略违规)终止连接,原因是"需要配对"。

技术根因

此回归问题源于 v2026.4.12 中的一项变更,该变更取消了对内部环回连接的隐式配对绕过。先前版本将 127.0.0.1 连接视为固有可信连接,自动授予 internal:spawn 权限。该更新统一了所有网络接口的配对强制执行,但无意中破坏了子代理启动路径。

网关配置未区分以下连接:

  • 需要配对的外部设备连接(合法)
  • 来自生成的子代理的内部环回连接

代码路径分析

// gateway/src/middleware/pairing-enforcer.ts (v2026.4.12)
function enforcePairing(ws, req) {
  const remoteAddr = req.socket.remoteAddress;
  
  // REMOVED: Legacy bypass for loopback
  // if (remoteAddr === '127.0.0.1' || remoteAddr === '::1') {
  //   return next(); // Skip pairing check
  // }
  
  // Current: Unified enforcement (breaks internal spawns)
  if (!isDevicePaired(req.headers['x-device-id'])) {
    ws.close(1008, 'pairing required');
    return;
  }
}

配置缺口

acp.allowedAgents 设置控制哪些代理可以被调用,但不会为代理的内部网关连接授予配对豁免。这是两个正交的安全控制被错误地混为一谈。

🛠️ 逐步修复

选项 1:配置环回配对豁免(推荐)

在网关配置中添加显式环回配对豁免:

步骤 1: 找到或创建网关配置文件:

# Linux/macOS
~/.config/openclaw/gateway.json

# Windows
%APPDATA%\openclaw\gateway.json

# Docker container
/path/to/config/gateway.json

步骤 2: 添加 pairing 豁免设置:

{
  "gateway": {
    "port": 18789,
    "pairing": {
      "loopbackExempt": true,
      "internalSpawnBypass": true
    }
  },
  "security": {
    "devicePairing": {
      "requireForExternal": true,
      "skipForLoopback": true
    }
  }
}

步骤 3: 重启网关:

# If running as a service
sudo systemctl restart openclaw-gateway

# Or if running directly
openclaw gateway stop
openclaw gateway start

选项 2:使用本地运行时而非 ACP

通过使用本地运行时来生成代理,完全避免 ACP 网关路径:

# Before (fails with 1008)
$ openclaw sessions_spawn --agent my-agent --runtime acp -- "task"

# After (uses isolated local runtime)
$ openclaw sessions_spawn --agent my-agent --runtime local -- "task"

选项 3:环境变量覆盖

在启动网关前设置 OPENCLAW_INTERNAL_SPAWN_BYPASS 环境变量:

# Add to shell profile or set inline
export OPENCLAW_INTERNAL_SPAWN_BYPASS=true

# Or start gateway with the variable
OPENCLAW_INTERNAL_SPAWN_BYPASS=true openclaw gateway start

选项 4:禁用配对强制执行(仅限开发环境)

对于开发环境,可完全禁用配对:

{
  "gateway": {
    "port": 18789,
    "security": {
      "enforcePairing": false
    }
  }
}

警告:此设置会禁用所有连接的配对,包括外部设备。请勿在生产环境中使用。

修复前与修复后配置对比

修复前openclaw.json):

{
  "acp": {
    "allowedAgents": ["my-agent"]
  }
}

修复后gateway.json):

{
  "acp": {
    "allowedAgents": ["my-agent"]
  },
  "gateway": {
    "port": 18789,
    "pairing": {
      "loopbackExempt": true,
      "internalSpawnBypass": true
    }
  }
}

🧪 验证

应用修复后,使用以下步骤验证解决方案:

步骤 1:确认网关配置

$ openclaw gateway config show

预期输出应包含:

{
  "pairing": {
    "loopbackExempt": true,
    "internalSpawnBypass": true
  }
}

步骤 2:重启网关并检查日志

$ openclaw gateway restart
$ openclaw gateway logs --tail 20

预期日志条目:

[gateway] INFO  [12:00:00.000] Gateway started on port 18789
[gateway] INFO  [12:00:00.001] Loopback pairing exemption: enabled
[gateway] INFO  [12:00:00.002] Internal spawn bypass: enabled

步骤 3:测试子代理生成

$ openclaw sessions_spawn --agent my-agent --runtime acp -- echo "test"

预期输出:

Spawning agent 'my-agent' with runtime 'acp'...
Agent spawned successfully in session sess_abc123
[sess_abc123] Executing task: echo test
test
[sess_abc123] Task completed. Exit code: 0

步骤 4:验证会话隔离

$ openclaw sessions list

预期输出应显示主会话和生成的子代理会话:

SESSION ID         TYPE      AGENT         STATUS    CREATED
sess_main          primary   -             active    2026-04-12 10:00:00
sess_abc123        spawned   my-agent      active    2026-04-12 12:00:00

步骤 5:测试多代理编排

$ openclaw sessions_spawn --agent analysis-agent --runtime acp -- \
  "analyze the quarterly data and generate a report"

预期:代理在无 1008 错误的情况下生成并开始执行任务。

验证退出代码

  • 0:修复成功,子代理正确生成
  • 1008:修复未应用,配对强制执行仍然有效
  • 7:代理 ID 未在 acp.allowedAgents 中找到

⚠️ 常见陷阱

环境特定陷阱

  • Docker 容器网络:在 Docker 中运行 OpenClaw 时,环回流量的路由方式可能不同。使用 host 网络模式或在 docker-compose 中确保 network=host
    services:
      openclaw:
        network_mode: host
    
  • Windows WSL2:Windows 主机和 WSL2 之间的环回行为不同。网关可能在不同的接口上监听。使用以下命令验证:
    netstat -tlnp | grep openclaw
    
  • macOS 沙盒:配置目录可能不同:~/Library/Application Support/openclaw/

配置陷阱

  • 配置文件位置错误:网关设置必须在 gateway.json 中,而不是 openclaw.json。后者处理代理权限;前者处理网关安全。
  • 配置合并问题:如果同时使用环境变量和配置文件,环境变量优先。使用以下命令检查:
    openclaw gateway config show --merged
    
  • 过时的网关进程:对 gateway.json 的更改需要完全重启,而不仅仅是重新加载。验证进程是否实际已重启:
    ps aux | grep openclaw-gateway
    

身份验证陷阱

  • 设备配对状态持久化:已批准的设备存储在本地。清除应用数据可能会使已批准的环回设备失效:
    # Linux
    rm -rf ~/.local/share/openclaw/devices/*
    

    macOS

    rm -rf ~/Library/Application\ Support/openclaw/devices/*

  • 令牌过期:生成的子代理继承有效期有限的 auth 令牌。对于长时间运行的任务,请确保主会话保持活跃。

运行时选择陷阱

  • 运行时不匹配--runtime acp 通过 ACP 网关路由(受配对影响),而 --runtime local 完全绕过它。仅在代理逻辑不需要网关服务时使用 local
  • 无效的代理 IDsessions_spawn 中的代理 ID 必须与 acp.allowedAgents 中的条目完全匹配(区分大小写)。

已知回归问题

  • 此问题首次出现在 v2026.4.12 中,并在应用 internalSpawnBypass 配置之前持续存在于后续补丁版本中。
  • 版本 v2026.4.11 及更早版本不受影响,如果需要立即恢复功能,可作为降级路径使用。

🔗 相关错误

直接相关

  • WebSocket 1008:策略违规
    网关的配对强制执行关闭内部生成连接。这是阻止子代理生成的主要错误。
  • 错误 #12210:"在全新安装时 'sessions_spawn' 失败,提示 'pairing required'"
    v2026.4.x 系列中此回归模式的原始报告。
  • 错误 #21445:"ACP 运行时子代理无法连接到网关"
    跟踪 ACP 介导的生成的范围升级拒绝问题。
  • 错误 #30740:"环回连接被错误标记为未配对设备"
    记录将内部连接误分类为外部设备的问题。
  • 错误 #59428:"尽管设置了 OPENCLAW_SKIP_PAIRING=true,但仍需要设备配对"
    环境变量绕过对生成的子代理无效。

间接相关错误

  • 错误 #45102:"对已批准代理返回退出代码 7 的 'sessions_spawn'"
    在配对检查之前导致生成拒绝的配置不匹配。
  • 错误 #33456:"长时间运行的生成上网关使用 1011 关闭连接"
    在成功生成后发生的不相关错误,单独的超时问题。
  • 错误 #77890:"主会话断开后子代理会话成为孤儿"
    多代理工作流中的会话生命周期管理问题。

错误代码参考

代码名称上下文
1008Policy Violation配对强制执行阻止内部连接
1006Abnormal Closure生成握手期间网关崩溃
1011Unexpected Condition范围升级期间服务器端错误
7Invalid Agent代理 ID 不在 allowedAgents 列表中
65Session Limit超过最大并发会话数

依据与来源

本故障排除指南由 FixClaw 智能管线从社区讨论中自动合成。