Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt

Use this file to discover all available pages before exploring further.

私有 QA 栈用于以比单个单元测试更真实、更贴近渠道形态的方式演练 OpenClaw。 当前组件:
  • extensions/qa-channel:合成消息渠道,包含私信、渠道、线程、回应、编辑和删除表面。
  • extensions/qa-lab:调试器 UI 和 QA 总线,用于观察转录、注入入站消息,并导出 Markdown 报告。
  • extensions/qa-matrix、未来的运行器插件:实时传输适配器,在子 QA Gateway 网关内驱动真实渠道。
  • qa/:由仓库支持的种子资产,用于启动任务和基线 QA 场景。
  • Mantis:针对需要真实传输、浏览器截图、VM 状态和 PR 证据的 bug,进行修复前和修复后的实时验证。

命令表面

每个 QA 流程都在 pnpm openclaw qa <subcommand> 下运行。许多命令有 pnpm qa:* 脚本别名;两种形式都受支持。
命令用途
qa run内置 QA 自检;写入 Markdown 报告。
qa suite针对 QA Gateway 网关通道运行由仓库支持的场景。别名:pnpm openclaw qa suite --runner multipass,用于一次性 Linux VM。
qa coverage打印 Markdown 场景覆盖率清单(--json 用于机器输出)。
qa parity-report比较两个 qa-suite-summary.json 文件,并写入智能体式一致性报告。
qa character-eval跨多个实时模型运行角色 QA 场景,并生成经过评判的报告。请参阅报告
qa manual针对选定的提供商/模型通道运行一次性提示词。
qa ui启动 QA 调试器 UI 和本地 QA 总线(别名:pnpm qa:lab:ui)。
qa docker-build-image构建预烘焙的 QA Docker 镜像。
qa docker-scaffold为 QA 仪表板 + Gateway 网关通道写入 docker-compose 脚手架。
qa up构建 QA 站点,启动 Docker 支持的栈,并打印 URL(别名:pnpm qa:lab:up:fast 变体会添加 --use-prebuilt-image --bind-ui-dist --skip-ui-build)。
qa aimock只启动 AIMock 提供商服务器。
qa mock-openai只启动感知场景的 mock-openai 提供商服务器。
qa credentials doctor / add / list / remove管理共享的 Convex 凭证池。
qa matrix针对一次性 Tuwunel homeserver 的实时传输通道。请参阅 Matrix QA
qa telegram针对真实私有 Telegram 群组的实时传输通道。
qa discord针对真实私有 Discord guild 渠道的实时传输通道。
qa slack针对真实私有 Slack 渠道的实时传输通道。
qa mantis用于实时传输 bug 的修复前和修复后验证运行器,提供 Discord 状态回应证据、Crabbox 桌面/浏览器烟雾测试,以及 Slack-in-VNC 烟雾测试。请参阅 MantisMantis Slack 桌面运行手册

操作员流程

当前 QA 操作员流程是一个双窗格 QA 站点:
  • 左侧:带有智能体的 Gateway 网关仪表板(Control UI)。
  • 右侧:QA Lab,显示类似 Slack 的转录和场景计划。
