ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Agent、Loop、Graph:从单点智能到流程编排的三段递进

Agent、Loop、Graph:从单点智能到流程编排的三段递进 如果你最近在接触 Agent 开发大概率会在同一篇文档、同一个项目里同时看到三个词Agent、Loop、Graph。单看每一个单词都不难但放在一起就容易发懵——它们到底是一回事还是三个不同的层次实际写代码的时候是不是只要把大模型接口调通项目就算完成了一大半这篇文章想给你画一张“三段递进地图”Agent 是一个能完成任务的智能体单元Loop 是驱动这个单元持续运转的循环机制Graph 则是把多个单元、工具和判断逻辑组织成复杂系统的一套骨架。三者不是并列的三个工具而是从“单点智能”到“流程编排”的三次跃迁。先想清楚这三层再去看 LangGraph、AutoGen 或者自研框架会顺畅很多。我的核心判断是很多 Agent 应用做得不理想并不是模型能力不够而是把“Agent”这个概念想简单了。你写完一次模型调用只完成了第一段循环怎么设计、流程怎么编排、状态怎么流转才是决定项目能不能上生产的关键。下文会从概念、代码、选型和工程落地四个角度把这条递进路线完整展开。1. 为什么要把 Agent、Loop、Graph 放在一张图里理解先说一个很常见的现象新手刚接触 Agent 开发时往往以为写一个client.chat.completions.create()就是在开发 AI Agent。调通了很开心等到需要处理多步工具调用、条件分流、状态回传代码就开始失控到处是 if-else改一处崩三处。这不是个例。从工作流类工具到多智能体协作框架真正困难的从来不是“让模型回答一句话”而是“让模型在一个可控的流程里反复决策、调用工具、处理结果直到完成目标”。要做到这件事光有 Agent 概念是不够的还要有 Loop 和 Graph。用一个通俗的类比Agent 相当于一个“会干活的人”。Loop 相当于这个人的“工作节奏”做完一步看看结果再决定下一步。Graph 相当于“项目排期表”谁先做、谁后做、什么条件下走哪条路全部提前画清楚。把这三点拆开理解你就能回答一个常见面试题Agent 架构到底包含哪几层答案不是“调一个大模型”而是“智能体单元 循环控制 流程编排”。其中 Loop 解决的是 Agent 内部“是否要继续”的问题Graph 解决的是整个系统“下一步该去哪里”的问题。2. 第一段Agent——从模型调用到最小智能单元2.1 Agent 是什么Agent 在 AI 开发语境里通常指一个能够感知输入、做出决策、执行动作并基于结果继续调整的智能体。它不再是一次性的“输入 Prompt输出答案”而是一个具备目标导向能力的执行单元。一个最小 Agent 通常包含四部分大模型负责理解和决策。工具让 Agent 能查询天气、查询数据库、访问 API 等。记忆记录历史上下文保证多轮交互不“失忆”。执行逻辑把模型决策变成真实动作。很多项目之所以做不到这里是因为只有第一部分“大模型”没有后面三部分。没有工具Agent 只能“纸上谈兵”没有记忆Agent 无法处理多轮依赖没有执行逻辑模型输出再正确也无法落地。2.2 一次普通模型调用和一个 Agent 的区别普通模型调用是“一次性问答”用户提问模型返回文本。Agent 则需要把文本返回变成动作。模型说“我需要查询天气”Agent 就要真的去调用天气接口再把结果喂回给模型让模型生成最终回答。下面用一个最小示例演示最基础的 Agent。为了不让示例依赖具体大模型 SDK代码里用字典模拟模型返回真实项目中替换成你自己的大模型接口即可。# 文件minimal_agent_demo.py 演示一个最小 Agent接收用户指令返回大模型生成结果。 这里用字典模拟大模型返回避免引入外部依赖。 def call_llm(message: str) - str: # 真实项目中这里会调用大模型 API if 天气 in message: return 北京晴气温 5~15 摄氏度。 if 时间 in message: return 现在时间是 2025-06-10 14:30。 return 我没有足够的信息处理这个请求。 def run_agent(user_input: str) - str: response call_llm(user_input) return response if __name__ __main__: print(run_agent(北京今天天气怎么样))跑这个示例你只会得到一个字符串返回。它离真正的 Agent 还差关键一步模型说“我需要查天气”之后系统并不知道怎么去查。真正的 Agent 需要一个循环来承载“决策—执行—观察”的过程这就是下文要讲的 Loop。3. 第二段Loop——让 Agent 从一次问答变成可持续循环3.1 为什么 Agent 必须有循环Agent 的经典工作模式是 ReAct即 Reasoning Acting。思路很简单模型先思考当前问题。模型决定调用哪个工具。Agent 执行工具拿到结果。结果回传给模型模型再思考。如果认为可以回答就输出最终答案否则继续调用工具。这个“思考—行动—观察—再思考”的过程本质上就是一个循环。没有循环Agent 只能调用一次工具拿到结果就结束了无法完成“先查天气再根据天气给出穿衣建议”这样需要连续依赖的任务。3.2 循环必须回答四个问题设计 Loop 时第一步不是写代码而是想清楚四个问题什么时候开始循环每次循环做什么什么时候结束循环达到最大尝试次数怎么办第一个问题通常由用户输入触发。第二个问题是模型输出解析和工具执行。第三个问题是循环设计里最容易出错的如果模型一直不输出 Final Answer循环就会卡死。所以必须有兜底机制最大轮数、超时时间、异常退出。行业中开始出现“Loop Engineering”的说法意思是Agent 应用能不能稳定工作取决于你对循环的设计能力。工具调用的参数怎么生成、错误结果怎么回喂、模型反复失败时怎么降级这些都属于循环工程问题值得花时间设计而不是靠运气。# 文件react_loop_demo.py ReAct Loop 演示代码。 生产环境将 call_llm 换成真实大模型接口即可。 import re TOOLS { get_weather: lambda city: f{city}今天晴气温 5-15 摄氏度, get_time: lambda _: 当前时间 2025-06-10 14:30, } def call_llm(prompt: str) - str: # 模拟模型返回实际开发中替换为大模型调用 if 工具返回 in prompt: result prompt.split(工具返回)[-1].strip() return fThought: 已经拿到工具结果可以给出最终答案。\nFinal Answer: {result} if 天气 in prompt: return Thought: 用户想查天气需要调用天气工具。\nAction: get_weather\nAction Input: 北京 if 时间 in prompt: return Thought: 用户想查时间需要调用时间工具。\nAction: get_time\nAction Input: None return Final Answer: 抱歉我暂时无法处理这个请求。 def run_agent(query: str, max_steps: int 5) - str: next_query query for step in range(1, max_steps 1): prompt ( f用户请求{next_query}\n 请按下面格式输出\n Thought: 你的思考\n Action: 工具名\n Action Input: 工具入参\n 或者直接输出Final Answer: 最终答案 ) output call_llm(prompt) print(f[Step {step}] 模型输出\n{output}\n) if Final Answer: in output: return output.split(Final Answer:)[-1].strip() action_match re.search(rAction:\s*(\w), output) input_match re.search(rAction Input:\s*(.), output) if not action_match or not input_match: print([Warning] 模型输出不符合 ReAct 格式提前结束) return output tool_name action_match.group(1) tool_input input_match.group(1) if tool_name not in TOOLS: return f工具 {tool_name} 不存在循环终止 tool_result TOOLS[tool_name](tool_input) print(f[Step {step}] 工具 {tool_name} 返回{tool_result}\n) next_query f工具返回{tool_result} return 最大轮数已用尽循环强制结束。 if __name__ __main__: print( ReAct Loop 演示 ) answer run_agent(北京天气怎么样) print(f\n最终回答{answer})运行这个脚本你会看到模型先输出 Action工具执行后把结果回传模型再输出 Final Answer。这就是一个标准的最小 Loop。3.3 Loop 的常见边界设计Loop 不是越大越好。实际项目中一个 Loop 内能做的事情应该有限制不然模型很容易在复杂任务里“迷失方向”。常见的边界机制包括机制作用示例最大轮数防止死循环max_steps5超时时间防止工具卡死timeout30s意图置信度低置信度时跳出循环阈值 0.4人工介入暂停循环等待人工确认Human-in-the-Loop其中人工介入机制是很多框架重点支持的功能。它用于处理模型没有把握的操作系统先执行到某个节点暂停下来问人等确认后再继续。这个机制从产品层面看是“让人参与审核”从工程层面看就是“在 Loop 上挂一个可中断、可恢复的断点”。4. 第三段Graph——从循环到流程编排4.1 为什么还需要 GraphLoop 能解决单个 Agent 反复决策的问题但它有一个明显缺陷整个流程是嵌套在代码里的改动流程就要改代码。当业务变成“先做意图识别再决定走查询分支还是兜底分支然后把结果格式化返回”继续在单个循环里堆逻辑就会很痛苦。Graph 的价值在于把流程显式化。你可以把系统看成一幅图节点Node一个处理函数可以是大模型调用、工具调用、代码判断。边Edge两个节点之间的连接关系。状态State在节点之间传递的共享数据。路由Router决定某一步之后走哪条边。Graph 不排斥 Loop。恰恰相反Loop 可以成为 Graph 中的一个节点。比如“让某个子 Agent 内部循环 5 次直到拿到可靠结果”这件事在 Graph 里只是其中一个节点。这样设计系统的可维护性会高很多。4.2 一个不依赖框架的最小 Graph 演示为了让读者理解 Graph 的本质我写一个不依赖任何框架的简化实现。它的核心思想是节点 边 状态 路由函数驱动整张图执行。# 文件minimal_graph_demo.py 一个不依赖框架的最小图编排演示。 每个节点是一个函数边通过路由函数决定下一步节点。 真实项目推荐使用 LangGraph 等成熟框架。 from typing import Callable, Dict def node_intent(state: Dict) - Dict: state[intent] weather if 天气 in state[query] else unknown print(f[intent] 用户意图{state[intent]}) return state def node_tool_call(state: Dict) - Dict: state[tool_result] 北京今天晴气温 5-15 摄氏度 print(f[tool_call] 工具结果{state[tool_result]}) return state def node_fallback(state: Dict) - Dict: state[tool_result] 暂不支持该意图 print(f[fallback] 进入兜底回复) return state def node_answer(state: Dict) - Dict: state[result] f最终答复{state[tool_result]} print(f[answer] {state[result]}) return state def route_after_intent(state: Dict) - str: return tool_call if state[intent] weather else fallback nodes { intent: node_intent, tool_call: node_tool_call, fallback: node_fallback, answer: node_answer, } edges { intent: (route_after_intent, [tool_call, fallback]), tool_call: (lambda state: answer, [answer]), fallback: (lambda state: answer, [answer]), answer: (lambda state: None, []), } def run_graph(query: str) - Dict: state {query: query} current intent while current: node_fn nodes[current] state node_fn(state) router, targets edges[current] next_node router(state) if next_node and next_node not in targets: raise ValueError(f路由非法{current} - {next_node}) current next_node return state if __name__ __main__: final_state run_graph(北京天气) print(final_state[result])这段代码把“意图识别—工具调用—兜底—生成答案”画成了一张图。路由函数route_after_intent决定了意图是天气时走tool_call否则走fallback。和纯 Loop 相比这种写法的最大优势是流程结构一目了然改路由只改一张边表不需要动节点内部逻辑。4.3 从手写 Graph 到框架手写这套逻辑可以帮你理解原理但生产环境不推荐每个项目都自研。LangGraph 等成熟框架已经帮你处理好了状态管理、并发、持久化、人工断点、重试等底层细节。你在框架里要做的就是把业务节点和边描述清楚。框架里的“Human-in-the-Loop”机制本质上就是在图的某条边上加一个中断点框架会把当前状态持久化等人工确认后恢复执行。这和前文 Loop 里讲的中断恢复思想是相通的只是承载层级从“单个循环”上升到了“整张图”。5. 三段递进地图从单元、循环到拓扑现在可以把三张地图拼起来了。理解这三者的递进关系是读 Agent 源码和设计 Agent 系统的关键。5.1 Agent 是一个“细胞”细胞能独立完成基本功能但单个细胞能力有限。Agent 也是这样一个 Agent 可以调模型、调工具但它只能处理一件事。你想让它不跑偏需要给它清晰的指令、足够的工具以及它内部的执行逻辑。这一层的核心问题是“这个智能体能做什么”。5.2 Loop 是“循环系统”有了细胞还需要循环系统来维持持续运转。Loop 让 Agent 不只做一次决策而是围绕一个目标反复迭代思考、行动、观察、再思考。这一层的核心问题是“如何保证它稳定地沿着目标推进”。5.3 Graph 是“神经系统”多个细胞和器官需要被协调起来才能完成复杂任务。Graph 就是这套协调系统它规定哪些节点存在、节点之间怎么连接、什么条件下走哪条路、状态在节点间怎么传递。这一层的核心问题是“整个系统如何组织”。三段递进的本质是抽象层级的上升层级关注对象核心机制常见问题第一段 Agent单个智能体单元工具调用、记忆、指令单元能力是否够用第二段 Loop单元内部的循环控制ReAct、终止条件、重试循环是否能收敛第三段 Graph多单元和流程编排节点、边、状态、路由流程是否可控可观测6. 实际项目中的选型建议理解了三层递进接下来要回答一个更实际的问题我的项目到底需要哪一层这里给出比较明确的判断。6.1 什么时候只需要一个简单的 Agent如果任务是单轮问答或者只需要调一次工具比如“帮我查一下这段文本的情绪倾向”那不需要复杂 Loop 和 Graph。写一个简单的 Agent封装好模型调用和工具函数即可。过度设计反而会增加维护成本。6.2 什么时候需要引入 Loop当任务需要多步工具调用比如用户问“北京适合穿什么衣服”Agent 需要先查天气、再查空气质量、再综合回答时就必须有 Loop。不要试图在一个 Prompt 里让模型一次性完成所有事让模型在循环里逐步获得信息成功率会高很多。6.3 什么时候需要升级到 Graph当系统有多个功能分支、多个智能体协作、状态需要在多个节点间共享时建议升级到 Graph。典型场景包括售前客服先识别意图再判断是订单查询、退换货还是人工客服。数据分析助手先理解问题再决定调用哪个分析工具然后格式化结果。多智能体协作一个 Agent 负责拆解任务另一个 Agent 负责执行工具第三个 Agent 负责汇总。在这种情况下Graph 的价值不只是“画图好看”而是让状态变化有明确载体让每条执行路径可追踪、可回滚、可测试。6.4 对比总结方案优点缺点适用场景单 Agent 调用简单、成本低无法处理多步依赖单轮问答、一次工具调用Agent Loop能处理多步任务流程复杂时难维护需要反复调用工具的任务Agent Loop Graph流程清晰、可编排实现复杂度较高多分支、多智能体、生产级 Agent 系统7. 常见问题与排查思路在实践过程中下面这些问题出现的频率非常高。问题现象可能原因排查方式解决方案Agent 循环不结束模型一直输出 Action不输出 Final Answer添加日志打印每轮模型输出设置最大轮数在提示词中强调“如果结果已足够请直接输出 Final Answer”工具调用返回格式解析失败模型输出与约定格式不一致打印原始输出检查正则匹配结果使用结构化输出或 JSON Schema增加重试解析逻辑状态在不同节点间丢失没有统一的 State 数据结构检查每个节点的入参和返回值定义统一 State 字典使用框架内置状态管理Graph 路由走到了错误节点路由函数判断条件写错打印路由函数返回值和候选目标为每条边增加输入输出校验工具调用报错导致整个流程中断Loop 内未捕获工具异常检查工具函数异常处理在工具调用外层加 try-except把错误信息回传给模型多个用户同时使用状态互相污染State 被设置成了全局变量检查状态作用域每个任务创建独立 State 实例避免共享可变数据排查的顺序建议是先看原始模型输出再看工具返回值最后看状态变化。大多数问题都能通过“打印每一轮输入输出”快速定位。8. 工程实践建议与安全边界框架和代码只是起点真正决定一个 Agent 系统能否上生产的是下面这些工程细节。8.1 为 Loop 设置硬边界Loop 一定要有硬性终止条件不能只靠模型自觉。建议同时设置最大轮数、超时等待和失败降级路径。比如模型连续 3 次调用同一工具没有新信息时强制终止并返回中间结果。这既保证了用户体验也保护了你的 API 调用成本。8.2 状态管理要做到“任务内隔离”在多用户场景下各个任务的执行状态必须隔离。推荐为每个任务单独创建 State 对象不要在模块里使用全局可变字典。如果使用框架优先使用框架提供的持久化状态这样即使进程重启任务进度也不会丢失。8.3 日志要记录模型输入输出Agent 系统的调试难度远高于普通后端因为中间每一层都有模型参与结果不确定。建议至少记录用户原始输入。每一轮模型输出。工具调用名称、入参、返回值。路由判断结果。Loop 退出原因。这些记录不仅能帮你排查问题还能用来分析模型在不同场景下的失败模式。8.4 工具权限要遵循最小权限原则Agent 调用工具时权限应严格限定在业务需要的最小范围。涉及数据库、文件系统、线上操作的工具要加入白名单、环境校验并在执行前尽可能加入人工确认环节。别让模型直接拿到可以删除数据或修改生产环境的全量权限这是 Agent 开发中非常重要的一条安全底线。属于生产环境的变更操作必须在测试环境先行验证并准备回滚方案。8.5 记忆和上下文窗口要提前规划Loop 会让模型看到越来越多的中间结果上下文窗口很容易被打满。实际项目里应对策略包括截断早期记录、做摘要压缩、只保留关键工具结果。你需要在“信息完整性”和“上下文长度”之间做取舍不能无脑把所有结果都塞进去。8.6 不要把图设计得过于复杂Graph 能表达复杂流程但不代表流程越复杂越好。节点超过 20 个时排查成本和测试成本会快速上升。更稳妥的做法是让单一节点内部尽量简单复杂判断交给路由函数同时在每个入口和出口设置断言保证状态结构符合预期。9. 总结与后续学习方向把 Agent、Loop、Graph 放在一张“三段递进地图”里可以发现一个清晰规律Agent 定义了智能体的能力边界Loop 解决了智能体内部的反复迭代Graph 解决了整个系统的状态与流程编排。理解这三层之后你再看各类 Agent 框架很可能会有一种“原来是这么设计”的通透感。后续的实践路径建议从这三步走先用最简单的 Loop 代码跑通一个带工具调用的 Agent感受“模型输出解析—工具执行—结果回传”这条链路。再给同一个任务加一个条件路由把它改造成一张最小 Graph。最后挑一个真实业务场景尝试用成熟框架把多分支流程落地并加上日志、超时、人工断点和权限控制。这三步恰好就是这张三段递进地图的落地版。做 AI Agent 开发重要的不是背概念而是亲手把循环跑通把图建出来再把边界卡住。如果这篇文章能帮你少走一点弯路建议收藏备用也欢迎在评论区留下你在 Agent 开发中遇到的具体问题一起讨论解决思路。
返回列表