跳转至

WhatsApp QA 和凭据

WhatsApp QA

pnpm openclaw qa whatsapp

目标为两个专用的 WhatsApp Web 账号:一个由测试框架控制的 driver 账号,以及一个由子 OpenClaw gateway 通过捆绑的 WhatsApp 插件启动的 SUT 账号。

当 --credential-source env 时必需的环境变量:

  • OPENCLAW_QA_WHATSAPP_DRIVER_PHONE_E164
  • OPENCLAW_QA_WHATSAPP_SUT_PHONE_E164
  • OPENCLAW_QA_WHATSAPP_DRIVER_AUTH_ARCHIVE_BASE64
  • OPENCLAW_QA_WHATSAPP_SUT_AUTH_ARCHIVE_BASE64

可选:

  • OPENCLAW_QA_WHATSAPP_GROUP_JID 启用群组场景,例如 whatsapp-mention-gating、whatsapp-group-pending-history-context、 whatsapp-broadcast-group-fanout、whatsapp-group-activation-always、 whatsapp-group-reply-to-bot-triggers、群组操作/媒体/投票场景, 以及 whatsapp-group-allowlist-block。

WhatsApp YAML 场景(qa/scenarios/channels/whatsapp-*.yaml):

  • 基线与群组门控:whatsapp-canary、whatsapp-pairing-block、 whatsapp-mention-gating、whatsapp-group-pending-history-context、 whatsapp-group-activation-always、whatsapp-group-reply-to-bot-triggers、 whatsapp-top-level-reply-shape、whatsapp-restart-resume、 whatsapp-group-allowlist-block。
  • 原生命令:whatsapp-help-command、whatsapp-status-command、 whatsapp-commands-command、whatsapp-tools-compact-command、 whatsapp-whoami-command、whatsapp-context-command、 whatsapp-native-new-command。
  • 回复与最终输出行为:whatsapp-tool-only-usage-footer、 whatsapp-reply-to-message、whatsapp-group-reply-to-message、 whatsapp-reply-to-mode-batched、whatsapp-reply-context-isolation、 whatsapp-reply-delivery-shape、whatsapp-stream-final-message-accounting。
  • 用户路径消息操作:whatsapp-agent-message-action-react 从真实的 driver 私信开始, 让模型调用 message 工具,并观察原生 WhatsApp 反应。 whatsapp-agent-message-action-upload-file 对 message(action=upload-file) 使用相同方式,并观察原生 WhatsApp 媒体。 whatsapp-group-agent-message-action-react 和 whatsapp-group-agent-message-action-upload-file 在真实 WhatsApp 群组中 证明相同的用户可见操作。
  • 群组扇出:whatsapp-broadcast-group-fanout 从一条被提及的 WhatsApp 群组消息开始, 并验证来自 main 和 qa-second 的不同可见回复。
  • 群组激活:whatsapp-group-activation-always 将真实群组会话更改为 /activation always,证明未提及的群组消息可以唤醒 agent,然后恢复为 /activation mention。 whatsapp-group-reply-to-bot-triggers 预置一条机器人回复,在不显式提及的情况下 向其发送原生引用回复,并验证 agent 从该回复上下文中唤醒。
  • 入站媒体和结构化消息:whatsapp-inbound-image-caption、 whatsapp-audio-preflight、whatsapp-inbound-structured-messages、 whatsapp-group-audio-gating、whatsapp-inbound-reaction-no-trigger。 这些通过 driver 发送真实的 WhatsApp 图像、音频、文档、位置、联系人、贴纸 和反应事件。
  • 直接 Gateway 契约探针:whatsapp-outbound-media-matrix、 whatsapp-outbound-document-preserves-filename、whatsapp-outbound-poll、 whatsapp-outbound-send-serialization、 whatsapp-group-outbound-media、whatsapp-group-outbound-poll、 whatsapp-message-actions、whatsapp-reply-context-isolation、 whatsapp-reply-delivery-shape。这些有意绕过模型 prompt,并证明确定性的 Gateway/通道 send、poll 和 message.action 契约。
  • 访问控制覆盖:whatsapp-access-control-dm-open、 whatsapp-access-control-dm-disabled、whatsapp-access-control-group-open、 whatsapp-access-control-group-disabled、whatsapp-group-allowlist-block。
  • 原生审批:whatsapp-approval-exec-deny-native、 whatsapp-approval-exec-native、whatsapp-approval-exec-reaction-native、 whatsapp-approval-exec-group-reaction-native、 whatsapp-approval-plugin-native。
  • 状态反应:whatsapp-status-reactions、 whatsapp-status-reaction-lifecycle。

WhatsApp 默认值由所选分类配置和 lane 约束派生。mock-openai 通过真实 WhatsApp 传输确定性地运行符合条件的场景,同时仅模拟模型输出;live-frontier 排除其提供商或模型契约需要 mock lane 的场景。

WhatsApp QA driver 观察结构化实时事件(text、media、location、 reaction 和 poll),并可以主动发送媒体、投票、联系人、位置和贴纸。 QA Lab 通过 @openclaw/whatsapp/api.js 包接口导入该 driver,而不是深入私有的 WhatsApp 运行时文件。对于群组观察,fromJid 是群组 JID,而 participantJid 和 fromPhoneE164 标识参与者发送者。消息内容默认会被脱敏。直接 Gateway 的 poll、upload-file、媒体、群组 poll、群组媒体和回复形状探针是传输/API 契约检查; 它们不被视为用户 prompt 使 agent 选择相同操作的证明。用户路径操作证明来自诸如 whatsapp-agent-message-action-react 和 whatsapp-group-agent-message-action-react 的场景,其中 driver 发送一条普通 WhatsApp 消息,QA Lab 观察由此产生的原生 WhatsApp 产物。WhatsApp 场景详情包括每个场景的方式(user-path、 direct-gateway 或 native-approval),因此证据不会被误认为比其实际证明更强的契约。