运行方式:
pnpm qa:lab:up
这会构建 QA 站点,启动 Docker 支持的 Gateway 网关通道,并公开 QA Lab 页面;操作员或自动化循环可以在该页面给智能体分配 QA 任务,观察真实渠道行为,并记录哪些可用、哪些失败或哪些仍被阻塞。 为了更快迭代 QA Lab UI,而不是每次都重新构建 Docker 镜像,请使用绑定挂载的 QA Lab 包启动栈:
pnpm openclaw qa docker-build-image
pnpm qa:lab:build
pnpm qa:lab:up:fast
pnpm qa:lab:watch
qa:lab:up:fast 会让 Docker 服务使用预构建镜像,并把 extensions/qa-lab/web/dist 绑定挂载到 qa-lab 容器中。qa:lab:watch 会在变更时重建该包,并且当 QA Lab 资产哈希变化时,浏览器会自动重新加载。 对于本地 OpenTelemetry 跟踪烟雾测试,运行:
pnpm qa:otel:smoke
该脚本会启动本地 OTLP/HTTP 跟踪接收器,在启用 diagnostics-otel 插件的情况下运行 otel-trace-smoke QA 场景,然后解码导出的 protobuf span,并断言发布关键形状:必须存在 openclaw.runopenclaw.harness.runopenclaw.model.callopenclaw.context.assembledopenclaw.message.delivery;成功轮次中的模型调用不得导出 StreamAbandoned;原始诊断 ID 和 openclaw.content.* 属性必须留在跟踪之外。它会在 QA 套件工件旁写入 otel-smoke-summary.json 可观测性 QA 仅保留在源码检出中。npm tarball 会有意省略 QA Lab,因此包 Docker 发布通道不会运行 qa 命令。更改诊断插桩时,请从已构建的源码检出运行 pnpm qa:otel:smoke 对于真实传输的 Matrix 烟雾测试通道,运行:
pnpm openclaw qa matrix --profile fast --fail-fast
该通道的完整 CLI 参考、配置文件/场景目录、环境变量和工件布局位于 Matrix QA。简要来说:它会在 Docker 中预置一次性 Tuwunel homeserver,注册临时 driver/SUT/observer 用户,在限定到该传输的子 QA Gateway 网关中运行真实 Matrix 插件(不使用 qa-channel),然后在 .artifacts/qa-e2e/matrix-<timestamp>/ 下写入 Markdown 报告、JSON 摘要、observed-events 工件和合并输出日志。 这些场景覆盖单元测试无法端到端证明的传输行为:提及门控、allow-bot 策略、allowlist、顶层回复和线程回复、私信路由、回应处理、入站编辑抑制、重启重放去重、homeserver 中断恢复、审批元数据递送、媒体处理,以及 Matrix E2EE 引导/恢复/验证流程。E2EE CLI 配置文件还会通过同一个一次性 homeserver 驱动 openclaw matrix encryption setup 和验证命令,然后再检查 Gateway 网关回复。 Discord 也有仅限 Mantis、需要选择启用的 bug 复现场景。使用 --scenario discord-status-reactions-tool-only 获取明确的状态回应时间线,或使用 --scenario discord-thread-reply-filepath-attachment 创建真实 Discord 线程,并验证 message.thread-reply 保留 filePath 附件。这些场景不在默认实时 Discord 通道中,因为它们是修复前/修复后复现探针,而不是广泛烟雾覆盖。线程附件 Mantis 工作流还可以在 QA 环境中配置了 MANTIS_DISCORD_VIEWER_CHROME_PROFILE_DIRMANTIS_DISCORD_VIEWER_CHROME_PROFILE_TGZ_B64 时,添加已登录 Discord Web 的见证视频。该查看器配置文件仅用于视觉捕获;通过/失败判断仍来自 Discord REST oracle。 CI 在 .github/workflows/qa-live-transports-convex.yml 中使用同一命令表面。定时运行和默认手动运行会使用实时前沿凭证、--fastOPENCLAW_QA_MATRIX_NO_REPLY_WINDOW_MS=3000 执行 fast Matrix 配置文件。手动 matrix_profile=all 会分散到五个配置文件分片,使完整目录可以并行运行,同时每个分片保留一个工件目录。 对于真实传输的 Telegram、Discord 和 Slack 烟雾测试通道:
pnpm openclaw qa telegram
pnpm openclaw qa discord
pnpm openclaw qa slack
它们以一个预先存在的真实渠道为目标,并使用两个机器人(driver + SUT)。所需环境变量、场景列表、输出工件和 Convex 凭证池记录在下面的 Telegram、Discord 和 Slack QA 参考中。 如需运行带 VNC 救援的完整 Slack 桌面 VM,请运行:
pnpm openclaw qa mantis slack-desktop-smoke \
  --gateway-setup \
  --scenario slack-canary \
  --keep-lease
该命令会租用一台 Crabbox 桌面/浏览器机器,在 VM 内运行 Slack 实时通道,在 VNC 浏览器中打开 Slack Web,捕获桌面,并在视频捕获可用时,将 slack-qa/slack-desktop-smoke.pngslack-desktop-smoke.mp4 复制回 Mantis 构件目录。Crabbox 桌面/浏览器租约会预先提供捕获工具和浏览器/原生构建辅助包,因此该场景只应在较旧租约上安装回退项。Mantis 会在 mantis-slack-desktop-smoke-report.md 中报告总耗时和各阶段耗时,因此运行缓慢时可以看出时间是花在租约预热、凭证获取、远程设置还是构件复制上。通过 VNC 手动登录 Slack Web 后,使用 --lease-id <cbx_...> 复用租约;复用的租约也会保持 Crabbox 的 pnpm store 缓存为热状态。默认的 --hydrate-mode source 会从源码 checkout 验证,并在 VM 内运行安装/构建。仅当复用的远程工作区已经有 node_modules 和构建好的 dist/ 时,才使用 --hydrate-mode prehydrated;该模式会跳过昂贵的安装/构建步骤,并在工作区未就绪时封闭失败。使用 --gateway-setup 时,Mantis 会在 VM 内留下一个持久运行的 OpenClaw Slack Gateway 网关,端口为 38973;不使用它时,该命令会运行常规的机器人到机器人 Slack QA 通道,并在捕获构件后退出。 操作员检查清单、GitHub workflow 派发命令、证据评论契约、hydrate-mode 决策表、耗时解读和失败处理步骤位于 Mantis Slack 桌面运行手册 如需运行智能体/CV 风格的桌面任务,请运行:
pnpm openclaw qa mantis visual-task \
  --browser-url https://example.net \
  --expect-text "Example Domain" \
  --vision-model openai/gpt-5.4
