从Loop Engineering 到 Graph Engineering:让Agent执行真正地走向一个系统性工程

发布时间:2026/7/30 18:38:39
从Loop Engineering 到 Graph Engineering:让Agent执行真正地走向一个系统性工程 如果把过去一段时间的 Agent 工程压缩成一条进化路线大概是这样Chat → Harness → Loop → Graph。最早我们解决的是 Chat怎么让模型听懂问题给出一个像样的回答。接着是 Harness给 Agent 配上工具、上下文、记忆、权限和检查机制。它不再只是聊天而是终于有了一张能干活的工作台。有了这套工作环境Loop 才真正成立Agent 可以观察结果、调用工具、调整动作再继续下一轮直到达到目标或者触发停止条件。但走到 Loop 之后一个新的问题也越来越明显。我们让 Agent 能持续工作、不断重试却仍然习惯把任务塞给同一个 Agent、同一个上下文、同一条执行链可你盯着屏幕等一会儿就会发现查不同文件、看不同数据源、从不同角度做检查明明互不依赖为什么非得一个接一个排队这就是 Agent 工程走向 Graph 的原因。Graph Engineering图工程不再只问“一个 Agent 能做什么”而是开始设计“很多份工作应该怎样连接”。谁先做谁可以同时开工哪一步必须等齐哪一步应该边做边往下流哪个结果要先被质疑哪个失败不能影响全局什么时候继续循环出现什么信号必须停。Chat 是让模型和人开始对话。Harness 是给 Agent 工具、资料和一张工作台。Loop 是让它在这张工作台上持续执行、检查和修正。到了 Graph我们终于开始组织一支队伍。重点Graph 不是 Agent 工程的终点但它是一个很重要的分水岭关注点从“个体能力”转向“系统协作”。以后模型、工具和节点还会不断变化但复杂工作大概率仍要回到节点、边、状态、条件和循环这些基本结构。01PARTAgent 工程为什么一定会走向 Graph01. 节点是一份工作边是流过去的数据一张任务图最基本的东西只有两个节点和边。节点是一份边界清楚的工作。一次agent()调用一个明确输入一个明确输出只负责一件事。边是依赖关系。A 的输出会被 B 读取A 和 B 之间才有一条边。这里最容易犯的错是把语言里的“然后”误当成依赖。“先总结这个文件然后告诉我今天天气。”看起来是两步但天气查询根本不会读取文件总结。它们只是被写在同一句话里并没有数据从前一步流向后一步。以后看到一个“然后”先问自己一句下一步真的会读取上一步的输出吗如果不会这两件事就是独立的可以同时开始。这是 Graph Engineering 最简单、也最有价值的判断。02. 线性脚本也是图只不过它只有一条路“先 A再 B再 C再 D”当然也是一张图。只是它没有分叉所有节点排成一条长链。能跑但慢也脆。C 一旦卡住D 永远开不了工A 已经产出的结果也堵在上游哪儿都去不了。Graph Engineering 的起点不是画出更复杂的图而是重新审视原来的那条直线。把每一条箭头都拿出来检查这里真的有数据在流动还是仅仅因为我打字时先写了 A、后写了 B多数长流程里总有几条箭头是假的。剪掉它们原来瘦长的一条线就会变宽几个互不依赖的节点同时开工最后再把结果交给真正需要全局信息的节点。比如审查一个项目的全部路由文件看看有没有漏掉鉴权。检查route/a.ts时并不需要先知道route/b.ts的结论。每个文件都可以交给一个独立 Agent 同时检查最后再统一整理风险。你需要的不是“让一个 Agent 更勤快”而是别让十份互不相干的工作挤在一条队伍里。03. 给每个节点一张写清楚的工作单任务能不能并行关键不在 Agent 数量而在每个节点的输入输出是否说得清。一个好节点应该像一张填好的工作单•输入从哪里来必须明确传入•输出包含哪些字段必须提前约定•这个节点只负责什么边界不能含糊。不能指望“大家都在同一个上下文里所以应该都懂”。共享上下文看似方便实际很容易让节点互相污染谁改了什么、谁依赖了什么最后没人说得清。Claude Code workflow 里可以用 JSON Schema 把节点的输出固定下来。子智能体必须按照这个结构返回格式不对工具层会要求它重试而不是把一大段自由文本丢给下游让下一个 Agent 自己猜。Schema 有点像快递单。发件人必须把标题、路径、影响等级填完整收件人拿到之后立刻知道里面是什么。格式不对当场退回重填不要等包裹流到最后才发现谁都打不开。// 输入明确、输出可校验而且只负责一件事。const ITEM type object additionalProperties false properties title type string url type string impact type string enumhigh medium low requiredtitle url impactconst await agentprompt label research:${source.key} schema ITEM agentType general-purpose能接进工作图的节点和只能把结果展示给人看的节点区别往往就在有没有清楚的契约。04. 边不是“谁排在谁后面”而是数据怎样交接边同样需要契约。它不是一句“B 在 A 后面运行”而是一份承诺A 会输出什么结构的数据B 会按照什么结构接收。按数据来理解边有两个直接好处。一方面你能一眼看出这条边是不是真的。没有数据跨过去就没有依赖。第二只要数据结构不变两端的节点都可以替换。今天 A 用 Claude明天换成一段本地脚本B 不需要跟着重写。实操中很多边只是普通 JavaScript把多组结果拍平、去重、过滤、排序。它们是确定性的计算不需要模型判断。// 如果“合并”只是拍平和去重普通代码就够了。constflatMap(item) findingsconstnew Mapmap(item) idvalues不少工作流会专门再叫一个 Agent 来“帮我合并结果”。如果合并只是flatMap()加一个Map就交给代码。Agent 应该用在需要判断的地方不要让它替水管接头收租。02PARTGraph 真正改变的是让工作同时发生前四步是在看清图。接下来才是把原来的一条队伍真正改造成一支可以同时开工的团队。05. 用parallel()把独立工作一起分发出去当你有 N 个互不依赖的节点比如 N 个数据源要查、N 个文件要审、N 条路由要检查不要让它们排队。Claude Code workflow 里的parallel()会一次性分发任务。每个函数拉起一个子智能体并发执行最后返回一组结果。phaseResearchconst await parallel SOURCESmap(source) () agentprompt label research:${source.key} phase Research schema ITEM_SCHEMA agentType general-purpose// 单个失败不会拖垮整批先把空结果滤掉。constfilterBoolean这里有两个很实用的细节。parallel()会等这一批任务结束后再返回所以后面的步骤可以拿到完整结果。某个子任务如果抛出异常不会把其他任务全部带倒失败项会变成null正常项仍然回来。并发数也不是无限的。超出机器处理能力的任务会排队但至少不会再由一个 Agent 串行处理所有内容。更重要的是分发发生在 JavaScript 编排层而不是把所有材料继续塞进主会话。九个子智能体各有自己的上下文干完只把结构化结果带回来。主会话不需要同时吞下九个数据源一张图因此可以承载更多子任务而不把一个上下文窗口撑爆。06. 只有真的需要看全局时才让大家集合工作分出去以后总有需要收结果的时候。这个集合点可以叫作 barrier可以把它理解成一个集合点。跨所有数据源去重、按照总体影响排序、判断结果总数是不是零、拿不同发现互相比较这些工作确实需要看全貌。但只是把列表拍平、过滤空值就别专门把所有人叫回来开会。普通代码当场做掉就行。// 边上的操作普通代码几乎不花模型 token。constflatMap(item) itemsphaseCurate// 这里才需要拿到完整集合跨来源去重并按影响排序。const await agent Dedupe and rank these by impact:\n${JSON.stringify(flat)} phase Curate schema CURATED_SCHEMA如果你的流程是parallel → 中间处理 → parallel而中间只做拍平、过滤没有任何跨任务比较那这个集合点大概率是多余的。每一批人都被迫等最慢的那个时间就是这样耗掉的。07. “拆任务 → 并行干活 → 汇总”是最常用的一张图把任务分发和结果汇总连起来就得到 Agent 工作流里最常见、也最耐用的一种结构一个节点拆任务一组节点并行执行一个节点综合结果。市场调研、依赖审计、代码评审、研究报告表面上完全不同本质上骨架往往都是这一套分发找广度 → 用代码整理结果 → 交给一个 Agent 做最终综合。这一步带来的变化不只是更快。以前你会问“怎样让 AI 再多做几步”现在你会问“工作应该在哪里拆开又应该在哪里汇合”前者是在加长队伍后者才是在设计系统。08. 让流程根据中间结果自己选路并不是每一张图都要提前画死。有时下一步走哪条路要看中途发现了什么。工单被分成不同类型后应该交给不同处理流程代码改动很小可以快速检查改动范围很大就需要拉起完整审计。这种节点叫 router也就是路由节点。分类判断可以由 Agent 完成真正选路则交给if或switch。模型负责判断代码负责执行规则。const await agent Classify this diffs risk:\n${diff} schema type object properties severity enumlow high requiredseverityconst high await parallelFILESmap(file) () agentAudit ${file} await agentQuick review of ${diff}这种组合很重要判断可以交给模型边界必须留在代码里。你能用到 Claude 的判断力又不会碰上“AI 今天心血来潮自己跳过了安全审计”。想跳过哪一步必须明确写进图里代码里没写它就不能悄悄绕过去。03PARTGraph 真正难的不是并行而是边界把十个 Agent 同时拉起来并不难。难的是它们犯错时系统会不会更快地把错误放大它们互相等待时会不会把并行重新跑成串行它们不断探索时会不会永远停不下来。所以Graph Engineering 真正拉开差距的部分不是“同时开了多少个 Agent”而是下面四条边界。09. 在结果继续往下流之前先找人挑刺图的价值不只是可以同时塞进更多 Agent。更重要的是你可以在数据从 A 流向 B 的途中插入一个验证节点。它的任务不是赞同前面的结果而是尽力证明它有问题。扛住了结果才继续往下走没扛住就别让它进入最终答案。有三种常用做法对抗验证找人专门挑刺对每条发现派出几个相互独立的“怀疑者”要求它们尝试推翻结论。只有多数检查都没找到致命问题这条发现才留下。多角度检查不要让三个 Agent 用同一种方式查三遍。分别从正确性、安全性、能不能复现等角度检查。很多问题不是检查次数不够而是看问题的角度太单一。评审团让多个节点从不同方向给出方案再让评审并行打分。最终以表现最好的方案为主同时吸收其他方案真正有价值的部分。补充说明验证节点不是让几个 Agent 互相客气地复述同一个结论。它必须有明确的反对目标、不同检查角度以及决定结果能否继续流动的规则。10. 把失败关在当前节点别让它传染整张图线性流程里一个节点失败往往意味着后面的步骤全部停下。图里更合理的做法是让失败尽量停在当前节点。parallel()已经提供了一层基础保护一个任务失败返回null其他八个正常结果仍然保留。后面的汇总节点也必须接受“不完整输入”这个现实不要默认十个人出发就一定十个人回来。另一种更隐蔽的失败是多个 Agent 同时写文件时互相踩脚。A 正在改一个文件B 也在改同一个文件。即使两个人各自做得都对最后合在一起也可能是一团乱。这时可以使用isolation: worktree。每个需要写文件的 Agent 在独立 Git worktree 里工作完成后再合并。但不要把 worktree 隔离当成所有节点的默认配置。它有创建和合并成本只适合那些真的会并行写文件的任务。安全带要系在会撞车的位置不必给每把椅子都装一套防滚架。11. 可以加循环但先写清楚它怎样停下来有些任务一开始根本不知道规模。你去找 bug发现一个问题后又牵出三个新线索顺着新线索继续查又出现新的文件和调用关系。这种任务需要一条返回前面节点的边也就是循环。循环不可怕停不下来的循环才可怕。在循环里要对所有已经见过的东西去重而不只是对“最后确认有效的结果”去重。否则一条已经被验证节点否决的发现下一轮又会被当成新东西找出来再否决、再发现一直循环。最后得到的不是一个会探索的系统而是一台花钱反复走同一条死胡同的机器。const new Set // 所有已经见过的发现const // 最后确认有效的结果let 0 // 连续没有新发现的轮数while 2 constawait parallel FINDERSmap(finder) () agentprompt schema BUGSfilterBooleanflatMap(result) bugs // 跟 seen 比不是跟 confirmed 比。 constfilter(bug) haskey iflength continue 0forEach(bug) addkey // 每条新发现分别从正确性、安全性、可复现性三个角度接受检查。 const await parallelmap(bug) () parallelcorrectness security repromap(lens) () agentJudge ${bug.desc} via ${lens} — real? schema VERDICTthen(votes) realfilterBooleanfilter(vote) reallength 2pushfilter(item) realmap(item) bug这段代码里最有价值的是退出条件和seen。任何自动循环在启动之前都应该先回答两个问题什么算新东西出现什么信号时必须停。12. 不同节点用不同档位的模型一张graph还会把另一个问题暴露得很清楚并不是每份工作都需要高档模型。抽取字段、做初步分类、检查固定格式这些任务边界明确而且重复。综合报告、裁决争议、判断某个发现是不是真的这些节点才承担真正的推理压力。如果所有节点都默认继承当前会话模型那么你开着 Opus连最简单的字段抽取也会按 Opus 的成本运行。更合理的做法是•重复、边界清楚的节点用更便宜的模型•需要综合和裁决的节点保留高档模型•普通去重和过滤直接交给代码。这样不用改变图的结构就能把预算花在真正需要判断力的地方。注意Graph Engineering 不是“Agent 越多越好”。如果每个节点都用最贵的模型每条边又请一个 Agent 来搬数据再漂亮的图也只是一台更复杂的烧钱机器。04PART从手动画图到让 Agent 自己选择结构前面 12 步解决了三个问题怎样看清依赖怎样释放并行怎样守住边界。最后两步开始回答一个更高级的问题一张图的形状是否也可以根据任务动态变化13.parallel()和pipeline()差别在于要不要等最慢的人图的形状不是画给人看的装饰它会直接决定运行时间。最常见的取舍是parallel()和pipeline()。parallel()会在阶段之间设置集合点。所有任务都到齐下一阶段才开始。这样做适合那些必须同时查看完整结果的工作但整批任务的速度会被最慢的那个拖住。pipeline()则让每个任务独立流过多个阶段。A 已经完成研究就可以马上进入验证B 还在研究也不会挡住 A。快的任务先结束不需要陪着慢的任务一起等。// 每个数据源独立流过“研究 → 验证”两个阶段。const await pipeline SOURCES (source) agentprompt schema ITEM_SCHEMA (items) agentVerify: ${JSON.stringify(items)} schema VERIFY_SCHEMA建议很直接默认优先考虑pipeline()。只有下一个阶段确实需要看到全部上游结果时才设置集合点。例如跨集合去重、根据结果总数提前结束或者要把“其他发现”放进同一个 prompt 里做比较。“这样代码看起来更整齐”“这两个阶段概念上应该分开”都不是让所有人等待的充分理由。分阶段和必须同步是两件不同的事。14. 有些工作无法提前画好就让 Claude 为这一次任务画图前面的图都默认由人来设计。但有些任务只有做起来以后才知道应该拆成多少块、需要走哪些分支。Dynamic workflows 允许你只描述目标由 Claude 生成本次任务的编排脚本拆任务、选择怎样分发、拉起一组子智能体、收集并综合结果。这不是拿一个固定模板硬套所有工作而是为当前任务生成一张合适的图。简单来说有三种进入方式在 prompt 里明确要求使用 workflow让 Claude 为当前任务生成编排脚本运行已经保存好的流程例如/deep-research在支持的模式下让 Claude 为较大的任务自动规划 workflow。一张图跑得不错可以把脚本保存到.claude/workflows/。它能被版本控制也能按名字重新执行。别人克隆仓库后也可以启动同一套流程。TEXT › Run a workflow to audit every route under src/routes/ for missing auth. Spawn one agent per route file, then verify each finding before reporting. ● Claude wrote an orchestration script · launching in background… /workflows — auth-audit · running ✓ Scope 1/1 ✓ Fan-out 18/18 one agent per route file ◯ Verify 11/18 3-vote skeptics per finding ○ Synthesize 0/1 waiting on verify session stays responsive — keep working while the fleet runs走到这一步Graph 又向前跨了一层。它不只是“人先画好一张图再让 Agent 去跑”而是 Agent 可以先理解任务再为这一次工作生成合适的结构。这也让边界变得更重要结构可以动态生成但权限、预算、验证规则和退出条件不能跟着一起漂移。六张可以立刻拿来练手的图路由安全扫描。每个路由文件交给一个子智能体检查是否缺少鉴权。发现问题后先经过验证再进入最终报告。一个上下文窗口装不下的广度可以分到多个节点里。带引用的深度研究报告。先把问题拆成几个搜索角度同时检索普通代码负责去重几名“怀疑者”分别给重要主张挑刺最后再综合成文。/deep-research的骨架就是这样。逐文件迁移代码。不同文件同时处理测试作为闸门。失败的任务回到前面重试再用挑刺式评审寻找一次修改里不容易看到的破损。根据 diff 大小选择审查力度。小改动快速检查大改动自动拉起正确性、安全性、性能三个角度的并行审计最后由评审节点综合。可以重复运行的生态扫描。同时检查 release、博客和讨论区等结果回来后按照影响排序生成摘要。脚本保存一次后面按名字重复运行。不知道规模的缺陷发现。并行寻找问题对所有见过的结果去重验证留下来的发现连续两轮没有新东西自动停止。如果你准备把手上的一个 Agent 流程改成 Graph先别急着写代码。把下面这张清单过一遍下一步真的会读取上一步的输出吗哪些任务互不依赖可以同时开始哪个节点必须看到全局结果才值得让所有人等待哪些工作只是去重、过滤和排序应该直接交给代码哪些结果必须先经过独立验证才能继续往下走并行写文件时是否需要 worktree 隔离循环里的“新东西”是什么出现什么信号必须停每个节点都需要高档模型吗即使工作图由 Agent 动态生成哪些权限和预算边界仍必须写死这九个问题基本就是一张 Agent Graph 的骨架。回到最开始那条“先 A、再 B、再 C”的直线你会发现真正的变化并不是多学了几个函数。你开始用一种不同的方式看工作哪些任务应该一起出发哪些结果必须等齐哪些发现需要先被质疑哪些失败应该被隔离哪个循环应该继续哪个节点到了这里必须停。写 Prompt是在告诉一个 Agent 做什么设计 Graph是在决定一套智能系统怎样协作。Agent 工程走到这一步拼的不再只是模型能力。它开始越来越像真正的工程有分工有接口有调度有检查也有不能越过的边界。Harness 给了 Agent 一张工作台Loop 让它能够持续工作Graph 才开始决定谁在什么时候开工结果要流向哪里整支队伍怎样不失控地完成任务。学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】