让一个 AI 写一份竞品报告,难点在它够不够聪明。让三个 AI 一起写,难点变成了:谁做哪部分,查到的东西怎么交给别人,两个人同时想干同一件事怎么办,有人说“我来”然后没下文怎么办。
这些问题和模型能力关系不大,更像是在设计一个小团队的工作规则。下面是 AelionBot 目前用的几条,以及它们为什么长成这样。代码在 GitHub。
不设主持人
常见的多 Agent 做法是一个主 Agent 拆任务、派给子 Agent,子 Agent 做完交回。结构清楚,但用户看到的基本是一根进度条,也很难中途插手某一个环节。
我们选了另一条路:群里一条公开消息平等发给所有成员,@ 只是提醒关注,不筛选收件人。每个 Bot 在自己的群工作区里判断要不要接话,看完选择不说话也是正常结果(它会回一个 [群聊静默],界面上不显示)。

代价是协调的责任落到了每个 Bot 自己身上。后面几条规则,都是在补这个代价。
认领:同一件事只能有一个负责人
群里有一张任务表。Bot 想做一件事,先调用 group_task_claim,用一个稳定的 key 创建并认领任务。认领在同一个存储写入者里同步完成,两个 Bot 同时抢,只有一个能成功;没抢到的不会重复执行,可以去看任务表,或者对别人的工作提意见。
更新任务要带当前的修订号。两个人基于旧版本同时改,后到的会收到冲突和最新记录,合并后再提交。
我们没做的是“语义去重”:两个 key 不同但内容重叠的任务,底层不去猜它们是不是一回事。这种判断很容易误伤,交给 Bot 先看任务表再决定更可控。
新消息不打断正在跑的工作
一个 Bot 正在终端里跑一段数据处理,群里又来了一条消息。停下来吗?
不停。普通消息不会取消推理或工具调用,而是排队,在下一次模型调用前一起读进来,也就是上一批工具结果已经保存好的那个边界。这样中途补充的要求能影响接下来的步骤,又不会把跑到一半的命令扔掉。只有明确的“停止”和把成员移出群,才会真正取消执行。
发言也是显式的。Bot 必须调用 group_send_message 才算公开发言,调用工具前后顺手写的文字不会自动群发。每次发件先存成 pending,再在同一次保存里提交消息、每个接收人的投递记录和回执。重试用同一个 clientMessageId,不会重复投递;同一个 id 想换内容会被拒绝。
上下文也按这个思路省着用。新的群工作区默认只装最近 4 条公开消息,单条最多 1800 字,截断处标明从哪里回读,更早的内容用 group_read 按需翻。
不许一句“稍后处理”就收工
模型有个老毛病:说完“好的,我这就开始”,这一轮就结束了。私聊里用户会追问;群里别的 Bot 可能正等着它的结果。
所以已认领、还在 working 状态的任务,不能靠一句承诺结束运行,执行循环会继续推进,直到完成、报告阻碍或主动释放。如果连续三次提前答复,或者连续三轮工具调用只是在重复相同的成功操作,系统会如实标记为受阻并保留检查点,不假装完成。
一次事故:工具设计让页面越改越差
九月中旬,一个设计师 Bot 接到任务:设计一个加密货币交易所的官网。9 分钟、22 轮模型调用之后,交付的页面比它自己的第一稿还差:链接变回浏览器默认的蓝色下划线,窄屏下菜单点了打不开,焦点样式也没了。
复盘发现问题不在“设计能力”,在工具:
- 新建文件和覆盖文件共用一个写入工具,带一个可选的
expectedSha256,用来防止覆盖用户同时做的修改。模型在新建文件时填了虚构的哈希(全零),最后一次还把真实哈希抄错了一位。防覆盖保护正确地拒绝了全部 5 次写入。 - 模型转而用 shell 写文件,提交了一条 9,477 字的命令,超过了 6,000 字的上限。
- 为了塞进上限,它主动把页面缩了。HTML 从首稿的 11,300 字变成交付时的 3,915 字,样式表也少了一半多。
修法都不复杂:加一个专门的 design_file_create,只要路径、内容和理由,不暴露哈希参数;在 shell 工具的 schema 里直接写明 6,000 字上限,让模型提前知道;在工作流里明确“工具失败不能成为缩减设计的理由”。防覆盖保护本身一点没放松。
这件事让我们更相信一点:Agent 的很多“笨”,是接口给了它犯错的空间。能在接口上消掉的错误,就不要指望提示词。
还没解决的
- 几个 Bot 在群里互相接话时,什么时候该停,目前靠提示词和任务状态引导,没有发言评分,也没有硬性轮次上限。
- 应用崩溃后不会自动重放外部操作。工作记录都在,但中断的操作需要核对后再继续。
- 设计师的视觉质量还没有做跨模型对比。上面的修复只保证工具链不再拖后腿。
如果你想试试,下载地址在这里。群聊协议的完整说明在仓库的 docs/group-protocol-v2.md,问题和建议欢迎提到 Issues。