我准备自己做一个 agent 调度层
前段时间我在 AI 随想第十篇 里下过一个判断,代码学会了自我进化。当时的证据是 Peter Steinberger,一个小时做出 OpenClaw,三个月 25 万颗星,没有团队,软件自己改自己。这个判断我现在也不改,agent 确实能读自己的源代码,能看懂架构,能自己提 PR,这些都是真的。
但拿我自己每天的工作流一对,就会发现中间还缺一层。我现在每天大概是这么干的:
- 打开 claude code
- 描述一个任务
- 看它干 20 分钟
- review PR
- merge
- 再开一个终端
- 描述下一个任务
- 重复
你看这个流程,每一步中间站着的都是我。调度是我在做,review 是我在做,哪个任务依赖哪个任务、得排在谁后面,也是我在脑子里算。把 context 从一个终端复制粘贴到另一个终端的是我,瞄一眼 Linear、算哪个 issue 对应哪个终端的还是我。这些活没有一件真的需要人来判断,全是系统该干的事,但现在全压在我身上。
所以只能说,模型是会写代码了,harness 也很好用,但这个环还没真正闭上。调度 agent 的那一层还没有人做出来,现在是我自己在人肉当这个调度层,每天排任务、盯进度、把 context 从这搬到那,都是我手动在干。这篇就讲讲我准备怎么把这一层做出来。
模型会写代码,但调度、review、依赖排序每一步中间都站着人——人肉充当了那层缺失的调度器。
先看了一圈市面上有什么
动手之前我花了一周,把号称能解决这个问题的开源项目都扒了一遍,主要看它们各自做到了哪一步。
Composio Agent Orchestrator,5650 颗星,MIT 协议。它是里面做得最认真的一个。插件架构很完整,7 个类型接口把 runtime、agent、workspace、tracker、SCM、notifier、terminal 全覆盖了。session 的生命周期有 16 种状态,CI 挂了还能自动响应。工程上是真下了功夫的。
但打开引擎盖一看,执行层是 tmux 跑在单机上,靠轮询,状态存在平面文件里,还有一个 setInterval 一遍遍检查 agent 还活没活着。它没有持久化执行,进程要是在任务中途挂了,session 就没了。它也没有 Linear Agent Sessions,没有靠 webhook 驱动的事件流。
AgentsMesh,1200 颗星,Go 写的。它做的是把看板绑到 Pod 上,还有实时的拓扑可视化。我觉得它架构上的直觉是对的,ticket 的内容直接变成 agent 的 prompt,MR 和 ticket 自动关联起来。问题是它用 BSL 协议,不能随便用。它也没有飞书集成,没有 Temporal,部署模型也跟我要的对不上。
dmux,1300 颗星,MIT 协议。它是个本地的终端多路复用器,按 n 开一个新 pane,输入 prompt,按 m 把输出合回来,简洁到了极点。但它也就到这了。它纯粹是个本地工具,没有 API,没有 webhook,没法从一条聊天消息触发,也连不上任何项目管理工具。
这三个各自都做对了一些事。Composio AO 的插件接口设计得好,AgentsMesh 拿看板来绑定,这个抽象选对了,dmux 证明了交互模型可以做到极简。但没有一个能做到我要的效果。说具体点,我要的是发一条指令进去,最后拿到 review 过、合并好的代码,中间这一段完全不用我插手。这三个离这一步都还差一截。
我想要的场景,拆开是五个问题
我想要的场景是这样的。我在飞书发一条消息,「实现 JWT 用户认证,给所有 API 加上限流,写集成测试」,然后去泡杯咖啡。等我回来,三个 Linear issue 已经建好了,三个 PR 开着,都自动 review 过了。通过的已经合了,没通过的那个,agent 读了 reviewer 的意见,改完又提了一版。飞书里还有一张汇总卡片,告诉我中间发生了什么。整个产品就干这一件事,把我现在人肉干的那部分调度活全接过去。
但要让它真的跑起来,得先回答五个问题。市面上没有一个工具同时解决了这五个:
-
状态怎么活过 30 分钟。agent 干一个复杂任务可能要半个小时,编排器要是在第 29 分钟崩了怎么办?换成 Composio AO,答案是全白干。传统的 serverless 会超时,cron job 也管不住工作流的状态。所以需要持久化执行,崩了能恢复,从上一个 checkpoint 接着跑。
-
等待怎么不烧钱。agent 提交 PR 以后,可能要等 5 分钟 review。这 5 分钟里一直轮询就是白烧算力,
setTimeout又靠不住。所以得让「等一个外部事件」这件事本身不消耗任何资源。 -
agent 怎么跟密钥隔离。你给 agent 开了 full-auto 的 bash 权限,环境里又放着 GitHub token、Linear API key、飞书凭证,那这些 agent 全能读到。只要一条 code review 评论里藏一段提示注入,攻击者就能把你环境里所有的密钥偷走。所以写代码的和调 API 的必须拆开,不能是同一个东西。
-
怎么防止 agent 自己批准自己的 PR。GitHub 本来就不让自己批准自己,agent 创建了 PR,CI bot 再用同一个身份去 review,GitHub 会直接拒绝。所以得有两个身份,一个写代码,另一个 review。
-
反馈怎么闭环。reviewer 在 PR 上留了评论,这条评论得送到写代码的那个 agent 手上,不能掉进通知收件箱。agent 得读反馈、弄明白、改代码、再推、再等下一轮 review。这一来一回横跨 GitHub 和编排器两个系统,还得一直记着状态,可能要持续几个小时。
这五个问题单独拎出来的话,每一个都有人解决过。只是我翻了一圈,没有找到把五个串在一起解决的工具,所以决定自己做一个。
核心的选择是 Temporal
Foundry 要干的就是把这五个问题串起来。架构上主要就做了一个选择,用 Temporal 做骨架,其他所有决定都是从这个选择推出来的。
Temporal 是一个 workflow 引擎,专门跑那种时间长、有状态、要跟外部系统打交道的流程,OpenAI 生产环境的 codex 就跑在它上面。它最关键的原语是 workflow.condition(),工作流停在那,不消耗任何资源,等一个 Signal 到了才接着跑。放到我的场景里就是这样:agent 提交 PR,工作流停下;GitHub 那边 review 完,触发 webhook;webhook 翻译成 Temporal Signal,工作流接着跑。整个过程不用轮询,不会超时,状态也不会丢。上面第 1 个和第 2 个问题,靠这一个原语就都解决了。
Temporal 的 condition 原语让工作流在等 review 时暂停、零资源消耗,直到 GitHub webhook 翻成 Signal 才恢复,不靠轮询。
密钥隔离是这么做的,在 Temporal 上面拆出三个 worker:
在 Temporal 之上把职责拆成三个 worker:编排 worker 不持密钥、agent worker 只有 AI key、集成 worker 独揽所有集成密钥,写代码的碰不到密钥。
- 编排 worker:轻量,只跑工作流逻辑,不持有任何密钥
- agent worker:CPU 密集,跑
claude -p和codex --quiet子进程,只持有 AI 的 API key - 集成 worker:IO 密集,调 Linear、GitHub、飞书的 API,所有集成密钥都在这
这样 agent worker 永远看不到 GitHub token,编排 worker 永远不碰子进程,每个 worker 能被攻击的地方都压到最少。就算真有一个 agent 被恶意的 review 评论注入了,最坏也就是写出一段坏代码。密钥它偷不走,因为它的环境里根本就没有。
工作流本身按任务的层级分两层。父工作流收到指令以后,让 claude 把指令拆成任务,建 Linear issue,并行 fan out N 个子工作流,最后汇总结果、发飞书卡片。子工作流只处理一个任务,写代码 → 开 PR → 等 review → 迭代(最多 5 轮)→ 合并,每个子工作流都跑在自己单独的 git worktree 里。父工作流负责往下分派,写代码、等 review 这些具体的活全在子工作流里干。
现在进行到哪了
说实话,Foundry 现在还没有一行能跑的代码。手上有的是五份调研报告、一份架构蓝图和一份安全审计。安全审计在最初的设计里找出了四个严重漏洞,在写第一行实现代码之前就全解决掉了。本来第一天就能直接开写,我还是先花了一周做调研,我觉得这一周花得值。
我在 AI 随想第八篇里写过,编排比生成更重要。Foundry 赌的是再往上一层,在 agent 上面做编排,或者说编排的编排。
后面会跟着 build 的进度接着写:
- 第二篇:五份调研报告教我的事
- 第三篇:三个 worker、三把钥匙,怎么给 agent 做权限隔离
- 第四篇:从第一条指令到第一个 PR,端到端跑通
- 第五篇往后:多任务并行、Linear Agent Sessions、失败恢复这些

