Files
Dirigent/plans/CSM.md

584 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CSM 设计稿:基于 Discord 私密频道的 Agent 协作讨论与回调机制
## 1. 背景
在 Dirigent 的多 Agent 工作流中,某个正在执行任务的 Agent 可能在处理中途需要与其他 Agent 讨论某个问题,例如:
- 方案评审
- 权限模型确认
- 实现细节对齐
- 风险/边界条件讨论
当前缺少一种受控、可回收、可回灌原工作流的讨论机制。目标是让 Agent 能在需要时主动拉起一个临时私密讨论频道,与指定 Agent 交流,并在结束后把讨论成果注入回原始工作 Session 所在的 Discord channel。
本方案采用:
- 由发起讨论的 Agent 直接调用 `create private channel`
- 为该工具新增两个可选参数,以标记“讨论模式”
- 由插件侧 moderator bot 用纯字符串拼接方式驱动讨论流程
- 由发起讨论的 Agent 在讨论结束时显式调用新工具 `discuss-callback`
- 回调后关闭讨论 channel并唤醒原工作 channel 继续处理
---
## 2. 目标
实现一种可控的 Agent 间讨论机制,满足以下要求:
1. Agent 能在工作过程中主动创建一个私密讨论 channel
2. 讨论 channel 能通过固定规则唤醒参与 Agent 开始讨论
3. 讨论结束时,结果必须以文件形式落地
4. 讨论结果能回传到原工作 channel
5. 讨论结束后,讨论 channel 不再继续处理任何 Agent 发言
6. moderator bot 不使用任何模型,所有发言均为固定模板/字符串拼接
7. 整个机制尽量复用现有插件顺序讨论能力
---
## 3. 非目标
以下内容不在本次 MVP 范围内:
- 不做基于模型的 moderator/coordinator 智能决策
- 不做自动总结(总结必须由发起讨论的 Agent 负责)
- 不做复杂投票/仲裁机制
- 不做多级讨论嵌套
- 不做跨 workspace 的结果存储
- 不做开放式 transcript 自动压缩和长期知识抽取
---
## 4. 核心思路
将“讨论”视为一种特殊模式的私密频道:
- 由工作中的 Agent 主动创建
- 创建时提供原工作 channel idcallback channel id和讨论指引discuss guide
- 插件识别该频道为特殊讨论频道
- moderator bot 在频道中发布一条固定 kickoff message说明
- 讨论目的
- 应如何进行讨论
- 结束条件
- 发起讨论的 Agent 在结束时必须写总结文档并调用 `discuss-callback`
- 讨论期间复用现有“顺序讨论”机制驱动 Agent 发言
- 如果轮转一圈无人发言,则 moderator 提醒发起者执行 callback 收尾
- callback 成功后:
- 检查总结文档是否存在,且必须位于发起讨论 Agent 的 workspace 下
- 将讨论 channel 中对应 session 的模型覆盖为 `NO_REPLY`
- 讨论 channel 后续任何消息都不再参与讨论,仅由 moderator 回复“channel 已关闭,仅留档”
- moderator 在原工作 channel 发消息,给出讨论结果文档路径,唤醒原工作流
---
## 5. 工具设计
### 5.1 扩展 `create private channel`
在现有 `create private channel` 工具上新增两个可选参数:
- `callbackChannelId?: string`
- `discussGuide?: string`
#### 兼容性要求
如果未填写 `callbackChannelId`
- 工具行为与当前完全一致
如果填写了 `callbackChannelId`
- 则必须同时填写 `discussGuide`
- 插件将该 channel 标记为“讨论模式 channel”
#### 参数语义
##### `callbackChannelId`
表示原工作 Session 所在的 Discord channel id。
该参数用于在讨论结束时,将结果回传给原工作 channel。
##### `discussGuide`
字符串,描述:
- 需要讨论什么
- 讨论希望得到什么结论
- 讨论的边界与目标
- 可选的产出要求
例如:
```text
讨论私密协作 channel 的回调机制,需要明确:
1. create private channel 扩展参数设计
2. discuss-callback 工具的行为
3. 讨论结束后的 session 收口方式
4. MVP 范围内的异常处理策略
```
---
### 5.2 新工具 `discuss-callback`
新增工具:`discuss-callback`
建议工具参数最小化为:
- `summaryPath: string`
#### 参数说明
##### `summaryPath`
讨论总结文档的路径。
要求:
- 文件必须存在
- 文件必须位于发起讨论 Agent 的 workspace 下
- 不允许引用 workspace 外路径
#### 不建议暴露的参数
以下参数不应由 Agent 自己传入:
- 原工作 channel id
- discussion channel id
- 发起者身份
这些信息应由插件根据当前 channel 上下文和已记录 metadata 自动推导,避免伪造和串错。
---
## 6. 讨论模式 Channel 的元数据
`create private channel` 以讨论模式创建 channel 时,插件需要记录对应 metadata。
建议结构如下:
```json
{
"mode": "discussion",
"discussionChannelId": "C_DISCUSS_001",
"originChannelId": "C_WORK_001",
"initiatorAgentId": "agent_planner",
"initiatorSessionId": "sess_123",
"discussGuide": "讨论如何设计 callback 机制并确定 MVP 行为",
"status": "active",
"createdAt": "2026-03-30T18:00:00Z",
"summaryPath": null
}
```
### 必需字段说明
- `mode`: 固定为 `discussion`
- `discussionChannelId`: 当前讨论 channel id
- `originChannelId`: 原工作 channel id
- `initiatorAgentId`: 发起讨论的 Agent 标识
- `initiatorSessionId`: 发起讨论对应的 session 标识
- `discussGuide`: 讨论说明
- `status`: 生命周期状态
- `createdAt`: 创建时间
- `summaryPath`: 结束后回写的总结文档路径
### 生命周期状态建议
- `active`:讨论进行中
- `completed`:已成功 callback已完成
- `closed`:已关闭,仅作留档
对于 MVP也可以将 `completed` 直接视为 `closed` 前的瞬时态,只要实现上清晰即可。
---
## 7. moderator bot 行为设计
moderator bot 的工作流完全不使用模型,所有输出均由模板字符串拼接生成。
### 7.1 讨论启动时发言
当检测到某 channel 为讨论模式 channel 时moderator bot 自动发 kickoff message。
建议内容结构如下:
```text
[Discussion Started]
This channel was created for a temporary agent discussion.
Goal:
{discussGuide}
Instructions:
1. Discuss only the topic above.
2. Work toward a concrete conclusion.
3. When the initiator decides the goal has been achieved, the initiator must:
- write a summary document to a file
- call the tool: discuss-callback
- provide the summary document path
Completion rule:
Only the discussion initiator may finish this discussion.
After callback:
- this channel will be closed
- further discussion messages will be ignored
- this channel will remain only for archive/reference
- the original work channel will be notified with the summary file path
```
结尾必须明确表达以下语义:
- 讨论结束由发起讨论的 Agent 判定
- 发起者结束时必须写入总结文档
- 发起者必须调用 `discuss-callback`
- callback 成功后,原工作 channel 会被通知结果文档路径
---
### 7.2 空转提醒机制
插件当前已有顺序讨论机制。
现有逻辑:
- 发言列表轮转一圈,如果没有人发言且所有人均回复 `NO_REPLY`,则认为 channel 休眠
本方案对“特殊讨论 channel”修改为
#### 新逻辑
在讨论模式 channel 中:
- 若发言列表轮转一圈,无人发言
- 则 moderator 不直接判定流程结束
- 改为提醒发起讨论的 Agent
- 若讨论目标已经达成,请写总结文档
- 然后调用 `discuss-callback` 结束讨论
建议提醒消息模板:
```text
[Discussion Idle]
No agent responded in the latest discussion round.
If the discussion goal has been achieved, the initiator should now:
1. write the discussion summary to a file in the workspace
2. call discuss-callback with the summary file path
If more discussion is still needed, continue the discussion in this channel.
```
这样可以避免讨论悄无声息悬空,同时不引入自动总结逻辑。
---
### 7.3 讨论结束后的行为
`discuss-callback` 成功后:
1. 讨论 channel 标记为关闭/完成
2. 讨论 channel 中所有相关 session 的模型覆盖为 `NO_REPLY`
3. 后续任何在该 channel 中的发言均不再触发实际讨论流程
4. 如果讨论结束后仍有人发言,由 moderator 统一回复:
- `channel 已关闭channel 仅做留档使用`
建议模板:
```text
[Channel Closed]
This discussion channel has been closed.
It is now kept for archive/reference only.
Further discussion in this channel is ignored.
```
这部分实现明确采用已有“在指定 session 上临时覆盖为 no-reply 模型”的方式,而不是修改 Agent 的全局默认模型。
---
## 8. `discuss-callback` 工具行为细节
### 8.1 调用前提
仅允许在讨论模式 channel 中调用。
### 8.2 调用权限
只有发起讨论的 Agent 对应 session 可以成功调用。
其他参与 Agent 调用时应被拒绝。
### 8.3 调用流程
`discuss-callback(summaryPath)` 执行时,插件执行如下步骤:
1. 从当前调用上下文获取 discussion channel id
2. 查询该 channel 的 discussion metadata
3. 校验该 channel 是否为讨论模式 channel
4. 校验调用者是否为 initiator session / initiator agent
5. 校验 `summaryPath` 对应文件是否存在
6. 校验文件路径是否位于发起讨论 Agent 的 workspace 下
7. 更新 metadata
- `summaryPath = ...`
- `status = completed``closed`
- `completedAt = now`
8. 将该 discussion channel 中相关 session 的模型覆盖为 `NO_REPLY`
9. 在原工作 channel 中由 moderator bot 发消息,给出结果文档路径
10. 讨论 channel 后续进入只留档、不再参与讨论的状态
---
## 9. 原工作 Channel 的唤醒机制
`discuss-callback` 成功后moderator bot 需要在原工作 channel 发一条固定格式消息。
目的:
- 向原工作 Session 明确传达“讨论结束”
- 提供结果文档路径
- 用新消息唤醒原工作 channel 上的 Agent 继续执行
建议模板:
```text
[Discussion Result Ready]
A temporary discussion has completed.
Summary file:
{summaryPath}
Source discussion channel:
<#discussionChannelId>
Status:
completed
Continue the original task using the summary file above.
```
### 注意事项
这里的“唤醒”不依赖额外模型调度逻辑,而是依赖:
- moderator bot 在原 channel 发布一条新消息
- 原工作 channel 正常接收到新消息事件
- 原工作 Session 被自然触发继续处理
---
## 10. 安全与边界条件
### 10.1 `summaryPath` 伪造
必须防止 Agent 传入伪造路径。
#### 强制校验
插件必须检查:
1. 文件是否存在
2. 文件路径是否位于发起讨论 Agent 的 workspace 下
3. 不允许使用 workspace 之外的路径
这是本方案的硬约束。
---
### 10.2 discussion channel 未正常结束
由于讨论结束依赖发起者显式 callback可能出现讨论完成但发起者未执行 callback 的情况。
#### MVP 策略
- 不做自动总结
- 复用顺序讨论机制检测“轮转一圈无人发言”
- 由 moderator bot 提醒发起者收尾
这已经足够形成最低可用闭环。
后续增强可再考虑:
- 超时提醒
- stale discussion 清理
- 管理员强制关闭
---
### 10.3 结束后继续发言
这是明确禁止的。
在讨论完成后:
- 任何会话都不应继续在该 channel 中讨论
- 相关 session 继续使用 `NO_REPLY` 模型覆盖
- channel 仅保留为留档用途
- 后续发言统一由 moderator bot 回复 channel 已关闭
这条约束需要严格执行,避免旧讨论“诈尸”。
---
### 10.4 状态重复提交
`discuss-callback` 被重复调用,应拒绝处理。
建议规则:
- 仅允许 `active -> completed/closed` 一次转换
- 若 channel 已完成或已关闭,则后续 callback 一律失败
---
## 11. 推荐状态机
```text
普通 channel
└── 不受本方案影响
讨论 channel
created
-> active
-> idle-reminded (可选显示态)
-> completed
-> closed
```
### 状态说明
- `created`channel 已创建但 kickoff 尚未发完
- `active`:讨论进行中
- `idle-reminded`轮转一圈无人发言moderator 已提醒收尾(实现上可不单独持久化)
- `completed`callback 已成功
- `closed`channel 已关闭,仅保留留档
MVP 中也可简化为:
- `active`
- `closed`
只要逻辑上能区分 callback 前后即可。
---
## 12. 典型流程示例
### 12.1 发起讨论
原工作 channel 中,某 Agent 发现需要和其他 Agent 对齐方案。
Agent 调用:
```json
{
"callbackChannelId": "origin-channel-123",
"discussGuide": "讨论私密协作 channel 的结束与回调机制,需要产出一份总结说明工具参数、结束条件和异常处理策略。"
}
```
插件创建私密讨论 channel并记录 metadata。
moderator bot 在新 channel 中发布 kickoff message。
---
### 12.2 展开讨论
参与 Agent 在该 channel 中按现有顺序讨论机制发言。
如果轮转一圈无人发言,则 moderator 提醒发起者:
- 若已达成目标,请写总结文档并 callback
---
### 12.3 结束讨论
发起讨论 Agent 在自己的 workspace 下写出总结文档,例如:
```text
plans/discussions/csm-discussion-summary.md
```
随后调用:
```json
{
"summaryPath": "plans/discussions/csm-discussion-summary.md"
}
```
插件校验通过后:
- 标记讨论完成
- 覆盖讨论 channel 中相关 session 的模型为 `NO_REPLY`
- 在原工作 channel 发 moderator message
---
### 12.4 原工作流继续
原工作 channel 收到 moderator 的结果通知:
- 结果文档路径
- 来源 discussion channel
- 状态 completed
原工作 Session 读取该总结文档,并继续原任务。
---
## 13. MVP 实施建议
建议按以下顺序实现:
### 第一步:扩展建频道工具
-`create private channel` 增加 `callbackChannelId``discussGuide`
- 实现参数联动校验
- 讨论模式下写入 metadata
### 第二步moderator kickoff
- 讨论模式 channel 创建后自动发固定模板消息
- 内容包含 callback 操作说明
### 第三步:接入空转提醒
- 复用现有顺序讨论逻辑
- 在讨论模式 channel 中改为空转提醒发起者 callback
### 第四步:实现 `discuss-callback`
- 当前 channel 识别
- initiator 身份校验
- `summaryPath` 文件存在校验
- workspace 范围校验
- metadata 更新
### 第五步:完成关闭逻辑
- 指定 session 模型覆盖为 `NO_REPLY`
- 结束后任何发言统一由 moderator 回复 channel 已关闭
### 第六步:原 channel 唤醒
- moderator 在 origin channel 发布结果消息
- 确保原工作 Session 被自然唤醒
---
## 14. 后续可扩展方向
在 MVP 跑通后,可考虑增加以下能力:
- 讨论超时自动提醒
- 管理员强制 callback / 强制关闭
- 讨论文档路径规范化
- 对总结文档结构给出模板约束
- discussion 状态查询工具
- 讨论留档索引
- callback 成功后自动附带摘要预览
但这些都应放在 MVP 验证后再做。
---
## 15. 结论
本方案将 Agent 间讨论能力实现为一种“特殊模式的私密 Discord channel”通过
- 扩展 `create private channel`
- 新增 `discuss-callback`
- 复用现有顺序讨论机制
- 使用纯规则驱动的 moderator bot
- 在指定 session 上临时覆盖 `NO_REPLY` 模型
形成一个完整闭环:
1. 原工作 Agent 发起讨论
2. 私密讨论 channel 被创建并自动启动讨论
3. 讨论结果写入发起者 workspace 中的文件
4. 发起者显式 callback 结束讨论
5. 插件关闭讨论 channel 的交互能力
6. moderator 将结果路径回传到原工作 channel
7. 原工作 Session 被唤醒并继续执行
这是一个实现成本可控、行为稳定、边界清晰、适合 MVP 落地的方案。