从 Loop 到 Graph

从 Loop 到 Graph 从 Loop 到 Graph EngineeringAI Agent 图工程的系统设计与实践方法很多 AI Agent 的讨论最后都会落到两个词Loop 和 Graph前者强调 让模型自己决定下一步后者强调 把任务拆成节点和边并规定它们怎样协作真正值得掌握的并不是判断哪一个更先进而是知道什么时候应该把决策权交给模型什么时候应该把流程写进系统Loop 适合处理路径未知、需要探索的工作而 Graph 适合处理结构已知、需要稳定执行的工作生产级 Agent 往往把二者组合起来用 Graph 约束全局流程用 Loop 完成其中不确定的子任务再用状态、工具协议、护栏和可观测性把整个系统收住几个容易混淆的概念Prompt 是行为说明而 Context 是当前事实Prompt Engineering 可以理解为给模型写行为说明例如规定角色、语气、输出格式和禁止事项它解决的是 模型应该怎样回答Context Engineering 解决的是 模型回答时应该看到什么它需要把用户输入、业务数据、检索结果、历史消息、工具结果和运行时约束组织成当前请求真正需要的上下文同一个模型即使拥有相同的 Prompt拿到不同 Context 后也会作出完全不同的判断因此Prompt 和 Context 不是二选一的替代关系Prompt 更像稳定的规则Context 更像随请求变化的事实两者共同构成一次模型调用的输入Skill 是可复用的程序性记忆如果某种做法会被反复使用就不应该每次都把完整步骤重新写进上下文可以把它整理成 Skill也就是一段可复用的程序性知识例如 如何处理退款请求如何检查一个 Pull Request如何为一份报告做事实核查Skill 适合表达稳定的操作顺序和判断规则它比一条临时提示更容易复用也更容易测试和版本化但它本身仍然是流程知识不等于一个能够自主探索的 AgentWorkflow、Agent 与 Graph 的关系官方资料通常把 Workflow 和 Agent 区分为两类系统Workflow 通过预先定义的代码路径组织模型与工具Agent 则由模型动态决定接下来调用什么工具、怎样推进任务Graph 是表达这种流程结构的一种工程形式它可以描述固定顺序也可以描述条件分支、并行执行、循环、动态派生的工作者和最终汇总所以 Graph 不必然意味着系统完全确定也不必然意味着系统已经具备自主性更准确的说法是Graph 提供结构Agent 提供决策一个 Graph 节点可以是普通函数、工具调用、一次 LLM 调用也可以是一个完整的 Agent LoopAI Agent 的演进不是替换而是增加控制层把 Prompt、Context、Skill、Loop 和 Graph 排成一条 工程阶梯 很有助于理解系统为什么越来越复杂但这不是所有项目都必须经历的标准升级路线每增加一层解决的是不同问题也增加了相应的状态管理、测试和运维成本层次主要解决的问题典型控制方式适合的场景Prompt如何让模型按要求表达和判断指令、角色、格式约束单次问答、内容生成Context模型需要哪些事实检索、记忆、运行时数据客服、销售、知识库问答Skill稳定步骤如何复用固定程序、操作规范代码审查、退款处理、报告模板Loop下一步做什么无法预先写死模型选择工具并检查结果调试、研究、开放式任务Graph已知流程如何稳定编排节点、边、路由、并行与汇总企业流程、批处理、可审计任务该表容易被误读成 Graph 取代 Loop实际情况更像是系统从 只会回答 逐渐拥有了 能调用工具、记住事实、重复执行和稳定编排 的不同控制面Loop让模型在工具调用中逐步探索Loop 的最小结构一个 Agent Loop 通常包含四个动作读取当前状态、让模型决定下一步、执行模型选中的工具、把工具结果写回状态并再次判断当模型认为任务已经完成或触发停止条件时循环才结束用户请求 | v 读取状态 - LLM 判断下一步 | ------------ | | 调工具 直接回答 | | - 写回状态 v | 结束 - 再次判断抽象成伪代码大致如下这里的重点不是某个框架 API而是 工具结果重新进入模型上下文 这一闭环# 最大执行轮次防止无限循环 MAX_STEPS 20 # 初始化会话状态载入用户输入 state initialize(user_input) # 多轮工具调用循环最多执行 MAX_STEPS 步 for step in range(MAX_STEPS): # 模型根据当前状态决定下一步动作调用工具 / 直接输出答案 decision model.decide(state, available_tools) # 分支1模型决定调用工具 if decision.kind tool_call: # 分发执行对应的工具传入参数并获取返回结果 result dispatch(decision.tool_name, decision.arguments) # 将工具执行结果追加到会话状态供下一轮模型决策使用 state state.add_tool_result(result) continue # 进入下一轮循环继续让模型决策 # 分支2模型决定给出最终回答终止流程并返回内容 if decision.kind final_answer: return decision.content # 分支3不支持的决策类型直接返回失败 return fail(unsupported decision) # 达到最大步骤上限仍未输出最终答案返回超时失败 return fail(step limit exceeded)Loop 适合什么任务Loop 的价值来自路径不确定性例如修复一个复杂 Bug 时模型可能先查看代码再运行测试再搜索依赖文档再检查部署配置下一步取决于上一步发现了什么如果把所有可能路径都提前写成 Graph分支数量会迅速膨胀而且很难覆盖未知情况开放式研究也是典型的 Loop 场景系统只知道目标是形成一份可信报告却不一定知道需要查哪些网页、补哪些证据、何时停止搜索因此可以让模型在工具预算内逐步探索Loop 的代价Loop 把决策权交给模型也把不确定性带进了系统它可能多调用工具、重复搜索、走错方向或在没有新信息时继续运行所以必须设置最大步数、总耗时、Token 预算、工具白名单、重试次数和人工审批边界工具还可能产生副作用例如发送邮件、修改数据库、执行命令或创建云资源这些操作不能只依赖模型 自觉谨慎而应该在工具层设置权限、参数校验、幂等键、审批和审计记录Graph把已知的系统形状写出来Graph 的四个基本组成一个可运行的 Agent Graph 至少需要明确四件事状态 State 保存什么、节点 Node 做什么、边 Edge 怎样流转、结束条件何时触发State 是跨节点传递的事实例如用户请求、分类结果、工具输出、错误信息和最终答案Node 是一个可执行单元可以是函数、工具、LLM、路由器或嵌套的 AgentEdge 描述节点之间的控制流可以是顺序、条件分支、回边或并行汇合Termination 定义何时结束例如到达END、通过校验、超过预算或进入人工处理Graph 的意义不是画出一张漂亮的流程图而是把 谁拥有状态、谁可以改变状态、失败在哪里收口 变成可以执行和测试的契约四种常见结构第一种是顺序链节点 A 的输出直接作为节点 B 的输入适合提取、转换、校验这类步骤清晰的任务第二种是路由先由规则或模型判断请求类型再把请求送到退款、物流、技术支持等专门分支如果路由结果来自模型最好要求结构化输出并对允许的分支做枚举校验第三种是并行化多个彼此独立的节点同时运行最后由汇总节点合并结果例如同时检查代码仓库、日历、记忆库和外部新闻再统一生成晨报第四种是编排者-工作者编排者先把任务拆成若干子任务工作者分别执行最后由汇总节点合成结果当子任务数量无法事先确定时可以使用动态派生的 Worker而不是预先写死每一个节点这些结构可以组合使用一个 Graph 可能先路由再并行执行多个分支其中某个分支内部又运行一个 Loop完成后再回到汇总节点为什么 Graph 能降低延迟和提高可控性在 Loop 中模型通常一轮只决定下一步工具调用往往是串行的在 Graph 中开发者可以提前声明彼此独立的工作让它们并行执行再等待全部结果汇合假设四个独立工具耗时分别为 1、2、3、8 秒串行执行的理想耗时接近 14 秒并行执行后主要等待最长的 8 秒再加上汇总时间这并不意味着所有任务都应该并行因为有依赖关系的节点仍然必须按顺序执行写共享状态时也需要明确合并规则Loop 与 Graph 如何协作可以把 Graph 看成宏观交通规则把 Loop 看成某一段路上的导航Graph 规定先做分类、再查数据、最后汇总Loop 则在 查数据 这个节点内部决定要搜索几次、调用哪些工具以及是否已经找到足够证据一次 每日工程晨报 可以设计成下面的结构START | ------------ 路由普通问答 / 晨报 Graph | ------------------------------------ | | | 查代码仓库 查日历/记忆 Web Research Loop | | | ------------------------------------ | 汇总与校验 | END这里的代码仓库查询、日历查询可以是确定性工具调用Web Research 可以是受预算约束的 Loop汇总节点不应该只把文本拼在一起还要检查每个分支是否返回、证据是否足够、结果之间是否矛盾这也解释了为什么 Graph Engineering 正在替代 Loop Engineering 是一个不准确的命题更合理的系统设计是让 Graph 负责稳定的外部形状让 Loop 负责局部探索把不确定性限制在可观察、可取消、可计费的边界内一个 Agent Harness 应该怎样承载这套系统Harness 可以理解为包住 Agent 运行时的一层系统外壳它不只是一个循环而是把入口、上下文、记忆、工作流、工具、观测、评估和发布连接起来一条典型请求链可以这样理解渠道 Gateway | v 身份与输入校验 | v 检索 GateSkill / 语义记忆 / 事件记忆 | v Graph Router | -- 固定 Workflow | -- Agent Loop | v 工具执行与权限控制 | v 结果校验、追踪、评估与反馈 | v 回复用户或进入人工处理这里的三类记忆需要区分Skill 属于程序性记忆描述 应该怎样做语义记忆保存相对稳定的事实和知识事件记忆保存带时间的历史经历和交互记录把三者都简单称为 记忆 会导致检索策略、更新策略和隐私边界混在一起Harness 的价值在于把运行控制从某个模型调用中抽离出来入口可以来自网页、命令行或消息渠道Graph 可以按版本发布工具可以统一鉴权所有节点可以产生追踪记录模型升级后也可以通过回放和评估比较新旧结果MCP 应该放在什么位置MCP 是 Model Context Protocol它解决的是 AI 应用如何以统一方式连接外部能力和上下文官方架构采用 Host、Client、Server 的分层Host 负责协调应用与安全策略Client 维护与具体 Server 的会话Server 暴露工具、资源或提示等能力因此MCP 更像能力接入协议不是 Agent 的 大脑也不是 Graph 引擎一个 Loop 可以调用 MCP Server 提供的工具一个 Graph 节点也可以调用 MCP 工具但调用协议本身不会替应用决定任务目标、停止条件或业务流程把 MCP 工具接入 Agent 时至少要考虑四个问题工具描述是否足够准确、参数是否严格校验、权限是否按工具和资源隔离、工具失败是否会被安全地写回状态如果工具描述模糊模型就可能选错工具如果权限过宽错误路径就可能造成真实副作用从一个简单 Agent 逐步演化到 Graph先做一条可测的最小路径先让一次模型调用完成一个边界清楚的任务例如根据输入生成结构化分类不要一开始就加入多 Agent、长记忆和复杂路由因为问题一旦出现很难判断是模型、上下文、工具还是调度出了错识别两种不稳定性如果不稳定性来自 下一步需要根据发现继续探索保留 Loop如果不稳定性来自 同一个业务步骤反复执行却没有明确契约先补齐输入输出和错误处理再把它固化成 Graph 节点一个实用判断是同一条流程在大量真实请求中都呈现相似形状且企业需要可审计、可回放、可控时延那么它就值得 Graph 化如果任务本身没有稳定 SOP强行 Graph 化通常只是把未知问题藏进大量脆弱分支为每个节点写清状态契约每个节点都应该说明读取哪些字段、写入哪些字段、失败返回什么、是否允许重试、是否可以并行节点之间尽量传递结构化数据而不是只传递一大段自然语言from typing import TypedDict class GatherState(TypedDict): question: str repository_items: list[dict] calendar_items: list[dict] research_notes: list[dict] final_answer: str errors: list[dict]状态契约的直接收益是便于测试和追踪当最终答案有问题时可以定位到是research_notes缺少证据还是final_answer的汇总逻辑误读了上游结果显式画出并行、分支和回路不要让节点之间的关系只存在于 Prompt 中把可并行的节点、必须等待的依赖、失败后的重试、需要人工审批的操作和最终出口都写成图上的边或运行时策略把护栏放在系统边界护栏至少要覆盖输入、路由、工具参数、工具结果和最终输出常见措施包括结构化输出校验、工具白名单、权限检查、敏感数据过滤、预算限制、超时取消、重试退避、幂等控制和人工审批护栏不是只为防止模型说错话更重要的是防止模型在错误状态下持续行动或把一个可恢复的判断错误扩大成不可逆的外部副作用最后补齐观测和评估生产系统需要记录每次运行经过了哪些节点、调用了哪些工具、耗时和成本是多少、在哪个护栏处被拦截、最终是否需要人工接管对 Loop还应记录每一步为什么继续对 Graph还应记录实际走了哪条边只有把这些信息保存下来才能回答 模型变差了还是工具变慢了并行是否真的降低了延迟某个路由分支是否经常选错 这类工程问题常见误区与边界把 Loop 当成万能 Agent一个会反复调用工具的循环并不自动具备可靠规划、正确记忆或安全执行能力没有状态边界、工具权限和停止条件的 Loop 只是更容易失控的自动化脚本把 Graph 当成 更高级的 LoopGraph 的优势是结构化和可控不是自主性更强如果任务路径本来就未知Graph 可能迫使开发者提前猜测所有情况维护成本反而高于一个受约束的 Loop所有节点都交给 LLM 决定能用普通代码判断的条件就用普通代码判断能用数据库查询解决的事情就不要让模型自由搜索模型路由适合处理语义不确定性确定性规则适合处理权限、金额、状态转换和合规边界并行化只看总耗时并行会引入更多并发请求、限流、共享状态冲突和部分失败需要明确取消策略、结果合并器、超时分支和单个任务失败时的降级行为不能只把几个函数包进gather就认为完成了系统设计把框架抽象当成系统本身LangGraph、Agents SDK 或其他编排框架可以提供状态、持久化、流式输出、追踪和工具调用能力但它们不会替你决定业务状态、审批边界和失败语义使用框架时仍然要理解底层模型调用、工具分发和状态更新发生了什么最后的判断框架面对一个新需求可以按下面的问题做设计选择这项任务是否只有一次模型调用就能稳定完成如果是先不要引入 Loop 或 Graph下一步是否必须根据上一步的新发现决定如果是在预算和权限边界内使用 Loop业务流程是否重复出现且步骤大体稳定如果是把稳定部分固化为 Graph是否存在互不依赖的子任务如果是考虑并行节点并定义合并和部分失败策略是否需要模型做语义路由如果是让模型输出受约束的结构化结果并由代码校验分支是否有真实外部副作用如果有在工具层加入权限、审批、幂等和审计是否需要解释一次运行为什么得到这个结果如果需要优先设计状态快照、节点追踪和评估样本结语把决策权放在正确的位置Loop 和 Graph 的差别本质上是控制权和确定性的分配问题Loop 让模型根据实时信息发现下一步Graph 让工程师把已经知道的流程、依赖和边界固定下来好的 Agent 系统不会把所有事情都交给模型也不会把所有可能性都硬编码成流程图它会把稳定的部分做成可测试、可审计的 Graph把未知的部分限制在一个有预算、有工具权限、有停止条件的 Loop 中再用 Harness 负责记忆、协议、观测、评估和发布当你再次听到 Loop 还是 Graph 这样的争论时可以把问题换成更具体的几个问题哪一步是已知流程哪一步需要探索谁拥有状态谁可以改变外部世界失败应该在哪里停止这些问题回答清楚之后系统该用 Loop、Graph还是二者组合通常就不再神秘