Flowness / 多 Agent 系统真实问题 · 首期

协调者记住了教训,为什么下一批 Agent 还会重犯

协调者三天五次认出“干完不交卷”,却没有修改下一批 Agent 的派发说明。另一条工作线里,教训已经进入共享日志、被后来者读到,重复派发仍未停止。我们沿真实案例追问:经验存在哪里,谁会在行动前遇到它,谁能据此改变下一步,以及怎样验证改变真的发生。

我们在开发 Flowness 时,曾遇到一种很难靠增加记忆解决的失败:协调者已经知道哪里会出错,也调整了自己的做法,下一批 Agent 却仍然在同一个地方受阻。复盘记录在增加,系统对新来者的要求没有跟着改变。

Flowness 是我们自己开发的 Harness 项目,用来组织多个 AI Agent 持续协作,管理任务、上下文、工具调用与工作记录。开发这样的系统,本身也需要多个 Agent 分工:有的整理设计,有的核对实现,有的审查前面几方的结论。一次工作可以不断换人,但从失败中学到的东西应当留下来,改变后续工作的条件。这是我们期待的持续协作能力。

2026 年 7 月,我们在一条设计审查工作线上看到了相反的情形。一个协调者三天里五次记下“干完不交卷”的模式,逐渐学会查文件、补材料、调整催报方式,却没有把报告到底该怎么送回来写进后续派发说明。后来复核的 67 份派发消息中,没有一份点明需要使用的回传工具。

本文讨论的,是一条经验如何跨过会话边界,真正影响下一次工作。

报告写出来了,协调者却只收到“空闲”

这条工作线正在审查 Flowness 的设计重建成果。我们借助开发环境原生的团队协作功能,安排多个独立会话分别核对痛点、拆解工程任务、攻击已有裁决。它们通过团队信箱与协调者通信。这里发生的交付问题,来自这套临时协作方式;弄清这一点,才能知道该改哪一处入口。

其中一位审查者负责判断:前面的设计工作究竟解决了原来的事故,还是只增加了一批文档。它读了事故材料、检查设计卷宗,又调用子代理核查代码,最后整理出报告。随后,它把报告写在自己的最终回复里。

协调者没有收到报告正文,只收到一条空闲通知。

两边对“交卷”的理解不同。在一种常见的子代理调用中,最终回复会自动返回给调用者;这次使用的团队信箱要求显式调用发送工具。纯文本回复仍留在子会话里。空闲通知只说明会话暂时停止运行,不是报告已经送达的回执。

协调者催它交卷。审查者认为自己已经写过,于是再次输出报告;协调者依然只收到空闲通知。第二次催促甚至要求它立即输出、不要再调用工具。这句话把它进一步推向了错误动作:而当时恰恰需要一个工具调用,才能把正文送出去。第三次文本回复之后,协调者把它判断为“三次空闲零产出”,自行补做了原本交给它的工作。

同组另外两名执行者给出了有用的对照。一名在第一次汇报前主动查找发送工具,随后成功投递。另一名也先写了纯文本,但收到催促后发现报告没有走团队信箱,补发后成功送达。三者面对相同的交付要求,结果取决于它们是否自行发现了这项没有写进派发说明的要求。

这使问题具体起来:报告内容可以已经完成,协作交付仍然失败。发送工具本身也并非不可用。系统把“找到正确通道”留给了每个新会话临场推断,却用“返回报告”这样的措辞,让不同交付方式看起来没有差别。

学习确实发生了,但落在协调者的补救动作上

如果只看这三名执行者,容易把问题解释为个别 Agent 没有发现工具。后来的复核回到协调者整条会话,发现它早就遇到过这种情况。

7 月 24 日 10 时 18 分,协调者已经指出:这是之前出现过两次的“干完不交卷”模式,不能把空闲当作完成。约 17 小时 50 分后,它派出前述审查者,后者仍然只输出文本,没有送回正文。更晚派出的会话中,也出现了同类结果。

协调者并没有原地不动。它先改成查文件是否落盘,再催报告;后来又形成“空闲即查落盘”的规程,因为反复催促已被它判断为无效。这个改变帮助它继续推进工作:能找到的成果直接收集,收不到的部分自己补做。

但这些经验进入的是协调者自己的工作习惯。下一名执行者拿到的派发说明,仍然没有报告回传方式。它看不到上游昨天如何诊断问题,也不继承前一名执行者尝试失败的过程。协调者越来越擅长处理后果,新来者面对的条件却几乎没变。

协调者确实调整了处理方式,但新会话仍拿到没有明确回传要求的派发说明。两区是同一工作线上的并行观察,不能把补救动作画成导致漏写说明的已证实原因。

复核检查了全部 67 份派发消息,确认它们都没有提到那项发送工具;另按团队消息统计,64 个出现过的子会话中,6 个始终没有送达正文,另有 4 个出现过额外的空闲往返。67 是派发消息数,64 是子会话数。它们让我们看见同一套说明被反复使用的范围,不能当成 67 次失败。