visual-task 会租用或复用一台 Crabbox 桌面/浏览器机器,启动 crabbox record --while,通过嵌套的 visual-driver 驱动可见浏览器,捕获 visual-task.png,在选择 --vision-mode image-describe 时针对截图运行 openclaw infer image describe,并写入 visual-task.mp4mantis-visual-task-summary.jsonmantis-visual-task-driver-result.jsonmantis-visual-task-report.md。设置 --expect-text 后,视觉提示会要求返回结构化 JSON 判定,并且只有当模型报告有正向可见证据时才通过;仅仅引用目标文本的负向响应会使断言失败。使用 --vision-mode metadata 可进行不调用图像理解提供商的无模型冒烟测试,以证明桌面、浏览器、截图和视频管线可用。录制是 visual-task 的必需构件;如果 Crabbox 未录制出非空的 visual-task.mp4,即使视觉驱动器已通过,任务也会失败。失败时,除非任务已经通过且未设置 --keep-lease,否则 Mantis 会保留租约以供 VNC 使用。 在使用池化实时凭证之前,请运行:
pnpm openclaw qa credentials doctor
Doctor 会检查 Convex broker 环境变量,验证端点设置,并在存在维护者 secret 时验证 admin/list 可达性。它只报告 secret 的已设置/缺失状态。

实时传输覆盖范围

实时传输通道共享同一个契约,而不是各自发明自己的场景列表形状。qa-channel 是广泛的合成产品行为套件,不属于实时传输覆盖矩阵。
通道金丝雀提及门控机器人到机器人allowlist 拦截顶层回复重启恢复线程跟进线程隔离reaction 观察help 命令原生命令注册
Matrixxxxxxxxxx
Telegramxxxx
Discordxxxx
Slackxxxxxxxx
这会让 qa-channel 继续作为广泛的产品行为套件,同时让 Matrix、Telegram 和未来的实时传输共享一个明确的传输契约检查清单。 如需运行一次不把 Docker 带入 QA 路径的一次性 Linux VM 通道,请运行:
pnpm openclaw qa suite --runner multipass --scenario channel-chat-baseline
这会启动一个全新的 Multipass guest,安装依赖,在 guest 内构建 OpenClaw,运行 qa suite,然后把常规 QA 报告和摘要复制回主机上的 .artifacts/qa-e2e/...。 它会复用主机上 qa suite 的同一套场景选择行为。 主机和 Multipass 套件运行默认会用隔离的 Gateway 网关 worker 并行执行多个选定场景。qa-channel 默认并发数为 4,受所选场景数量限制。使用 --concurrency <count> 调整 worker 数量,或使用 --concurrency 1 进行串行执行。 只要任何场景失败,该命令就会以非零状态退出。如果你希望获取构件但不让退出码失败,请使用 --allow-failures。 实时运行会转发 guest 可实际使用的受支持 QA 认证输入:基于环境变量的提供商密钥、QA 实时提供商配置路径,以及存在时的 CODEX_HOME。请将 --output-dir 保持在仓库根目录下,以便 guest 可以通过挂载的工作区写回。

Telegram、Discord 和 Slack QA 参考

Matrix 有一个专用页面,因为它的场景数量较多,并且需要 Docker 支持的 homeserver 预配。Telegram、Discord 和 Slack 更小,每个只有少量场景,没有 profile 系统,并且针对预先存在的真实渠道,因此它们的参考内容放在这里。

共享 CLI 标志

这些通道通过 extensions/qa-lab/src/live-transports/shared/live-transport-cli.ts 注册,并接受相同的标志:
标志默认值描述
--scenario <id>-只运行此场景。可重复指定。
--output-dir <path><repo>/.artifacts/qa-e2e/{telegram,discord,slack}-<timestamp>写入报告、摘要、观察到的消息和输出日志的位置。相对路径会相对于 --repo-root 解析。
--repo-root <path>process.cwd()从中立 cwd 调用时的仓库根目录。
--sut-account <id>sutQA Gateway 网关配置中的临时账号 id。
--provider-mode <mode>live-frontiermock-openailive-frontier(旧版 live-openai 仍可使用)。
--model <ref> / --alt-model <ref>provider 默认值主/备用模型 ref。
--fast关闭提供商支持时的快速模式。
--credential-source <env|convex>env参见 Convex 凭证池
--credential-role <maintainer|ci>CI 中为 ci,否则为 maintainer--credential-source convex 时使用的角色。
只要任一场景失败,每个通道都会以非零状态退出。--allow-failures 会写入构件,但不会设置失败退出码。

Telegram QA

pnpm openclaw qa telegram
目标是一个真实的私有 Telegram 群组,其中有两个不同的机器人(driver + SUT)。SUT 机器人必须有 Telegram 用户名;当两个机器人都在 @BotFather 中启用 Bot-to-Bot Communication Mode 时,机器人到机器人的观察效果最好。 使用 --credential-source env 时必需的环境变量:
  • OPENCLAW_QA_TELEGRAM_GROUP_ID - 数字 chat id(字符串)。
  • OPENCLAW_QA_TELEGRAM_DRIVER_BOT_TOKEN
  • OPENCLAW_QA_TELEGRAM_SUT_BOT_TOKEN
