Wink Pings

1800行,一个周末读完Agent框架内核

prodagent 是一个教学级 Python Agent 运行时内核,约 1800 行、14 个文件、零第三方运行时依赖。它把 Agent 框架拆成 Plan、Run、Scheduler、EventLog、Interrupt、Bus 六个部件,并用离线示例演示 ReAct、先规划后执行和多 Agent 协作如何从同一套原语拼出来。适合想真正看懂 LangGraph、Google ADK、CrewAI 背后机制的人。

调试 Agent 框架时,最难受的是运行时像个黑盒。框架能跑,但你看不清一次执行里状态怎么变、事件怎么记、人在哪一步被拦住。

Dan Kornas 最近在 X 上发了一个项目 prodagent,定位是教学级 Python Agent 运行时内核。目标读者是愿意读代码的构建者,想弄明白 LangGraph、Google ADK 这类框架背后的原语。

它刻意做小。内核六个部件,每个只管一件事:Plan 是可复用的步骤蓝图,Run 是一次执行和状态,Scheduler 驱动波次,EventLog 记录事实,Interrupt 停下来等人,Bus 让外部观察、裁决和订阅。净代码约 1800 行,14 个文件,零第三方运行时依赖,测试全部离线可跑。作者说一个周末能读完。

prodagent 内核示意

同一副骨架,换了身衣服。Dan Kornas 把 prodagent 的核心概念映射到主流框架,思路很直接:先认清每个部件负责什么,再去看别的框架把同一个决定藏在哪个名字下面。

要解决的事prodagent常见框架里的同类做法
可复用的步骤蓝图Plan = Node / Edge / ChannelLangGraph 的 StateGraph;ADK 的 workflow / agent 图;CrewAI 的 Process + Tasks
一次执行和状态Run + 通道与合并规则LangGraph 的 State + checkpointer;ADK 的 Session
驱动执行的引擎Scheduler 每波重算就绪集合LangGraph 的 Pregel 超步;ADK 的 Runner;CrewAI 的 kickoff 循环
运行时跳转与扇出Goto / SendLangGraph 的 Command(goto/send);ADK 的 transfer;OpenAI 的 handoff
停下来等人Interrupt,之后 resumeLangGraph 的 interrupt + Command(resume);ADK 的人工输入
事实源 / 重放只追加的 EventLog,状态是事件折叠LangGraph 的 checkpointer + time travel;ADK 的会话重放
从外面观察和拦截Bus:旁观 / 裁决 / 订阅LangGraph 的 callbacks 与 stream;ADK 的 EventBus

机制在内,策略在外。内核里没有 ReAct 类,也没有运行模式开关。ReAct、先规划后执行、多 Agent 协作,都在应用层用同一套原语拼出来。换一种编排,内核一行不用改。

应用层(策略):ReAct · plan-first · 多 Agent · 你
        ↓
内核(机制)· 六个部件
Plan → Run → Scheduler → EventLog
                 ↘ Bus / Interrupt

怎么跑起来也不复杂。项目给了一个不花 API Key 的入口。ScriptedLlm 按剧本演戏,结果确定,离线可重复。

git clone https://github.com/limenagent/prodagent && cd prodagent
pip install -e .

prodagent run
prodagent run --trace
make play

prodagent run 会离线跑通完整流程,中途在终端答一句人工审批。加 --trace 会把同一次运行渲染成父子 Run 的因果树。make play 打开网页版,能看轨迹、事件、状态、文件和图。想接真模型,设一个 OPENAI_API_KEY 换成任意 OpenAI 兼容接口,其余代码不用改。

API 也短。节点就是 async def fn(input, ctx)。直接 return 把结果交给下游;要改道就 go(目标, 值);要扇出就 return [send(模板, x) for x in items];要停下等人就 wait_human(问题)。问题和回答都进日志,恢复时从事实继续。

from src import Agent, Workflow, go, send, wait_human

agent = Agent(name='researcher', model=llm, instruction='...', tools=[search])
await agent.run('帮我查 X')

wf = Workflow()
wf.add_node('diagnose', diagnose_fn)
wf.add_node('repair', repair_agent, terminal=True)
wf.add_edge('diagnose', 'repair')
wf.entry('diagnose')
await wf.run('故障')

有网友在回复里说,剥掉品牌,大多数框架就是一个队列,其中某一步刚好调用模型。Dan Kornas 回了一句更具体的:如果 worker 在工具跑完、结果还没保存时崩了,幂等性会占掉你一下午。这个细节比讲一堆抽象概念有用。

项目开源,MIT 许可。仓库里还有框架对比、常见问题、术语表,以及一篇 30 分钟手写最小内核的文档。它不解决所有生产问题,但适合在信任一个框架之前,先把循环读一遍。

原推文

GitHub 仓库

发布时间: 2026-10-26 04:38