更值得追问的是:为什么一次有效的局部学习,会容许系统继续重复出错?一种与这条轨迹相符的解释是,补救动作先解决了协调者眼前的阻塞。它能继续工作,就更容易把经验收在自己的处理流程里,而没有回到下一批任务的输入处。新执行者又是一次性的,无法靠自身反复练习来补上这个缺口。

因此,复盘时只问“有没有记住教训”不够。还要问这条教训改变了谁的哪一个动作。这个案例里发生变化的是上游收不到报告后的处置,真正需要同时改变的却是下游第一次交报告的方法。

教训进入公共记录以后,还需要有人能据此行动

顺着前面的案例,我们很自然会想到把经验写进共享知识库。但另一条工作线表明,共享和读取也各有边界。

当时一项修复任务被连续派发了五次。后续会话核对改动、重跑测试,得出一致结论:修复已经准备好,等待总控终审。到了第四次,会话明确把重复派发写进共享日志,建议检查触发通道。第五次会话读到了前序记录,也知道这是第五次,仍然又完成了一轮独立复核,再次报告异常。最后,这项工作经过人工触发的集中处理收口。

这里已经无法把原因归结为“没有读到”。记录放在共同使用的地方,后来者确实读了,判断也没有分歧。问题落在另一个位置:执行会话能够读写日志,却没有相应权限去修改派发、回流或升级通道。它能再确认一次“已经准备好”,无法让调度方据此停止重派。

两种断点要求不同的改动。回传案例需要把交付要求带到新会话的任务入口;重复复核案例需要让已有结论进入掌握派发状态的那一方,并使它能在权限范围内改变下一次动作。给后者增加一段更醒目的提醒,只会让执行者更明确地描述自己无力改变的情况。

这也留下一个不能跳过的研究问题:究竟是哪条通道持续触发重派?当时的调查没有定位到具体触发代码,执行者提出了若干候选原因。因此,我们可以明确下一步要找的是“谁读完成状态、谁决定再派”,还不能把某个候选开关写成已经验证有效的修复。

一个更好的落点,以及一条根本不可执行的建议

同批运行记录里,有一个朝正确方向前进的例子。后台进程在处理位置落后较多时被重新启动,积压工作集中涌入,带来大量对账负担。协调者把这次经验写进了运行服务说明中对应进程的一节,又整理成六步复工操作流程。

这次,经验有了明确的使用场景。准备重启的人可以在运行说明中看到风险,恢复工作的人有具体步骤可循。与只在某个会话里记住“下次注意”相比,改动已经进入后续操作的说明入口。

这条反例使我们的判断更精确。我们确实能够把教训写进后来者会使用的操作材料;下一步要看的,是后续重启有没有按这份流程执行,以及积压问题有没有因此减少。当时的记录没有继续给出这段运行结果,入口的改善与运行成效应当分开验收。

两例有不同的缺口。共享日志已经被读取,仍需要掌握派发权限的一方改变安排;操作说明已经更新,仍需要后续运行证明行为与效果发生变化。两例不是同一事件的连续阶段。

反过来,进入待办清单的建议也未必具备可执行性。回传问题的早期调查曾建议修改本地配置,让发送工具默认加载,并把它列为高优先级。后来复核发现,建议所指的权限配置控制的是自动批准,不控制工具描述是否预先加载;按原建议操作,达不到它声称的效果。

这又改变了“为什么教训没落实”的解释。如果一条建议根本没有对应的可用操作,给它找负责人、提高优先级、反复催办,都不能完成修复。先验证建议能否改变目标行为,才有理由继续追问传递和执行。这一步也能防止系统把错误修法沉淀得越来越牢。

下一次出现同类情境时,哪一步会不一样

这些经历让我们把跨 Agent 学习的检查对象,从经验文档转向下一次具体工作。

对报告回传,可以让一个没有经历过旧事故的新会话,只依靠更新后的派发说明完成任务,再观察它是否在第一次交付时使用正确通道、上游是否收到正文。成功发送一条测试消息还不够;任务真正结束时是否再次正确交付,才对应原来的失败情境。

对重复派发,需要在目标已经复核完成、输入没有变化时,观察调度方是否仍然创建同一任务;同时保留输入变化后重新检查的能力。否则,停止了重复工作,也可能顺手阻止必要的新复核。该由谁接收完成信号、谁有权改变状态、什么变化允许再次派发,必须落到这条实际工作链上。

对复工流程,则要追踪下一次恢复时读到了哪个版本、执行了哪些步骤、积压如何变化。流程可能写得正确但没有被打开,也可能被完整执行却仍不足以处理新的运行条件。两者需要的后续修改不同,不能共同归入“经验已经沉淀”。

我们还没有从这些历史案例中得到一个普遍有效的记忆方案。它们带来的推进,是把一个过于宽泛的问题拆得可以调查:建议是否可执行,后来者是否在行动前遇到它,遇到之后是否有能力改变动作,变化是否在真实运行中发生。这几项之间缺少哪一项,就应当沿那一项继续取证。

某个协调者熟练地收拾残局,是有价值的能力。一个持续协作系统还需要把这种能力转移到工作条件里,让新来的 Agent 不必先经历相同的失败。对我们来说,一条教训最有说服力的后续证据,是后来者第一次遇到那个情境时,已经能够做出不同的动作。