可选:
  • OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1 会在观察消息构件中保留消息正文(默认会遮蔽)。
场景(extensions/qa-lab/src/live-transports/telegram/telegram-live.runtime.ts):
  • telegram-canary
  • telegram-mention-gating
  • telegram-mentioned-message-reply
  • telegram-help-command
  • telegram-commands-command
  • telegram-tools-compact-command
  • telegram-whoami-command
  • telegram-status-command
  • telegram-repeated-command-authorization
  • telegram-other-bot-command-gating
  • telegram-context-command
  • telegram-current-session-status-tool
  • telegram-reply-chain-exact-marker
  • telegram-stream-final-single-message
  • telegram-long-final-reuses-preview
  • telegram-long-final-three-chunks
隐式默认集合始终覆盖金丝雀、提及门控、原生命令回复、命令寻址和机器人到机器人群组回复。mock-openai 默认值还包括确定性的回复链和最终消息流式传输检查。telegram-current-session-status-tool 仍然是选择加入项,因为它只在紧接金丝雀之后直接串联时稳定,而不是在任意原生命令回复之后稳定。使用 pnpm openclaw qa telegram --list-scenarios --provider-mode mock-openai 可打印带回归 ref 的当前默认/可选拆分。 输出构件:
  • telegram-qa-report.md
  • telegram-qa-summary.json - 从金丝雀开始,包含每条回复的 RTT(driver 发送 → 观察到 SUT 回复)。
  • telegram-qa-observed-messages.json - 除非设置 OPENCLAW_QA_TELEGRAM_CAPTURE_CONTENT=1,否则正文会被遮蔽。

Discord QA

pnpm openclaw qa discord
目标是一个真实的私有 Discord guild channel,其中有两个机器人:一个由 harness 控制的 driver 机器人,以及一个由子 OpenClaw Gateway 网关通过内置 Discord 插件启动的 SUT 机器人。验证频道提及处理、SUT 机器人是否已向 Discord 注册原生 /help 命令,以及选择加入的 Mantis 证据场景。 使用 --credential-source env 时必需的环境变量:
  • OPENCLAW_QA_DISCORD_GUILD_ID
  • OPENCLAW_QA_DISCORD_CHANNEL_ID
  • OPENCLAW_QA_DISCORD_DRIVER_BOT_TOKEN
  • OPENCLAW_QA_DISCORD_SUT_BOT_TOKEN
  • OPENCLAW_QA_DISCORD_SUT_APPLICATION_ID - 必须匹配 Discord 返回的 SUT 机器人用户 ID(否则该通道会快速失败)。
可选:
  • OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1 会在观测消息产物中保留消息正文。
  • OPENCLAW_QA_DISCORD_VOICE_CHANNEL_IDdiscord-voice-autojoin 选择语音/舞台频道;如果未设置,场景会为 SUT 机器人选择第一个可见的语音/舞台频道。
场景(extensions/qa-lab/src/live-transports/discord/discord-live.runtime.ts:36):
  • discord-canary
  • discord-mention-gating
  • discord-native-help-command-registration
  • discord-voice-autojoin - 需要显式启用的语音场景。单独运行,启用 channels.discord.voice.autoJoin,并验证 SUT 机器人当前的 Discord 语音状态是目标语音/舞台频道。Convex Discord 凭证可以包含可选的 voiceChannelId;否则运行器会发现服务器中第一个可见的语音/舞台频道。
  • discord-status-reactions-tool-only - 需要显式启用的 Mantis 场景。它会单独运行,因为它会把 SUT 切换为始终在线、仅工具的服务器回复模式,并设置 messages.statusReactions.enabled=true,然后捕获 REST 反应时间线以及 HTML/PNG 可视产物。Mantis 前后对比报告还会把场景提供的 MP4 产物保留为 baseline.mp4candidate.mp4
显式运行 Discord 语音自动加入场景:
pnpm openclaw qa discord \
  --scenario discord-voice-autojoin \
  --provider-mode mock-openai
显式运行 Mantis 状态反应场景:
pnpm openclaw qa discord \
  --scenario discord-status-reactions-tool-only \
  --provider-mode live-frontier \
  --model openai/gpt-5.4 \
  --alt-model openai/gpt-5.4 \
  --fast
输出产物:
  • discord-qa-report.md
  • discord-qa-summary.json
  • discord-qa-observed-messages.json - 正文会被遮盖,除非设置了 OPENCLAW_QA_DISCORD_CAPTURE_CONTENT=1
  • 运行状态反应场景时会生成 discord-qa-reaction-timelines.jsondiscord-status-reactions-tool-only-timeline.png

Slack QA

