
【免费下载链接】overstoryMulti-agent orchestration for AI coding agents — pluggable runtime adapters for Claude Code, Pi, and more项目地址https://gitcode.com/gh_mirrors/ov/overstory点击查看免费下载Overstory 是一个面向 AI 编码智能体的多智能体编排系统其Headless无头模式通过stream-json协议驱动无头智能体并以事件流为核心实现全程可观测。本文带你深入理解spawn-per-turn进程模型、stream-json事件解析、邮件驱动的回合调度以及事件写入events.db的完整链路——无需tmux也能掌控整个智能体集群。什么是 Overstory Headless 模式无头智能体的默认运行方式Overstory 把一次 Claude Code 会话变成一支多智能体小队每个工人智能体运行在隔离的git worktree中通过 SQLite 邮箱系统协同最后把成果合并回主干。过去智能体常跑在tmux分屏里需要终端环境。而Headless 模式让智能体作为普通子进程运行用结构化的stream-json流代替肉眼盯屏。对新项目而言Headless 已是默认ov init会写入runtime.claudeHeadlessByDefault: true。维度Headless默认tmux逃生舱进程模型每个回合spawn一个新进程长期运行的终端会话I/Ostdout 走 NDJSON 事件流抓取分屏内容可观测ov serveWeb UI ov feedtmux attach肉眼盯屏适用场景CI、容器、UI 驱动集群、需要逐工具调用事件保真度想中途 attach 手动干预 两种模式写入同一个EventStore与SessionStore所以ov status、ov inspect、ov feed的表现完全一致。这正是无头模式底层可观测的根基。智能体按职责分为两类见 capabilities.ts任务型工人builder / scout / reviewer / merger / lead走spawn-per-turn引擎回合之间不留持久进程。常驻型coordinator / orchestrator / monitor长期运行走 worktree/process.ts 的长生命周期子进程。spawn-per-turn 点火一个回合如何驱动无头智能体传统想法是启动一个进程一直挂着。Overstory 的 Headless 走的是更彻底的spawn-per-turn每回合生成模型每收到一个用户回合初始派发、邮件批次、nudge就spawn一个全新的claude进程用--resume session-id恢复上下文处理完即退出。回合与回合之间没有任何持久进程。这个设计的妙处无状态、易恢复、天然适合并发调度进程不会挂死在中间。下面是一个回合的完整生命周期ov serve 检测到某 agent 有新邮件 │ ▼ startTurnRunnerMailLoop ──每 2s 轮询 mail.db──▶ 发现未读邮件 │ ▼ runTurn() ──▶ acquireTurnLock() 每智能体序列化锁进程内 跨进程 │ ▼ Bun.spawn( claude -p --output-format stream-json --input-format stream-json --verbose --strict-mcp-config --permission-mode bypassPermissions --resume session-id ) │ ├──▶ stdin 写入 user-turn NDJSON → 立即 end()EOF │ ├──▶ stdoutstream-json 事件流 ──▶ parseEvents() 逐行解析 │ │ │ ▼ 落库 │ events.db ▼ 进程因 EOF 退出 ──▶ 检测终止邮件 ──▶ 状态转移 ──▶ 释放锁关键参数由 claude.ts 的buildDirectSpawn()生成-p无头单次运行输出写 stdout 后退出--output-format stream-jsonstdout 输出结构化事件流--input-format stream-jsonstdin 接受 NDJSON 格式的 user turn--resume session-id后续回合恢复上一轮对话--permission-mode bypassPermissions让智能体无需逐次确认即可行动回合引擎的完整实现在 turn-runner.ts它负责从点火到熄火的全过程拿锁、重读会话、spawn、写 stdin、排空事件流、捕获新 session id、检测终止邮件、状态转移、处理中止信号。stream-json 事件流解析从 stdout 字节流到类型化事件无头智能体把一切都喊在 stdout 上。Overstory 的解析器parseEvents()位于 claude.ts负责把这条字节流翻译成类型化的AgentEvent对象。它的处理逻辑缓冲部分行流是逐块到达的可能一行 JSON 被拆成两块。解析器用buffer累积按\n切分末尾不完整的行留在 buffer 里等下一块。逐行解析每行是一个 JSON 消息按type字段映射为事件。文本批处理assistant的文本片段是增量到达的解析器用批处理窗口把它们合并——500ms 或累计 4096 字节先到先触发避免事件流被碎片刷屏。Claudestream-json到 Overstory 事件的映射如下stream-json 消息解析出的 AgentEvent说明assistanttextassistant_message文本增量按批合并assistanttool_usetool_use一次工具调用含 callId / inputassistantthinking跳过思考块不入事件流usertool_resulttool_result工具执行结果systemstatus会话初始化携带session_idresultresult回合收尾是否出错、耗时、轮数解析出的每个事件随即被分流落库通过teeStreamToWriter写入 events/store.ts 的EventStoreSQLiteWAL 模式 5 秒 busy timeout天然支持多智能体并发读写。参数瘦身工具入参会经过 tool-filter.ts 的智能过滤把原本约 20KB 的负载压缩到约 200 字节——只保留定位所需的路径、命令、pattern 等关键字段丢弃文件正文等大块内容让事后分析轻量高效。 正是这条stdout → 类型化事件 → events.db的链路取代了过去 TUI 模式下靠钩子事后重建的日志。结构化流里天然带有工具调用的时序、入参与结果保真度更高。邮件驱动的回合调度如何用一封信唤醒下一个回合既然回合之间不留进程那么下一封信到来时谁来把智能体重新点火答案是服务端的邮件调度循环startTurnRunnerMailLoopheadless-mail-injector.ts。它的工作节奏每 2000ms 轮询一次mail.db查该智能体的未读消息。批量合并把多条未读邮件合成一个stream-json user turn而不是逐条各发一轮防止智能体对每条邮件都单独回应、却没来得及行动。驱动一个回合调用runTurn()生成一次claude --resume进程把批次写入 stdin。串行保护回合进行中时后续 tick 直接短路——绝不给同一智能体开第二个进程跨进程的串行再由回合锁兜底。失败重试只有runTurn成功退出码 0 且无异常后才把消息标记为已读失败则保持未读下一轮自动重试。一个 user turn 的 NDJSON 长这样由 headless-prompt.ts 的encodeUserTurn()生成{type:user,message:{role:user,content:[{type:text,text:[MAIL] From: lead | Subject: dispatch ...\n\n正文}]}}首轮派发的初始 prompt 则由buildInitialHeadlessPrompt()组合三部分prime 上下文ov prime输出的经验/配置/运行上下文待派发邮件激活口令以---分隔。这样智能体一睁眼就带着完整上下文开工。无头钩子等价物取代 TUI 生命周期的巧妙设计交互式 Claude Code 靠钩子SessionStart、UserPromptSubmit、PreToolUse…在生命周期各节点推事件。但无头进程没有钩子机制——它只从 stdin 读、向 stdout 写。于是责任模型反转钩子不再往外推而是由编排方从 stdout 拉事件、向 stdin 注入上下文与邮件。钩子等价物的责任从智能体的 shell 环境转移到了服务端的ov serve/ coordinator 进程。完整的设计与映射见 headless-hooks-design.md。各钩子在无头模式下的归宿原钩子tmux 模式无头等价物处理方式SessionStart→ov prime初始 stdin prompt替代SessionStart→ov mail check --inject初始 stdin prompt替代UserPromptSubmit→ 邮件检查服务端注入循环ov serve替代PreToolUse守卫headlessOnly子集部署保留并部署PostToolUse→ov log tool-endstream 解析器已捕获跳过冗余Stop→ov log session-end解析器收到result事件跳过冗余Stop→ml learn需智能体侧 shell无法服务端化省略PreCompact→ 压缩重注入检测 compact 事件后重发延期一个值得一提的反转早期设计以为无头模式下PreToolUse守卫不会触发于是跳过部署。后来实测发现claude -p --output-format stream-json确实会分发settings.local.json里的PreToolUse钩子。于是实现改为无头模式仍部署钩子但只保留PreToolUse这一安全子集路径边界、能力拦截、bash 危险命令等其余类型因已有无头等价物而被剥离。相关逻辑在 hooks-deployer.ts 的deployHooks(..., headlessOnlytrue)。稳定性三件套序列化锁、停滞看门狗与信号升级无头集群要长时间无人值守地跑稳定性设计是底层原理里最硬核的部分。 每智能体序列化锁turn-lockrunTurn绝不能对同一智能体重叠运行。锁是双层的turn-lock.ts进程内层模块级MapagentName, Promise同进程内并发调用排队。跨进程层turn-locks.db里的 SQLite 租约用BEGIN IMMEDIATE事务保证两个进程不会同时抢走同一行持有者 PID 不再存活时陈旧租约会被窃取。⏱️ 事件停滞看门狗若claude卡住API 阻塞、死锁进程会永久挂起。解析器设了一个停滞看门狗连续eventStallTimeoutMs默认 10 分钟没有任何 parser 事件就判定回合卡死主动SIGTERM。每个事件到达都会重置计时器所以再长的工具调用也不会误伤。 信号升级SIGTERM → SIGKILL无论是运维ov stop触发的中止还是看门狗触发的中止都遵循先礼后兵先SIGTERM优雅退出sigkillDelayMs默认 2 秒后仍未退场则升级SIGKILL强杀绝不留下孤儿进程。此外回合结束前 runner 会做一次契约校验如果claude干净退出收到isError:false的result却没发该职责对应的终止邮件builder/scout/reviewer/lead 的worker_donemerger 的merged/merge_failed会被记为契约违规并向父级合成一封worker_died邮件避免 lead 永远等一个不会到来的信号。长生命周期智能体的事件 tailer后台守护 stdout 日志上面讲的都是每回合生成的智能体。对于真正长生命周期的无头智能体例如以--json运行的 Sapling进程持续把 NDJSON 写到.overstory/logs/{agent}/{timestamp}/stdout.log。ov sling退出后就没人读这条流了——于是 tailer.ts 的startEventTailer()登场字节游标轮询每 500ms 用file.size作为游标只读上次之后的新增字节避免重复处理旧行。NDJSON 解析入库逐行JSON.parse映射为EventType写入events.db畸形行部分写入、调试输出静默跳过。session_id 固定从system/result事件的session_id字段提取并一次性持久化到SessionStore若与请求的 id 不一致还会触发resume 不匹配告警。绝不崩守护进程所有错误文件不存在、解析失败、写库失败都被吞掉——tailer 必须永远安静不能拖垮看门狗守护进程。看门狗守护进程会为每个无头会话启动一个 tailer会话完成或终止时停止它。可观测性用命令实时观察无头智能体集群无头不等于黑盒。事件全部落进events.db后一系列命令让你像tail -f一样盯着整支舰队实现见 feed.ts、logs.ts命令用途长尾场景ov feed --follow统一实时事件流跨智能体按时间合并像tail -f一样盯全舰队ov logs --agent name查询 NDJSON 日志按智能体 / 级别 / 时间过滤ov status所有活跃智能体、worktree、状态一眼看集群健康度ov inspect agent --follow单个智能体深度视图持续追踪某个工人ov trace target时间线事件回放还原某任务/智能体的先后顺序ov errors聚合错误视图快速定位失败ov replay多智能体交错回放复盘一次协作全过程 因为 Headless 与 tmux 共用同一套事件存储你在ov feed里看到的每一行都来自无头智能体 stdout 上那条被解析、瘦身、落库的事件流。核心源码导航Headless 模式关键模块速查想动手读源码按这条链路走最快关注点模块路径回合引擎点火到熄火turn-runner.tssrc/agents/turn-runner.tsClaude 运行时 stream-json 解析claude.tssrc/runtimes/claude.ts邮件驱动回合调度headless-mail-injector.tssrc/agents/headless-mail-injector.ts初始 stdin prompt 编码headless-prompt.tssrc/agents/headless-prompt.ts事件解析入流长生命周期tailer.tssrc/events/tailer.ts事件存储events.dbstore.tssrc/events/store.ts工具参数智能瘦身tool-filter.tssrc/events/tool-filter.ts每智能体序列化锁turn-lock.tssrc/agents/turn-lock.ts长生命周期无头子进程process.tssrc/worktree/process.ts职责分类任务型 / 常驻型capabilities.tssrc/agents/capabilities.ts钩子部署含 headlessOnlyhooks-deployer.tssrc/agents/hooks-deployer.ts无头钩子设计文档—docs/headless-hooks-design.md小结Overstory 的 Headless 模式把盯屏这件事彻底重构了spawn-per-turn——每回合生成一个全新claude进程无状态、易恢复、可并发。stream-json事件流——stdout 上每一行结构化事件被parseEvents()解析、批处理、瘦身统一落库events.db。邮件驱动调度——服务端循环轮询邮箱把未读邮件合成 user turn重新点火下一个回合。稳定性兜底——序列化锁防重叠、停滞看门狗防卡死、SIGTERM→SIGKILL 防孤儿、契约校验防静默失败。理解了这条stdin 点火 → stdout 事件流 → 落库可观测 → 邮件再点火的闭环你就掌握了无头智能体与事件流的底层原理——这也正是 Overstory 能在 CI、容器等无终端环境里可靠编排整个 AI 编码智能体集群的关键。赞分享【免费下载链接】overstoryMulti-agent orchestration for AI coding agents — pluggable runtime adapters for Claude Code, Pi, and more项目地址https://gitcode.com/gh_mirrors/ov/overstory点击查看免费下载相关推荐Presto ORC 文件格式解析文件、Stripe 与 Stream 的三层结构及自底向上解码原理Presto ORC 文件格式解析文件、Stripe 与 Stream 的三层结构及自底向上解码原理 导读 本文以 orc file format.md ht大数据数据库后端Thorium开着一堆标签不烫手的 Chromium 浏览器3 个关键点一次说清Thorium开着一堆标签不烫手的 Chromium 浏览器3 个关键点一次说清 Thorium 是基于 Chromium 深度优化的浏览器以元素周期表桌面应用跨平台CAP 分布式事务框架集成 RabbitMQ完整配置指南与底层原理解析CAP 分布式事务框架集成 RabbitMQ完整配置指南与底层原理解析 本指南围绕开源项目 CAP基于最终一致性 Outbox 模式的事件总线官方文档后端消息队列微服务创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考