WhatsApp 模块场景通过 execution.config.whatsappScenario 选择其实现。适配器 在流程准备期间应用其配置并等待通道就绪,这发生在场景截止时间开始之前。负向 场景随后观察其完整的静默窗口;配置和重连时间不会消耗该窗口。

输出产物:

  • qa-suite-report.md
  • qa-suite-summary.json
  • qa-evidence.json - 实时传输检查的证据条目。

Convex 凭据池

Buzz、Discord、Slack、Telegram 和 WhatsApp 通道可以从共享 Convex 池中租用凭据,而不是读取记录在 通道 QA 参考、Slack QA 和 WhatsApp QA 中的每个通道的环境变量。传入 --credential-source convex(或设置 OPENCLAW_QA_CREDENTIAL_SOURCE=convex);QA Lab 会获取独占租约,在整个运行期间对其发送心跳,并在关闭时释放它。池类型包括 "buzz"、"discord"、"slack"、"telegram" 和 "whatsapp"。

测试套件在启动开始之前负责其 Gateway 生命周期,包括打包的 auth 和 plugin-repair 命令、启动重试、替换进程,以及针对活动 Gateway 运行的命令。每个 CLI 命令有 2 分钟执行限制。Stop 会立即关闭准入并结束所有拥有的进程组;leader 退出不会绕过关闭流程或对继承 stdio 关闭的有界等待。在 POSIX 上,CLI 命令使用自己的进程组,因此并发命令不会替换活动 Gateway 的身份。CLI 失败(包括超时、取消和流故障)会保留有界且已脱敏的 stderr 和 stdout,并捕获至关闭完成。打包插件设置错误会区分 update repair --help 和 update repair。

Gateway RPC 调用仅在请求未发送时等待重连。一旦发送,丢失的连接会报告给场景,而不会重放请求:Gateway 可能已经提交该请求。场景代码必须先检查最终状态,再决定被中断的操作是否可安全重试。

传输适配器在 cleanup() 中排空其 driver 工作,并在 cleanupAfterGatewayStop() 中释放由 Gateway 支持的凭据。测试套件仅在未生成子进程,或所有拥有的进程组均确认已停止时,才运行该第二阶段。就绪失败或已退出的组 leader 不构成关闭证明。

启动或替换失败会结束进程,而不会最终确定其日志或暂存目录。调用方保留生命周期所有者,并始终调用 stop(),包括在启动被拒绝之后。该显式 stop 会应用调用方的工件策略,因此失败报告可以在临时运行时状态被移除之前保留已净化的 Gateway 日志。

在确认关闭后,成功导出(或选择不导出)会在临时状态移除之前最终确定工件策略。清理重试会保留该导出,而不会重写它或使用更晚的目标,同时 RPC 和暂存清理仍会重试。失败的导出仍可重试。未确认的 stop 会刷新请求的快照,最终确认的快照包含后续输出。保留临时状态会使其日志可用于后续的清理重试。

如果无法确认终止,测试套件会报告清理失败,保留运行时目录,并保留适配器的租约和心跳所有权。在重新使用这些凭据之前,检查报告的进程组和保留的运行时。日志、RPC 或工件错误仍会报告,但当进程组确认已停止时,不会阻止 stop 后的清理。该顺序要求适配器使用两个清理阶段;它不会更改 broker TTL,也不会在 QA 父进程或主机丢失后提供持久保证。

临时运行时目录和暂存插件目录会独立移除,清理失败会以脱敏诊断信息报告。在移除运行时之前,QA 父进程会关闭该 root 的 auth 读取器和 agent 数据库,在共享状态仍打开时释放它们的租约,然后关闭共享数据库。其他 QA root 保持不变。关闭失败会保留运行时以便重试,同时仍会尝试移除暂存插件。因此,即使进程终止已确认,清理错误也可能在磁盘上留下孤立的运行时或 auth 状态。修正报告的问题,并在保留的生命周期所有者上重试 stop();确认终止后仍允许 stop 后的凭据清理。

broker 在 admin/add 上验证的 payload 形状:

  • Buzz(kind: "buzz"):{ relayUrl: string, roomId: string, driverPrivateKey: string, sutPrivateKey: string, driverAuthTag?: string, sutAuthTag?: string } - relayUrl 必须使用 wss://,仅回环中继允许使用 ws://;roomId 必须是频道 UUID,且身份必须不同。
  • Discord(kind: "discord"):{ guildId: string, channelId: string, driverBotToken: string, sutBotToken: string, sutApplicationId: string, voiceChannelId?: string }。
  • Telegram(kind: "telegram"):{ groupId: string, driverToken: string, sutToken: string } - groupId 必须是数字 chat-id 字符串。
  • WhatsApp(kind: "whatsapp"):{ driverPhoneE164: string, sutPhoneE164: string, driverAuthArchiveBase64: string, sutAuthArchiveBase64: string, groupJid?: string } - 电话号码必须是不同的 E.164 字符串。

Slack 通道也可以使用池。Slack payload 形状检查目前位于 Slack QA runner 中,而不是 broker;使用 { channelId: string, driverBotToken: string, sutBotToken: string, sutAppToken: string },Slack 频道 id 形如 Cxxxxxxxxxx。有关应用和 scope 配置,请参阅 设置 Slack 工作区。

运维环境变量和 Convex broker 端点契约位于 测试 → 通过 Convex 共享 Telegram 凭据(该章节名称早于多通道池;租约语义在各类型间共享)。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/openclaw