pnpm openclaw qa slack
目标是一个真实的私有 Slack 渠道,其中有两个不同的机器人:由 harness 控制的驱动机器人,以及由子 OpenClaw Gateway 网关通过内置 Slack 插件启动的 SUT 机器人。 使用 --credential-source env 时必需的环境变量:
  • OPENCLAW_QA_SLACK_CHANNEL_ID
  • OPENCLAW_QA_SLACK_DRIVER_BOT_TOKEN
  • OPENCLAW_QA_SLACK_SUT_BOT_TOKEN
  • OPENCLAW_QA_SLACK_SUT_APP_TOKEN
可选:
  • OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1 会在观测消息产物中保留消息正文。
场景(extensions/qa-lab/src/live-transports/slack/slack-live.runtime.ts:39):
  • slack-canary
  • slack-mention-gating
  • slack-allowlist-block
  • slack-top-level-reply-shape
  • slack-restart-resume
  • slack-thread-follow-up
  • slack-thread-isolation
输出产物:
  • slack-qa-report.md
  • slack-qa-summary.json
  • slack-qa-observed-messages.json - 正文会被遮盖,除非设置了 OPENCLAW_QA_SLACK_CAPTURE_CONTENT=1

设置 Slack 工作区

该通道需要在一个工作区中有两个不同的 Slack 应用,以及一个两个机器人都加入的渠道:
  • channelId - 两个机器人都已受邀加入的渠道的 Cxxxxxxxxxx ID。请使用专用渠道;该通道每次运行都会发帖。
  • driverBotToken - Driver 应用的机器人令牌(xoxb-...)。
  • sutBotToken - SUT 应用的机器人令牌(xoxb-...),它必须是与驱动机器人不同的独立 Slack 应用,这样它的机器人用户 ID 才不同。
  • sutAppToken - SUT 应用的应用级令牌(xapp-...),带有 connections:write,供 Socket Mode 使用,以便 SUT 应用可以接收事件。
优先使用专用于 QA 的 Slack 工作区,而不是复用生产工作区。 下面的 SUT 清单有意将内置 Slack 插件的生产安装(extensions/slack/src/setup-shared.ts:10)收窄到实时 Slack QA 套件覆盖的权限和事件。对于用户看到的生产渠道设置,请参阅 Slack 渠道快速设置;QA Driver/SUT 组合有意分离,因为该通道需要在一个工作区中有两个不同的机器人用户 ID。 1. 创建 Driver 应用 前往 api.slack.com/appsCreate New AppFrom a manifest → 选择 QA 工作区,粘贴以下清单,然后 Install to Workspace
{
  "display_information": {
    "name": "OpenClaw QA Driver",
    "description": "Test driver bot for OpenClaw QA Slack live lane"
  },
  "features": {
    "bot_user": {
      "display_name": "OpenClaw QA Driver",
      "always_online": true
    }
  },
  "oauth_config": {
    "scopes": {
      "bot": ["chat:write", "channels:history", "groups:history", "users:read"]
    }
  },
  "settings": {
    "socket_mode_enabled": false
  }
}
复制 Bot User OAuth Tokenxoxb-...)- 它会成为 driverBotToken。驱动机器人只需要发送消息并识别自身;不需要事件,也不需要 Socket Mode。 2. 创建 SUT 应用 在同一工作区中重复 Create New App → From a manifest。这个 QA 应用有意使用内置 Slack 插件生产清单(extensions/slack/src/setup-shared.ts:10)的更窄版本:反应作用域和事件被省略,因为实时 Slack QA 套件尚未覆盖反应处理。
{
  "display_information": {
    "name": "OpenClaw QA SUT",
    "description": "OpenClaw QA SUT connector for OpenClaw"
  },
  "features": {
    "bot_user": {
      "display_name": "OpenClaw QA SUT",
      "always_online": true
    },
    "app_home": {
      "home_tab_enabled": true,
      "messages_tab_enabled": true,
      "messages_tab_read_only_enabled": false
    }
  },
  "oauth_config": {
    "scopes": {
      "bot": [
        "app_mentions:read",
        "assistant:write",
        "channels:history",
        "channels:read",
        "chat:write",
        "commands",
        "emoji:read",
        "files:read",
        "files:write",
        "groups:history",
        "groups:read",
        "im:history",
        "im:read",
        "im:write",
        "mpim:history",
        "mpim:read",
        "mpim:write",
        "pins:read",
        "pins:write",
        "usergroups:read",
        "users:read"
      ]
    }
  },
  "settings": {
    "socket_mode_enabled": true,
    "event_subscriptions": {
      "bot_events": [
        "app_home_opened",
        "app_mention",
        "channel_rename",
        "member_joined_channel",
        "member_left_channel",
        "message.channels",
        "message.groups",
        "message.im",
        "message.mpim",
        "pin_added",
        "pin_removed"
      ]
    }
  }
}
Slack 创建应用后,在它的设置页面上完成两件事:
  • Install to Workspace → 复制 Bot User OAuth Token → 它会成为 sutBotToken
  • Basic Information → App-Level Tokens → Generate Token and Scopes → 添加作用域 connections:write → 保存 → 复制 xapp-... 值 → 它会成为 sutAppToken
