- shaxiaozili2026-09-0768808
我之前反复研究 LangGraph 和 Google 的 ADK ,想搞清楚一个 agent 运行时到底是怎么工作的,但每次都卡壳。不是说它们不好,而是等我穿过三层抽象之后,已经彻底搞不清楚哪些东西是"必须的"、哪些是附加的。所以我干脆自己写了一个尽可能小、但仍然保留生产级 agent 该有的关键特性的东西:崩溃恢复、human-in-the-loop 暂停、有界并发,以及并行分支下的确定性状态。
项目叫 prodagent: https://github.com/limenagent/prodagent
内核大约 1800 行代码,分布在 11 个文件里,只依赖 Python 标准库(唯一的开发依赖是 pytest ; 70 个测试全部离线运行)。整体拆分得很干净,机制( mechanism )和策略( policy )分离:
• 内核完全不知道 LLM 是什么。它只有一个静态的 Plan (节点 / 边 / 状态通道)、一个针对每次执行的 Run ,以及一个
Scheduler——它每一轮( wave )只做一件事:算出"现在谁可以跑",并发执行它们,然后在一个屏障( barrier )处统一提交。• 状态是一个投影( projection ),而不是一个存储( store )。一份只追加的事件日志才是唯一真相源;状态是通过每个通道各自的 reducer 从事件日志折叠( fold )出来的。checkpoint
只是这个折叠结果的一份可丢弃缓存——这也是为什么"崩溃后恢复"和"时间旅行(回放)"几乎是免费得到的。• 控制语义故意只留两个命令:Goto (重新激活一个静态节点 / 走回边 / 做 handoff )和 Send (在运行时实例化一个 fan-out 模板)。内核里没有 ReAct 节点,也没有"agent 模式"的枚举——ReAct
说白了就是两个节点加一条回边,在内核之上一个可替换的层里拼出来的。多 agent 之间的 handoff 也不是一个新的原语,它就是一次指向另一个 agent 节点、且没有返回边的 Goto 。• 模型、工具、子 agent 和存储全部通过"端口( port )"接入,所以同一个内核在测试里可以完全离线地跑在写死的 fake 实现上。
make play 会打开一个零依赖的本地 playground ,你可以在里面看到 wave 的时间线、看并行分支如何折叠状态,并且可以在某次运行中途批准一次工具调用,让它从 checkpoint 处继续执行。文档是中英双语的。
它不是什么:它是单进程的,自带的持久化只是一个基于文件的 checkpoint 存储,没有分布式调度器,也没有多租户能力。这是一个带有明确态度的"教学工件"——核心想法是"花一个周末读懂这个,再回去看 LangGraph /
ADK ,那些抽象自然就懂了"。我很想听听两个问题上的反馈:这种基于 BSP ( wave barrier )的调度方式,相比纯 actor 模型,是不是这类工作流更合适的默认选择?以及把控制语义压缩成只有两个命令,到底是真的更清晰,还是只是我个人偏执的怪癖?内核内部任何细节都欢迎问。
主楼 - 暂无回复