# 我是如何用 Orca 做 Graph Engineering
**作者**: Aiden
**日期**: 2026-07-27T07:39:16.000Z
**来源**: [https://x.com/wohsj110/status/2081645581379031509](https://x.com/wohsj110/status/2081645581379031509)
---

我做移动端开发。这一个月手上有几个大需求,拆成一百多个任务交给一批 agent 去跑,我用 Orca 的编排调度它们。
先讲这个月最典型的一次。
一个新功能,开工前我把需求交给它,让它先拆。出来 12 个任务,依赖也标好了:先加类型枚举,再做功能本体和它的面板,然后注册进入口列表,最后接上层入口、跑终验。我看了一遍,觉得挺完整。
跑到第五个任务,agent-device 的验收没过。
agent-device 是个开源库,让 agent 直接操作真机跑用例:按步骤点进去,看该出现的东西有没有出现。我拿它当端上行为的验收手段。
诊断结果指向的不是实现,是计划里的一个前提:「后端和 Runner 已就绪」。在真机上跑一遍就发现,runner 和 scheduler 压根不认这个新类型,直接当成不支持。
这不是漏了一个检查,是整张图有一段建立在一个假前提上。后面 010、011 都挂在它下面。

只画受影响的那一段。左边是开工时的计划,右边是改完的样子。
然后 orchestrator 自己补了一个任务:013,后端服务实现,P0,并且把 010 和 011 的依赖都改成要等它。它给这个任务写的备注是「task-005 真机暴露:后端/Runner『已就绪』是假前提」。
编号排到 013,是因为它最后才被创建。但在依赖图上,它的位置在 010 前面。
这一轮我没有插手。agent-device 给出的是不可争辩的证据,orchestrator 拿着这份证据判断出前提不成立,然后补节点、重连依赖,接着往下派。但它能做这个判断,是因为那道验收是我提前设计好、并且允许它拦下游的。
这种「以为就绪、其实不是」的东西,七月七号 Anthropic 的 @trq212 有个说法:地图不是疆域。
你给 agent 的 prompt、skill、spec、case 代码,都是地图。真实的代码库、线上约束、没人写下来的规矩,是疆域。两者的差他叫 unknowns。最麻烦的是 unknown unknowns:你连自己漏了什么都不知道。
十一天后,另一个词火了。@steipete 发了一句调侃:are we still talking loops or did we shift to graphs yet。八天之内,时间线上多了一个工种名。
先把这篇要论证的说在前面
graph 先解决一件事:长活怎么拆开、怎么往下接。但它只解决这一件。跑得对不对要靠 eval,跑偏了能不能拐回来要靠改图权。

三样同时成立,长任务才立得住。
开头那件事就是三者结合在一起的样子:图把活拆开跑起来,agent-device 把假前提拦下来,orchestrator 拿着这份证据补节点、重连依赖。
要是少了第二件,005 会报完成,后面挂在假前提上的节点继续跑。那时候你拿到的才是假成功:每步都绿,整张图却建在空气上。少了第三件,就算发现了也只能整单推倒重来。
下面按这三样各讲一节,最后讲它们怎么结合成一个整体。
共识部分,快速过
怎么拆 graph,已经有人讲得很清楚了,我不重复。四条我天天在用的都在图里,出处也标了:先判断这活要不要 graph(@ericosiu 的 rails / motor 最好用),砍掉不传数据的边,把执行和复核分开,按节点难度选模型。

四条做法与出处都在图里。第三条的三角色拆分和三轮复核是我自己的实现,@rohit4verse 的原话只支持「执行与复核要分开」。
@humzaakhalid 讲成本那句我印象最深,因为我就是这么发现的:people discover this on the invoice。你不会在设计的时候意识到一次宽的并行按顶配计费,你会在账单上意识到。
这四条做好,你会得到一张跑得挺远的图。我遇到的问题都在这之后。
## 一 · 跑得远:图是长出来的,不是画出来的

真实跑起来的样子(任务标题已模糊)。绿色是已完成,橙色是正在跑,蓝色是就绪待派,灰色是写好了还没轮到——四种状态同时存在,这是常态。这张图是用 npx orca-viz@latest 实现
这波讨论里最简的一条路径来自 @alex_frantic:先画 graph,再让 Codex 生成并运行脚本;按他的说法,没有第三步。
疆域已知的时候,这完全正确。标准化的 SOP,比如定时扫描、按模板出的报告、批量迁移、发版流程,形状跑过一百遍没变过,编译成脚本就是最优解,我自己也这么干。
但写一个新需求、加一个没做过的功能,就不是这么回事了。工程越复杂,你越没法保证开工前想出来的那张图是对的。该考虑的点有没有漏?这个改动会不会牵动一个你压根没想到的模块?上游那个接口是不是还有条没写进文档的约束?这些问题在开工那一刻,你答不上来。
这跟想得周不周全关系不大。有些事情就是要做到那一步才会露出来。方案评审的时候我一般都觉得考虑得挺全,然后动手到第三天,发现有个前提根本不成立。
先把家底摊开
这一个月的运行记录里一共 570 个任务,跨度 31 天,实际动手 15 天。这个数不能直接当工作量看:里面很大一部分是我试错试出来的,一个做法不成换个思路重来,同一件事就留下好几个任务。任务多有时候只说明我走了弯路。
带依赖关系、成规模的编排只有 4 组,共 76 个任务:41、15、13、7。下面讲的机制主要从这 4 组里长出来,最大那组是主要案例。数据取自 2026 年 6 月 26 日到 7 月 26 日的本机快照,只用来说明发生过什么,不拿来比效率和成本。

task graph 持续增长了 5 小时 10 分。如果「开工前把 graph 画完」是对的,这该是一条从 41 开始的水平线。
开工的时候,graph 上只有 2 个任务。首个任务 05:24:46 创建,11 秒后就派出去了;第二个 05:25:36 才建。把相同创建时间视作一批,41 个任务一共 33 个创建时间点:头一分钟建了 2 个,剩下 39 个分布在另外 31 个时间点上。
我不想把这 39 个直接说成「39 个 unknown unknowns」。晚创建也可能只是我懒得提前写,或者本来就是例行的复验。但有一批能认出来:任务名里带 recovery、reverify、correction 的那些,都是前面的任务真跑过一遍、暴露出问题之后才出现的。
## 我实际是怎么使用 Orca 的编排的
开工只写两个任务。
第一个是探路,我用一个叫 wayfinder 的 skill 来做:它不写代码,只去把这活的边界摸出来:相关代码在哪、有哪些没写进文档的约束、哪几处一碰就会牵动别的地方。它交回来的是一份「我原来不知道的东西」清单。地图和疆域的差,能提前摸到多少算多少。
第二个才是把第一块实现出来。两个都 dispatch 出去,各派一个 worker。然后等回执。worker 干完把 worker_done 和结果交回 orchestrator,它据此补任务、改依赖,或者回答 worker 的 ask;多数时候是 task-create 加两三个新任务,deps 指向刚做完的那个。只有它也裁不了的,才升到我这儿。
一轮一轮加,直到没有新任务可加。前面那条曲线上的 33 个创建时间点就是这么来的——它能证明 task graph 在持续增长,但光凭时间戳我没法证明每一次增长都对应一次人工判断。
这些都是orca 编排,不是我手动去编辑一张图,编排后会存都到本地的

所谓「graph 能改」,落到操作上就是这几组接口。也因为都走接口,每次改动都留在库里,后面那些数字才查得出来
## 二 · 跑得对:怎么防假成功

第三个工位交出一个歪的,后面的人照样认真抛光、包装、系蝴蝶结,末端账单越吐越长。
回到开头那个假前提。
「后端和 Runner 已就绪」这句话,在计划里读起来跟别的条件没什么两样。它不会自己报错,也没有哪个节点专门负责验它,只是被默认为真,然后底下挂了一串任务。
这就是假成功的来源:每一步都执行了,报告也是真的,但结论建立在一个没人验过的前提上。开头那次没有真的变成假成功,只是因为那道验收拦住了它。
graph 救不了这个。它只规定谁先谁后,不管前提是真是假。加 verifier 也未必够。@humzaakhalid 列的三种模式,adversarial、多视角、judge panel,判的都还是模型的输出。
他自己也说 graph 需要 anchor,举的例子是「真的到账的营收」「真的执行过的测试」。@IntuitMachine 说得更狠:a loop that runs on schedule while its measurements have detached from the world is theater with good attendance。
两边都点到了模型互评不等于接触现实,但都没给切换判据:哪些节点可以让模型复核,哪些必须由真实执行、真实到账、设备状态这类 anchor 放行。

先把前提验成事实,再看三类证据;没过就挡住下游。
我这边是怎么接的
顺序是吃过亏才排对的。
第一道先把前提验成事实:这个功能依赖的后端、Runner、配置,得有一条真跑过的证据说它在,而不是「计划里写了它在」。对不上就直接停,后面一项都不用跑。开头那个 013 就是这么补进来的。
过了这道再看三类证据:单元测试管数据和方法层,agent-device 管端上的真实行为,系统日志补时序和权限。日志这条别把话说满。没有那一行可能是真没发生,也可能是埋点挂了,所以它只有在日志链路本身没问题的前提下才算证据。
接起来只有一句话:这一步没过,依赖它的任务就不派发。
重点在「不派发」这三个字。我一开始只是让它把没过的项写进报告里,人看到再决定要不要管。结果是头几次我会去看,后来警告越积越多,看到红字的第一反应变成「先让它跑着,回头再说」。那条警告就等于没有了。
挡住下游不给你这个余地。要么把它修到过,要么明确改判据,没有第三条路。
看一个完整的例子,agent-device 的验收连挂三次:

03:32 那两次失败之间没有新任务;03:39 和 03:43 各插入一个开工时不存在的修正任务。
这条链路在 03:32 和 03:39 一共失败三次。前两次失败之间没有新增任务;后面的诊断先后触发了 P0 恢复实现和一个交互确认修正,都是开工时不存在的。中间 03:59 到 04:20 还有另一个模块的重实现和复验,04:41 才最终放行。
它能说明的是:失败催生了原计划外的修正任务。卡住下游的不是哪个 reviewer 说「看起来不太行」,是设备上真的没过。
还有一种失败:它漏做了,自己却不知道
大多数失败会自己撞出来:报错、超时、断言不过。但漏做一项而自己不知道,不会主动报错。
一个节点列了八项检查,它做了六项,漏了两项,然后交回一份「完成」。

最难发现的漏项,是执行者和验收者都没检查到的那一项。
它不是在骗你。在它那份「完成」里,那两件事根本没进过视野;而门禁也没有逐项核验,所以漏掉这个动作不留任何痕迹。
开头那个假前提就是这么漏掉的:「后端已就绪」躺在计划里,没有哪一项检查专门负责验它。
所以后来我把能单独验收的步骤拆成独立节点,漏一项就有一项亮红。任务切到十几分钟这个尺度,是我目前的经验值,不是从这一个案例推出来的阈值。
## 三 · 拐得回来:权在谁手里
有了 eval,你知道哪儿不对了。但光知道不够。下游要不要停、要不要加节点、谁拍板,才是第三件事。这一节先说权在谁手里,下一节说失败之后怎么用这个权。
这波讨论里讲得最细的几篇我都读了:Hamza Khalid 的 Graph Engineering、Carlos Perez 的 From Loop Engineering to Graph Engineering、Mike Piccolo 的 Loops, graphs, and the layer that matters、LangChain 的 3 Years of Graph Engineering with LangGraph——没有一篇说清楚运行中谁能改这张图。
有人谈 autonomy boundaries 和 approvals,但那说的是图里预先画好的审批节点,不是运行中谁有权增删任务、改依赖。
@IntuitMachine 那篇讲到了道理。他谈的是控制回路,不是 task graph,但判断可以直接搬:
> A loop drives its variable toward a reference — but nothing inside the loop can ask whether the reference is right. … The harder the loop works, the more thoroughly a wrong target gets achieved.
闭环没法质疑自己的目标,得有人从外面问一句「这个目标还对吗」。

这三道的共同点:放行权都不在干活的那个 agent 手里,判据也不是「它自己觉得可以」。
gate 是闸门的意思:条件不满足就卡在这,依赖它的任务一个都别想开始。图里那三道我这一个月都在跑,共同点是放行权都不在干活的那个 agent 手里。
第二道那次多说一句。提案方要在项目仓库里新建一份验收流程,orchestrator 没同意,让它去改公共的流程库。推荐的是 A,裁决下来是 A′,前后 6 分钟。提案方当时只提交了局部方案,裁决端拿到的是跨仓库的约束。这次改对了,不代表次次都会改对。
第三道那边也有东西可看。worker 干完活想提交,得先把三轮独立复核的结果摆出来,逐条列清楚才申请放行。大意是「规范轴通过、架构对抗通过、上一轮两个 P1 已修并被 follow-up 复审确认」,然后才是那句「请放行提交」。
我实际盯的只有一栏
这套东西有三层。worker 拿不准,问 orchestrator;orchestrator 也裁不了的,才会浮到我这儿来。

我平时只盯左边这一栏。它是空的,说明下面自己转得动;它亮了,才轮到我做决定。(卡片正文已模糊)
## 四 · 三者结合起来,才是一个反脆弱的系统
失败之后第一件事是让它先搞清楚为什么失败,而不是原地重跑。
一次失败里的信息量比一次成功大得多,它告诉你地图和疆域在哪一处对不上。这是你花钱买来的东西,重跑一遍就等于把它扔了。
见功夫的地方在后面:拿到这份反馈之后怎么改。

这是我设定的失败处理策略。本月没有真的触发到三轮上限。
诊断、修、再 verify 一次,用的是同一套机器证据。过了就走,没过再来一轮,三轮还不过就停下来上报。
这是我给验收链路设的熔断机制:诊断、修、再验,最多三轮。跟 Orca 自带的 dispatch 熔断不是一回事,那个数的是同一个任务连续派发失败三次。这个月我设的这道没真的触发过,所以下面讲的是流程设定,不是已经发生过的结果。
达到我设的三轮上限之后,不再自动重试,三轮的诊断结果一起交给 orchestrator,由它裁定下一步。多数时候是局部调整,实现有问题就回去改实现,判据定错了就改判据。
但有一种情况得整段推翻:前置任务本身就是错的。
它错了,后面挂在它下面的十几个任务全都建立在一个不成立的前提上。这时候改依赖没有意义,因为那些任务本身就不该存在。得把这一段整个作废,按新的理解重新起一张图。
这也是 superseded 要留记录的另一个原因:一次推翻可能带走一串任务,事后你得能看出来它们是为什么一起没的,否则过两周回来看,只会觉得这里莫名其妙断了一截。
前面 agent-device 连挂那三次就是例子。要是当时只做「再跑一遍」,它会挂第四次,因为问题不在那次执行,在它前面缺了一个恢复步骤。那三次挂掉换回来的,是「缺了什么」这个答案。
什么时候该改 graph,是被判断出来的
前面一直在说「graph 要能改」。但难的一直不是能不能改,是怎么知道该改了。
我是靠这几样东西凑出这个判断的:
- 某个前提没人验过,agent-device 一撞才发现 → 说明验收链路有洞,该在 graph 里补一道前置 gate
- 同一个 gate 连着失败 → 先别盲目重跑。诊断可能指向实现、环境、判据或前置步骤,只有证据指向上游才动 graph
- 诊断指向上游 → 说明依赖连错了,该重新接线
- spec 里的禁止项被触发 → 说明这条路以前摔过,不该再走
agent-device 的结果、gate 判据、禁止项命中,这些是机器证据。但要不要改 graph、改哪条边,仍然是 orchestrator 拿着这些证据做的裁定。
所以三者是这么结合的:graph 让活能一直跑下去,eval 告诉你哪儿不对,权限决定谁来改。eval 在这里的位置比看上去靠前,那个判断是它产生的。少了它,能改图只会让错改得更快。
这个环闭上之后,反脆弱才谈得上。013 那次换来的不止是一个补上的任务。从那以后,「依赖的东西得先验成事实,不能靠计划里写了它在」变成了我所有编排的第一道 gate,一条以后每单都生效的规则。
能证明的到此为止。这条规则确实沉淀下来了,但同类问题以后是不是真的变少了,我没有跨月的数据可以拿出来。
## 最后

身后那串是走过的路,手里这块是刚确认的,前面还是雾。
一个月下来,我拿得出手的结论就一条:graph 让 agent 跑得远,并行的时候还能快一些,但跑得远不等于跑得对。
要让一个长任务立得住,还得有 eval 告诉你哪儿不对,有明确的权限决定谁能改。三样凑齐,失败才有机会变成下一版图的输入。
这里最容易被看轻的是第二样。图会自己长、任务会自己补,看起来很像系统在自我修复。
但 agent-device 本身不是 eval。它跟 computer-use 是一类东西,让 agent 能碰到真实环境而已,它不知道什么算过、什么该拦。真正构成 eval 的是另外三样:代码架构本身得可验证(有稳定的锚点能断言,而不是靠截图猜)、任务约束(这一步允许做什么、禁止什么、拿什么当证据)、判据与阻塞范围(什么算过,没过拦哪些下游)。agent-device 只是把这些约束跑在真机上的手段。
这三样全是人一条条写出来的。这个月我花在这上面的工夫,比花在编排上的多。
边界也说一下。@PawelHuryn 主张这类流程最好做成带 evals 和 guardrails 的状态机。我不反对:验收、装包、取证这类稳定步骤,我这边也是写死的,一步不改。分歧只在本单还没定下来的任务和依赖,要不要留活口。
我推荐 Orca,一是编排本身够灵活,运行中能增删任务、改依赖、阻塞提问,裁决还会写回记录;二是 worktree 隔离,多个 worker 各自一份工作区,并行改代码。
引用:@trq212《A Field Guide to Fable: Finding Your Unknowns》7-07;@steipete 7-18;@IntuitMachine 7-18;@PawelHuryn 7-19;@humzaakhalid 7-21;@mfpiccolo 7-21;@ericosiu、@rohit4verse 7-22;@alex_frantic 7-24。
## 相关链接
- [Aiden](https://x.com/wohsj110)
- [@wohsj110](https://x.com/wohsj110)
- [7.9K](https://x.com/wohsj110/status/2081645581379031509/analytics)
- [@trq212 有个说法](https://x.com/trq212/status/2073100352921215386)
- [@steipete 发了一句调侃](https://x.com/steipete/status/2078277297791189132)
- [@ericosiu](https://x.com/ericosiu/status/2079991948106957131)
- [@rohit4verse](https://x.com/@rohit4verse)
- [@humzaakhalid](https://x.com/humzaakhalid/status/2079532755499839772)
- [@alex_frantic](https://x.com/alex_frantic/status/2080776965070496115)
- [@humzaakhalid](https://x.com/@humzaakhalid)
- [@IntuitMachine](https://x.com/IntuitMachine/status/2078419526354378975)
- [Hamza Khalid 的 Graph Engineering](https://x.com/humzaakhalid/status/2079532755499839772)
- [Carlos Perez 的 From Loop Engineering to Graph Engineering](https://x.com/IntuitMachine/status/2078419526354378975)
- [Mike Piccolo 的 Loops, graphs, and the layer that matters](https://x.com/mfpiccolo/article/2079609609275220165)
- [LangChain 的 3 Years of Graph Engineering with LangGraph](https://www.langchain.com/blog/3-years-of-graph-engineering-with-langgraph)
- [@IntuitMachine](https://x.com/IntuitMachine/status/2078419526354378975)
- [@PawelHuryn](https://x.com/PawelHuryn/status/2078755464754376719)
- [@trq212](https://x.com/trq212/status/2073100352921215386)
- [@steipete](https://x.com/steipete/status/2078277297791189132)
- [@IntuitMachine](https://x.com/IntuitMachine/status/2078419526354378975)
- [@PawelHuryn](https://x.com/PawelHuryn/status/2078755464754376719)
- [@humzaakhalid](https://x.com/humzaakhalid/status/2079532755499839772)
- [@mfpiccolo](https://x.com/mfpiccolo/article/2079609609275220165)
- [@ericosiu](https://x.com/ericosiu/status/2079991948106957131)
- [@rohit4verse](https://x.com/rohit4verse/status/2079945989511905549)
- [@alex_frantic](https://x.com/alex_frantic/status/2080776965070496115)
- [Upgrade to Premium](https://x.com/i/premium_sign_up)
- [3:39 PM · Jul 27, 2026](https://x.com/wohsj110/status/2081645581379031509)
- [7,968 Views](https://x.com/wohsj110/status/2081645581379031509/analytics)
- [View quotes](https://x.com/wohsj110/status/2081645581379031509/quotes)
---
*导出时间: 2026/7/28 12:51:02*