ARTICLE · 1234348
Raft 源码拆解:多 Agent 协作如何处理消息、任务与记忆
多个 Agent 同时工作,很快会遇到几个问题:回复写到一半,对话已经变了;任务分给了某个 Agent,却不知道它有没有开工;进程恢复了,旧会话里的信息是否仍然有效。
Slock 更名后的 Raft,把这些问题做进了协作平台。它在 Claude Code、Codex 等运行时之上,增加持久身份、频道、线程、任务和机器管理。

团队状态与模型执行分层
Server 保存身份、消息、任务和权限。Computer 在用户机器上管理 Daemon,Daemon 再连接各个 Agent runtime。Agent 通过捆绑的 raft CLI 读消息、发言、认领任务、提交附件。
这里保留了运行时差异:Claude 使用 stream-json 子进程;当前 Codex 接入的是常驻 app-server,通过 JSON-RPC 启动线程、恢复会话、追加输入;Pi、Kimi 还有 SDK 路径。不同 Agent 可以用不同模型、跑在不同机器上。
它们共享可访问的频道和任务,各自保留模型上下文与工作目录。一个 Agent 掌握的信息,需要通过消息、文件或任务证据交给其他参与者。

收件箱让 Agent 自己选择何时补读
A 在线程里请 B 检查改动,Server 会保存消息,解析提及身份,再根据频道成员、线程关注、静音和可见性决定通知谁。B 允许自动运行时,系统可以唤醒它;人工停止则有单独处理。
普通新消息常先留在 Daemon 收件箱,模型收到的是无正文的未读通知。B 在适当时机调用 raft message check 或 read 拉取正文,决定是否回应。线程加入背景、恢复补读等路径也可以直接带内容。
这个区分很实际:通知写进进程,只能说明传输完成,不能证明当前模型已经读到正文。Raft 为投递、排队、读取和确认分别留状态,避免用一个 online 标记解释整段交接。
可见回复也必须走 raft CLI。模型在终端输出了一段话,不会自动成为频道消息。
发言之前,检查对话是否已经变化
假设 A 读到第 10 条消息开始构思,B 随后发出第 11 条更正。Raft 的发送请求会带上 A 当前上下文的读取证据。Server 发现相关新消息尚未覆盖,就暂缓发送,由 CLI 保存草稿并返回补读信息。
A 可以修改草稿、原文重发或保持沉默,也有显式 anyway 绕过。平台把状态变化暴露给 Agent,让它重新判断发言是否还合适。
读取证据还区分连续游标和零散观察。只看过 12、14,不能把此前所有消息都标成已知。有 contextId 信号时,新模型上下文也不能直接沿用旧上下文的已读记录;没有信号时保留兼容行为。这部分由 contextId 和本地 SQLite 账本共同支撑。

源码中的 held 响应可能使用 HTTP 200,但 CLI 会明确返回消息未发送、草稿是否保存。网络结果不明确时,再用原 idempotencyKey 查询提交状态,降低重试造成重复消息的概率。这个保证只覆盖消息协议,不能外推到部署等业务操作。
长期记忆与短期会话分别维护
Agent 身份长期存在,不要求模型会话无限延长。Raft 分别维护服务端协作记录、本地 MEMORY.md 和工作文件、长期指令,以及原生 runtime session。
当服务端开关开启,且会话满足默认闲置超过一小时、上下文超过 128K token 等条件时,下一次启动可以建立新 session。初始输入由记忆文件头部、近期消息、近期动作、文件当前内容等块重新构成,没有另请模型写摘要。
重新读磁盘有直接价值:旧工具输出里的文件内容可能已失效。较老对象只保留指针,也能减少把旧计划误当成当前任务。

这项自动决策在当前源码中主要由 Claude 的会话事实读取器支撑。其他 runtime 缺少可靠的大小或时间事实,就继续 resume,不能写成所有模型都已覆盖。
上下文压缩还有另一道处理:能观测压缩的驱动在压缩开始时刷新 context generation,让旧的已见证据失效。系统区分了同一个进程、同一个 session 和同一代上下文。
任务认领用数据库处理竞争
当前 Task 以独立 tasks 表为规范存储,聊天消息负责关联需求和讨论,task_events 记录变更。部分手册仍用消息附加 metadata 解释任务,架构分析应以实际 writer 为准。
两个 Agent 拿着同一个 revision 认领,条件更新只允许一个提交该版本。分配操作会清空 claimedAt,让分给某人和已经开工保持区别。任务可以经过 in_review,也允许其他合法流转,平台没有把每个任务都强制变成人工审批链。

还有一个少见的细节:标记为创建资源的任务,完成前必须填写资源回执,带上用途、到期时间和清理负责人。回执与到期 follow-up 在同一事务建立,资源善后有了持续记录。
这些机制保护任务归属与记录。它们不会自动锁文件、合并 Git 分支或证明代码正确。跨机器协作仍需要产物共享、代码集成和验收方式。
恢复与权限都有适用边界
Raft 为有效 Agent mention 维护逐跳回执,并绑定机器、launch 和 session 身份。Daemon 也把运行结果先持久化再发送,精确确认后删除。若硬崩溃导致前次运行结局无法确认,部分恢复路径会停下来等待人工启动。
普通服务端 inbox 本身是有上限的内存缓冲,跨重启恢复依赖消息、未读事实和投递记录。收到 ACK 也不能证明模型理解、任务完成或外部操作只执行了一次。
凭据方面,Daemon 通过本地代理持有 Server key,给每次 launch 分配受约束的访问入口。这个设计保护凭据使用路径。主机执行权限则是另一件事:Claude、Codex 的驱动配置包含宽权限执行选项,工作目录分开不构成系统沙箱。

总结
Raft 适合长期角色、多机器、混合运行时持续交接的团队。值得借鉴的设计是读取证据绑定上下文、发送前检查共享状态变化,以及把分配、认领和完成状态拆开。业务验收由参与者负责。严格流程、代码隔离和业务幂等仍需团队补齐。
本次只验证了三条真实源码策略:稀疏读取不抬高连续游标,新上下文屏蔽旧读取证据,并能建立自己的读取边界;未运行完整平台或多 Agent 效能测试。
仓库采用 FSL-1.1-ALv2,官方称其为 source-available:存在竞争用途限制,每个版本两年后转 Apache 2.0。它是发布快照镜像,开发在私库进行,目前不接受外部 PR。















































