通过分别对每个令牌调用 auth.test 来验证两个机器人具有不同的用户 ID。运行时通过用户 ID 区分驱动机器人和 SUT;为两者复用同一个应用会让提及门控立即失败。 3. 创建渠道 在 QA 工作区中创建一个渠道(例如 #openclaw-qa),并在渠道内邀请两个机器人:
/invite @OpenClaw QA Driver
/invite @OpenClaw QA SUT
channel info → About → Channel ID 复制 Cxxxxxxxxxx ID - 它会成为 channelId。公共渠道可以使用;如果使用私有渠道,两个应用已经拥有 groups:history,因此 harness 的历史读取仍会成功。 4. 注册凭证 有两种选择。对单机调试使用环境变量(设置四个 OPENCLAW_QA_SLACK_* 变量并传入 --credential-source env),或写入共享 Convex 池,让 CI 和其他维护者可以租用它们。 对于 Convex 池,将四个字段写入 JSON 文件:
{
  "channelId": "Cxxxxxxxxxx",
  "driverBotToken": "xoxb-...",
  "sutBotToken": "xoxb-...",
  "sutAppToken": "xapp-..."
}
在你的 shell 中导出 OPENCLAW_QA_CONVEX_SITE_URLOPENCLAW_QA_CONVEX_SECRET_MAINTAINER 后,注册并验证:
pnpm openclaw qa credentials add \
  --kind slack \
  --payload-file slack-creds.json \
  --note "QA Slack pool seed"

pnpm openclaw qa credentials list --kind slack --status all --json
预期为 count: 1status: "active",且没有 lease 字段。 5. 端到端验证 在本地运行该通道,确认两个机器人可以通过代理彼此对话:
pnpm openclaw qa slack \
  --credential-source convex \
  --credential-role maintainer \
  --output-dir .artifacts/qa-e2e/slack-local
一次绿色运行会在远少于 30 秒内完成,且 slack-qa-report.md 显示 slack-canaryslack-mention-gating 的状态都是 pass。如果该通道挂起约 90 秒并以 Convex credential pool exhausted for kind "slack" 退出,要么池为空,要么每一行都已被租用 - qa credentials list --kind slack --status all --json 会告诉你是哪一种情况。

Convex 凭证池

Telegram、Discord、Slack 和 WhatsApp 通道可以从共享 Convex 池租用凭证,而不是读取上面的环境变量。传入 --credential-source convex(或设置 OPENCLAW_QA_CREDENTIAL_SOURCE=convex);QA Lab 会获取一个独占租约,在运行期间为其发送 Heartbeat,并在关闭时释放。池类型为 "telegram""discord""slack""whatsapp" 代理在 admin/add 上验证的载荷形状:
  • Telegram(kind: "telegram"):{ groupId: string, driverToken: string, sutToken: string } - groupId 必须是数字聊天 ID 字符串。
  • Telegram 真实用户(kind: "telegram-user"):{ groupId: string, sutToken: string, testerUserId: string, testerUsername: string, telegramApiId: string, telegramApiHash: string, tdlibDatabaseEncryptionKey: string, tdlibArchiveBase64: string, tdlibArchiveSha256: string, desktopTdataArchiveBase64: string, desktopTdataArchiveSha256: string } - 一个独占的一次性账号租约,同时供 TDLib CLI 驱动和 Telegram Desktop 可视见证使用。
  • Discord(kind: "discord"):{ guildId: string, channelId: string, driverBotToken: string, sutBotToken: string, sutApplicationId: string }
  • WhatsApp(kind: "whatsapp"):{ driverPhoneE164: string, sutPhoneE164: string, driverAuthArchiveBase64: string, sutAuthArchiveBase64: string, groupJid?: string } - 电话号码必须是不同的 E.164 字符串。
对于可视化真实用户 Telegram 证明,优先使用保持的 Crabbox 会话:
pnpm qa:telegram-user:crabbox -- start --tdlib-url http://artifacts.openclaw.ai/tdlib-v1.8.0-linux-x64.tgz --output-dir .artifacts/qa-e2e/telegram-user-crabbox/pr-review
pnpm qa:telegram-user:crabbox -- send --session .artifacts/qa-e2e/telegram-user-crabbox/pr-review/session.json --text /status
pnpm qa:telegram-user:crabbox -- finish --session .artifacts/qa-e2e/telegram-user-crabbox/pr-review/session.json
start 会持有一个独占 Convex telegram-user 租约,供 TDLib CLI 驱动和 Telegram Desktop 见证同时使用,启动桌面录制,并保持 Crabbox 存活,以便执行任意由智能体驱动的复现步骤。智能体可以使用 sendrunscreenshotstatus,直到满意为止,然后 finish 会在释放凭证前收集截图、视频、运动裁剪后的视频/GIF、TDLib 探测输出 和日志。publish --session <file> --pr <number> 默认只评论运动 GIF;--full-artifacts 是对日志和 JSON 输出的 显式选择加入。默认的 probe 命令仍是用于快速 /status 冒烟检查的 单命令简写。 当 PR 需要确定性的视觉 diff 时,使用 --mock-response-file <path>: 在 Telegram 格式化器或投递层发生变化时,可以在 main 和 PR head 上运行同一份 mock 模型回复。捕获默认值针对 PR 评论做了调优:标准 Crabbox 类、24fps 桌面录制、24fps 动态 GIF,以及 1920px 预览宽度。前后对比评论应发布一个干净的 bundle,其中只包含预期的 GIF。 Slack lane 也可以使用该池。Slack payload 形状检查目前位于 Slack QA runner 中,而不是 broker 中;请使用 { channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string },并使用类似 Cxxxxxxxxxx 的 Slack 渠道 id。请参阅 设置 Slack workspace,了解 app 和 scope 配置。 操作环境变量和 Convex broker 端点契约位于 测试 → 通过 Convex 共享 Telegram 凭据(该小节名称早于多渠道池;lease 语义在各类型之间共享)。

repo 支持的 seeds

Seed 资产位于 qa/
  • qa/scenarios/index.md
  • qa/scenarios/<theme>/*.md
这些文件有意提交到 git 中,以便 QA plan 对人类和智能体都可见。 qa-lab 应保持为通用 markdown runner。每个场景 markdown 文件都是一次测试运行的事实来源,并应定义:
  • 场景元数据
  • 可选的 category、capability、lane 和 risk 元数据
  • 文档和代码引用
  • 可选的插件要求
  • 可选的 Gateway 网关配置 patch
  • 可执行的 qa-flow
支撑 qa-flow 的可复用运行时 surface 可以保持通用且跨领域。例如,markdown 场景可以将传输侧 helper 与浏览器侧 helper 组合起来,通过 Gateway 网关 browser.request seam 驱动嵌入式 Control UI,而无需添加特例 runner。 场景文件应按产品能力分组,而不是按源码树文件夹分组。文件移动时保持场景 ID 稳定;使用 docsRefscodeRefs 实现实现可追踪性。 baseline 列表应保持足够宽,以覆盖:
  • 私信和渠道聊天
  • thread 行为
  • 消息操作生命周期
  • cron 回调
  • 记忆召回
  • 模型切换
  • subagent handoff
  • repo 阅读和文档阅读
  • 一个小型构建任务,例如 Lobster Invaders

提供商 mock lane

qa suite 有两个本地提供商 mock lane:
  • mock-openai 是场景感知的 OpenClaw mock。它仍然是 repo 支持的 QA 和 parity gate 的默认确定性 mock lane。
  • aimock 会启动一个由 AIMock 支持的提供商服务器,用于实验性协议、fixture、录制/重放和 chaos 覆盖。它是增量补充,不会取代 mock-openai 场景 dispatcher。
provider lane 实现位于 extensions/qa-lab/src/providers/ 下。每个提供商拥有自己的默认值、本地服务器启动、Gateway 网关模型配置、auth-profile staging 需求,以及 live/mock capability 标志。共享 suite 和 Gateway 网关代码应通过提供商 registry 路由,而不是按提供商名称分支。

传输适配器

qa-lab 拥有一个面向 markdown QA 场景的通用传输 seam。qa-channel 是该 seam 上的第一个适配器,但设计目标更宽:未来真实或合成的渠道应接入同一 suite runner,而不是新增传输专用 QA runner。 在架构层面,划分如下:
  • qa-lab 负责通用场景执行、worker 并发、artifact 写入和报告。
  • 传输适配器负责 Gateway 网关配置、readiness、入站和出站观测、传输操作,以及标准化传输状态。
  • qa/scenarios/ 下的 markdown 场景文件定义测试运行;qa-lab 提供执行它们的可复用运行时 surface。

添加一个渠道

向 markdown QA 系统添加渠道只需要两件事:
  1. 该渠道的传输适配器。
  2. 覆盖该渠道契约的场景包。
当共享 qa-lab host 可以拥有该 flow 时,不要添加新的顶层 QA command root。 qa-lab 拥有共享 host 机制:
  • openclaw qa command root
  • suite 启动和 teardown
  • worker 并发
  • artifact 写入
  • 报告生成
  • 场景执行
  • 旧版 qa-channel 场景的兼容别名
Runner 插件拥有传输契约:
  • openclaw qa <runner> 如何挂载到共享 qa root 下
  • 如何为该传输配置 Gateway 网关
  • 如何检查 readiness
  • 如何注入入站事件
  • 如何观测出站消息
  • 如何暴露 transcript 和标准化传输状态
  • 如何执行传输支持的操作
  • 如何处理传输专用 reset 或 cleanup
新渠道的最低采用门槛:
  1. qa-lab 继续作为共享 qa root 的 owner。
  2. 在共享 qa-lab host seam 上实现传输 runner。
  3. 将传输专用机制保留在 runner 插件或渠道 harness 内。
  4. 将 runner 挂载为 openclaw qa <runner>,而不是注册一个竞争性的 root command。Runner 插件应在 openclaw.plugin.json 中声明 qaRunners,并从 runtime-api.ts 导出匹配的 qaRunnerCliRegistrations 数组。保持 runtime-api.ts 轻量;惰性 CLI 和 runner 执行应留在独立入口点后面。
  5. 在按主题组织的 qa/scenarios/ 目录下编写或改造 markdown 场景。
  6. 为新场景使用通用场景 helper。
  7. 除非 repo 正在进行有意迁移,否则保持现有兼容别名可用。
决策规则很严格:
  • 如果行为可以在 qa-lab 中表达一次,就放到 qa-lab 中。
  • 如果行为依赖某一个渠道传输,就保留在该 runner 插件或插件 harness 中。
  • 如果一个场景需要多个渠道都能使用的新能力,请添加通用 helper,而不是在 suite.ts 中添加渠道专用分支。
  • 如果某个行为只对一个传输有意义,请让场景保持传输专用,并在场景契约中明确说明。

场景 helper 名称

新场景首选的通用 helper:
  • waitForTransportReady
  • waitForChannelReady
  • injectInboundMessage
  • injectOutboundMessage
  • waitForTransportOutboundMessage
  • waitForChannelOutboundMessage
  • waitForNoTransportOutbound
  • getTransportSnapshot
  • readTransportMessage
  • readTransportTranscript
  • formatTransportTranscript
  • resetTransport
现有场景仍可使用兼容别名 - waitForQaChannelReadywaitForOutboundMessagewaitForNoOutboundformatConversationTranscriptresetBus - 但新场景编写应使用通用名称。这些别名存在是为了避免一次性迁移,而不是作为未来模型。

报告

qa-lab 会从观测到的 bus timeline 导出 Markdown protocol 报告。 该报告应回答:
  • 哪些有效
  • 哪些失败
  • 哪些仍被阻塞
  • 哪些后续场景值得添加
如需查看可用场景清单 - 在估算后续工作量或接入新传输时很有用 - 请运行 pnpm openclaw qa coverage(添加 --json 可获得机器可读输出)。 如需进行 character 和 style 检查,请在多个 live 模型 ref 上运行同一场景,并编写经过评审的 Markdown 报告:
pnpm openclaw qa character-eval \
  --model openai/gpt-5.5,thinking=medium,fast \
  --model openai/gpt-5.2,thinking=xhigh \
  --model openai/gpt-5,thinking=xhigh \
  --model anthropic/claude-opus-4-6,thinking=high \
  --model anthropic/claude-sonnet-4-6,thinking=high \
  --model zai/glm-5.1,thinking=high \
  --model moonshot/kimi-k2.5,thinking=high \
  --model google/gemini-3.1-pro-preview,thinking=high \
  --judge-model openai/gpt-5.5,thinking=xhigh,fast \
  --judge-model anthropic/claude-opus-4-6,thinking=high \
  --blind-judge-models \
  --concurrency 16 \
  --judge-concurrency 16
该命令运行本地 QA Gateway 网关子进程,而不是 Docker。Character eval 场景应通过 SOUL.md 设置 persona,然后运行普通用户轮次,例如聊天、workspace 帮助和小文件任务。不应告知候选模型正在接受评估。该命令会保留每个完整 transcript,记录基本运行统计信息,然后以 fast 模式询问 judge 模型,并在支持时使用 xhigh reasoning,按自然度、vibe 和幽默感对运行进行排名。 在比较提供商时使用 --blind-judge-models:judge prompt 仍会获得每个 transcript 和运行状态,但候选 ref 会替换为中性标签,例如 candidate-01;报告会在解析后将排名映射回真实 ref。 候选运行默认使用 high thinking,GPT-5.5 使用 medium,支持它的旧版 OpenAI eval ref 使用 xhigh。使用 --model provider/model,thinking=<level> 内联覆盖特定候选。--thinking <level> 仍会设置全局 fallback,较旧的 --model-thinking <provider/model=level> 形式会为兼容性保留。 OpenAI 候选 ref 默认使用 fast 模式,以便在提供商支持的地方使用 priority processing。当单个候选或 judge 需要覆盖时,内联添加 ,fast,no-fast,fast=false。仅当你想强制每个候选模型都启用 fast 模式时,才传入 --fast。候选和 judge 的 duration 会记录在报告中,用于 benchmark 分析,但 judge prompt 会明确说明不要按速度排名。 候选和 judge 模型运行都默认使用并发 16。当提供商限制或本地 Gateway 网关压力使运行噪声过大时,降低 --concurrency--judge-concurrency。 未传入候选 --model 时,character eval 默认使用 openai/gpt-5.5openai/gpt-5.2openai/gpt-5anthropic/claude-opus-4-6anthropic/claude-sonnet-4-6zai/glm-5.1moonshot/kimi-k2.5google/gemini-3.1-pro-preview。 未传入 --judge-model 时,judge 默认使用 openai/gpt-5.5,thinking=xhigh,fastanthropic/claude-opus-4-6,thinking=high

相关文档