9.6 KiB
Dirigent 插件测试计划
版本:v0.3.x | 测试环境:OpenClaw 2026.4.9(待升级)
测试架构说明
参与者
main、home-developer、test-ph0:测试 agentCT-Moderator:主持人 bot(发送/删除调度消息)Proxy Bot:模拟人类用户,所有测试中需要"人工发消息"的操作均通过 Proxy Bot 完成
核心机制
before_model_resolve:轮次门控(非当前 speaker → NO_REPLY)agent_end:推进下一轮次,含 tail-match 轮询确认消息已发送message_received:外部消息处理(唤醒休眠、中断 tail-match、已结束频道自动回复)
一、前置检查
| # | 检查项 | 期望结果 |
|---|---|---|
| 1.1 | OpenClaw 升级到 2026.4.9,gateway 正常启动 | 日志无报错 |
| 1.2 | Dirigent 插件 deploy(cp -r plugin/* ~/.openclaw/plugins/dirigent/) |
日志显示 dirigent: plugin registered (v2) |
| 1.3 | dirigent-identity.json 确认三个 agent 均已注册 |
main、home-developer、test-ph0 均有 agentId → discordUserId 映射 |
| 1.4 | Proxy Bot 在目标 guild 内可见,有发消息权限 | 能在私有频道中发消息 |
二、Chat 模式报数测试(2 个 agent)
目的: 验证 2-agent 轮次调度和休眠(dormant)机制
2.1 创建频道并发起报数
步骤:
- 在 Discord 中创建一个新的私有文字频道,将
main、home-developer的 bot 账号及 CT-Moderator 加入 - 在
127.0.0.1:18789/dirigent控制页面中将该频道设置为 chat 模式 - Proxy Bot 在频道中发送指令:
请报数,从 0 开始,每次回复你看到的最后一个数字 +1。超过 5 之后,所有人只能回复
NO_REPLY。
期望(调度行为):
- Proxy Bot 消息触发
message_received→ speaker list 初始化 - CT-Moderator 发送
<@discordUserId>➡️后立即删除 main先发言回复1,CT-Moderator 触发home-developerhome-developer回复2,CT-Moderator 再次触发main- 如此交替,直到某 agent 回复
6(超过 5)
期望(休眠行为):
- 两个 agent 均回复
NO_REPLY后,日志显示entered dormant - Chat 模式:不发送空闲提醒
- 频道无任何后续消息
期望聊天记录:
Proxy Bot: 请报数,从 0 开始 ...
main: 1
home-developer: 2
main: 3
home-developer: 4
main: 5
home-developer: 6
main: NO_REPLY (静默,无 Discord 消息)
home-developer: NO_REPLY (静默,无 Discord 消息)
← 进入休眠,频道沉默
2.2 唤醒休眠并验证 Moderator 不触发再次唤醒
前置: 频道处于休眠
步骤:
- Proxy Bot 在频道发任意消息
期望:
- 日志显示
woke dormant channel - CT-Moderator 发调度消息触发第一个 speaker,轮次恢复
- CT-Moderator 自身的调度消息不触发二次唤醒(日志无第二条
woke dormant)
三、Chat 模式报数测试(3 个 agent,验证 Shuffle)
目的: 验证 3-agent shuffle 模式下轮次顺序在每个 cycle 结束后随机重排
3.1 创建频道并发起报数
步骤:
- 在 Discord 中创建一个新的私有文字频道,将
main、home-developer、test-ph0的 bot 账号及 CT-Moderator 加入 - 在
127.0.0.1:18789/dirigent控制页面中将该频道设置为 chat 模式 - Proxy Bot 在频道中发送指令:
请报数,从 0 开始,每次回复你看到的最后一个数字 +1。超过 7 之后,所有人只能回复
NO_REPLY。
期望(调度行为):
- 三个 agent 依次发言(Cycle 1 顺序由初始化决定)
- 每轮 3 条消息为一个 cycle
- Cycle 1 结束后,下一个 cycle 的顺序应与上一个不同(shuffle 生效)
- Shuffle 约束:上一个 cycle 的最后一个 speaker 不能成为下一个 cycle 的第一个 speaker
验证 Shuffle:
- 观察 Discord 聊天记录,记录每 3 条消息的发言者顺序
- 至少经历 2 个完整 cycle,确认顺序发生变化
- 日志中确认 3-agent 场景走 shuffle 分支
期望(休眠行为):
- 超过 7 后三个 agent 均
NO_REPLY→ 日志显示entered dormant
期望聊天记录示例(顺序仅供参考,shuffle 后会不同):
Proxy Bot: 请报数,从 0 开始 ...
[Cycle 1]
main: 1
home-developer: 2
test-ph0: 3
[Cycle 2 — shuffle 后顺序可能变化]
test-ph0: 4
main: 5
home-developer: 6
[Cycle 3]
home-developer: 7
test-ph0: 8 (超过 7)
main: NO_REPLY
...
← 进入休眠
3.2 外部消息中断 tail-match
步骤:
- 在某 agent 完成发言、tail-match 轮询期间(约 0-15s 内)
- Proxy Bot 立即发一条消息
期望:
- 日志显示
tail-match interrupted - 轮次正常推进至下一个 speaker,不卡住
四、Discussion 模式测试(完整生命周期)
目的: 验证 discussion 频道从创建到结束的全流程,包括 callback
4.1 创建 Channel A(Chat)并通过 agent 发起讨论
步骤:
- 在 Discord 中创建一个新的私有文字频道(即 Channel A),将
main的 bot 账号及 CT-Moderator 加入 - 在
127.0.0.1:18789/dirigent控制页面中将 Channel A 设置为 chat 模式 - Proxy Bot 在 Channel A 发送指令:
请使用
create-discussion-channel工具,邀请home-developer参与一个讨论,主题自定,讨论结束条件是达成至少 2 条共识。
期望:
main调用create-discussion-channel工具,Discord 中出现新私有 Discussion 频道dirigent-channels.json新增该频道记录:mode=discussion,concluded=false,initiatorAgentId=main,callbackChannelId=Channel A 的 ID- CT-Moderator 在 Discussion 频道发送讨论指南(discussionGuide)
- CT-Moderator 发调度消息触发第一个 speaker
4.2 Discussion 轮次正常运转
期望:
main和home-developer在 Discussion 频道内交替发言- 非当前 speaker 静默(
before_model_resolve返回 NO_REPLY)
4.3 Discussion 休眠 → 空闲提醒
触发条件: 两个 agent 在同一 cycle 内均输出 NO_REPLY
期望(discussion 独有行为):
- 日志显示
entered dormant - CT-Moderator 在 Discussion 频道发送空闲提醒给 initiator(main):
<@main的discordUserId> Discussion is idle. Please summarize the results and call `discussion-complete`. - 只发一次
4.4 discussion-complete 结束讨论 → Callback 验证
步骤: main 在 Discussion 频道中调用 discussion-complete 工具
期望:
dirigent-channels.json中该频道concluded变为true- CT-Moderator 在 Channel A(callbackChannel)发送:
Discussion complete. Summary: /path/... - Discussion 频道不再有任何 agent 发言
4.5 已结束 Discussion 频道:外部消息自动回复(单次,无循环)
步骤: Proxy Bot 在已结束的 Discussion 频道发一条消息
期望:
- CT-Moderator 回复恰好一次:
This discussion is closed and no longer active. - CT-Moderator 自己的这条回复不触发新的 "closed" 回复(无限循环修复验证)
- 日志确认:senderId 匹配 moderatorBotUserId → 跳过 concluded auto-reply
五、Report / Work 模式测试
5.1 创建 Report 频道
操作: 让任意 agent 调用 create-report-channel
期望:
- 频道创建成功
- Proxy Bot 在该频道发消息后,agent 不响应(mode=report → NO_REPLY)
5.2 创建 Work 频道
操作: 让任意 agent 调用 create-work-channel
期望:
- 频道创建成功,mode=work(locked)
- 无轮次管理,agent 自由响应
5.3 Locked Mode 不可更改
操作: 对 discussion/work 频道调用 /set-channel-mode
期望:
- 报错:
Channel is in locked mode
六、边界条件 & 回归验证
| # | 场景 | 期望 |
|---|---|---|
| 6.1 | Gateway 重启后,chat 频道收到 Proxy Bot 消息 | 重新初始化 speaker list,轮次正常恢复 |
| 6.2 | Proxy Bot 连续快速发多条消息(压力测试) | blocked-pending 计数不超过 MAX=3,不形成死循环 |
| 6.3 | 同一事件被多个 VM 上下文处理 | globalThis dedup(BMR WeakSet / agent_end Set / concluded Set)确保只执行一次 |
| 6.4 | fetchVisibleChannelBotAccountIds 返回空列表 |
不崩溃,日志警告,不发调度消息 |
七、日志关键词速查
正常流程应出现的日志:
dirigent: plugin registered (v2)
dirigent: initialized speaker list channel=... speakers=...
dirigent: before_model_resolve anchor set channel=...
dirigent: triggered next speaker agentId=...
dirigent: agent_end channel=... empty=false
dirigent: entered dormant
dirigent: woke dormant channel=...
dirigent: moderator message sent to channel=...
异常(需关注):
dirigent: tail-match timeout ← 15s 内消息未落地
dirigent: agent_end skipping stale ← 正常(stale NO_REPLY 被过滤)
dirigent: before_model_resolve init in progress ← 并发初始化保护(正常)
八、测试顺序建议
前置检查 (§1)
↓
2-agent 报数:轮次 + 休眠 + 唤醒 (§2)
↓
3-agent 报数:shuffle 验证 + tail-match 中断 (§3)
↓
Discussion 完整生命周期:创建 → 轮次 → 空闲提醒 → 结束 → callback → 防循环 (§4)
↓
Report/Work 频道 (§5)
↓
边界条件 (§6)
测试中如遇 agent 卡住超过 10 分钟,重启 gateway 后继续。偶发的 5-10 分钟响应延迟属正常(Kimi 模型特性)。