ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Agent、Loop、Graph:智能体开发的三段进阶路线

2026/8/26 20:54:50 拓冰建站 浏览量
Agent、Loop、Graph:智能体开发的三段进阶路线 最近后台收到不少同学留言问题非常一致“我已经会调大模型 API 了为什么还是写不出 Agent”这个困惑我太理解了。很多人的 Agent 开发之路是从“把 Prompt 塞进模型”开始的。输入一段话返回一段结果好像任务完成了。但做着做着就会发现这只是在调用接口距离真正的 Agent 差得很远。真正把 Agent 开发串起来的其实是三个词Agent、Loop、Graph。如果你去翻各类 Agent 框架的源码去看面试题里的高频考点去观察那些“看起来很能打”的智能体项目你会发现它们兜兜转转都在围绕这三个概念展开。它们不是三个并列的技术点而是一条递进路径Agent是单次的智能单元负责“理解任务 调用能力”Loop让 Agent 从“回答一次”变成“循环思考、行动、观察”这是 ReAct 模式的核心Graph则把循环流程变成可控制、可分支、可人工介入的编排图。理解这条递进关系相当于拿到一张 Agent 开发的核心地图。这篇文章不打算堆概念而是把这三段拆开揉碎配合代码演进示例帮你把 Agent 开发的学习路线理清楚同时也讲明白一个很多人没意识到的问题框架里的 Loop 和 Graph到底是解决什么问题的。1. 为什么要把 Agent、Loop、Graph 放在一张地图里看先说一个现象。很多人学 Agent学得很散今天看 LangChain 文档明天研究 ReAct 论文后天跑到 LangGraph 里折腾图状态。每个概念单独看好像都懂但落到自己项目里就不知道怎么组合。问题出在哪出在没有先建立“三段递进”的整体框架。传统软件开发里我们习惯用函数、模块、流程来控制程序。但 Agent 不一样它的行为不是“写死的”而是由模型在运行时动态决策的。这个变化带来一个核心矛盾既要给模型足够的自主性又要让流程足够可控。第一段 Agent解决“模型如何拥有工具和目标”。 第二段 Loop解决“模型如何迭代地逼近一个复杂目标”。 第三段 Graph解决“多步骤、多分支、多 Agent 的流程如何被工程化地管理”。这三层不是替代关系而是叠加关系。你在实际项目里做多轮对话 Agent可能只需要 Loop做复杂的自动化工作流 Agent就必须上 Graph。把这张地图装进脑子里你看框架文档时的视角会完全不同你不再是在学“某个框架的某个 API”而是在理解“不同框架是如何实现这三段能力的”。2. 第一段Agent 是“有工具、有目标、有约束”的智能单元2.1 Agent 不等于大模型这是最容易被混淆的一点。大模型LLM本身只是一个“文本推理引擎”输入文本、输出文本。你问它“今天天气怎么样”它只能凭训练数据猜测无法获取实时的天气信息。而 Agent 的定位是一个能感知环境、做出决策、调用工具、完成目标的智能体系统。一个典型的 Agent至少包含四个部分组成作用类比模型LLM负责推理、决策、生成大脑工具Tools负责执行具体动作如搜索、计算、写文件手脚记忆Memory保存上下文和中间结果工作记忆指令与约束Instructions定义目标、边界、输出格式任务书很多初学者把“调大模型”当成“写 Agent”其实差的就是后面这三块。没有工具Agent 只能“说”不能“做”没有记忆Agent 无法处理多轮上下文没有约束Agent 的输出可能完全偏离业务场景。2.2 最小 Agent 的代码形态下面是一个非常简化的 Agent 调用示意重点是让你看到“Agent”和“直接调接口”的区别# 文件simple_agent_demo.py from typing import List, Dict from datetime import datetime # 工具清单Agent 可以调用的能力 TOOLS { get_current_time: datetime.now().strftime, calculate: lambda expr: eval(expr) # 仅演示实际项目不要用 eval } def call_llm(messages: List[Dict[str, str]]) - str: 这里只是占位函数。 真实项目中会替换为具体的大模型 API 调用并传入模型名称、温度等参数。 # 简化逻辑如果消息里出现“几点了”就返回一个时间工具调用指令 if 几点了 in messages[-1][content]: return ACTION: get_current_time return ANSWER: 我无法直接回答需要工具协助。 def run_simple_agent(user_input: str) - str: messages [{role: user, content: user_input}] response call_llm(messages) if response.startswith(ACTION:): tool_name response.split(:, 1)[1].strip() tool_fn TOOLS[tool_name] result tool_fn() return f工具执行结果{result} return response if __name__ __main__: print(run_simple_agent(现在几点了))这个例子不是完整生产代码但它展示了 Agent 的基本骨架模型负责判断需要什么操作程序负责执行工具并返回结果。这也就是 Agent 开发的第一层认知你写的不是一段“模型调用代码”而是一个“能让模型调用能力”的系统。从这一层开始你的程序才从“聊天机器人”往“智能体”迈进。2.3 第一段的局限单次 Agent 有一个明显问题它只执行一轮“判断-执行”。如果任务是“帮我调研一下某领域的近期动态然后写一份总结报告”单次 Agent 根本做不完它需要先搜索资料、再阅读、再总结、再校验。每一步的结果都是下一步的输入必须多轮迭代才能完成。这就是第二段 Loop 要解决的问题。3. 第二段Agent Loop 让“单次回答”进化为“多步推理”3.1 从 ReAct 说起如果你看过 Agent 相关的论文或框架文档一定遇到过 ReAct 这个词。它的核心思想是让模型在“推理Reasoning”和“行动Acting”之间交替进行。具体来说就是让模型每轮输出两种内容Thought当前这一步的思考比如“我需要查询天气 API 来获取北京今天的天气”。Action要调用的工具和传入参数比如get_weather(city北京)。模型输出 Action 之后程序执行工具把结果作为 Observation观察结果返回给模型。模型看到结果后继续思考再决定是继续调用工具还是输出最终答案。这个“思考 - 行动 - 观察 - 再思考”的循环就是 Agent Loop。3.2 Agent Loop 的三个关键设计Loop 看起来简单真正写起来有三个容易出问题的点第一最大步数限制。没有限制的循环是灾难。模型一旦陷入逻辑混乱可能无限调用工具既耗费 token 又卡死流程。生产环境里通常设置max_steps5~10超过步数就强制结束并告警。第二停止条件。循环什么时候结束要么模型明确输出最终答案要么达到最大步数要么触发用户中断即 human-in-loop 的一种形式。第三工具结果回填。工具执行结果必须转换为模型能理解的消息格式并放回上下文。否则模型看不到结果下一步决策就是盲猜。3.3 一个简化版 Agent Loop下面代码演示一个最小可用的 Agent Loop。它不依赖某个具体框架只用一个循环模拟“思考-行动-观察”的流程# 文件agent_loop_demo.py from typing import List, Dict TOOLS { search: lambda query: f关于{query}的模拟搜索结果, calculate: lambda expr: str(eval(expr)), } MAX_STEPS 5 def call_llm_with_loop(messages: List[Dict[str, str]]) - str: 真实项目里这里会调用大模型 API。 本示例用规则模拟模型输出只为展示循环结构。 last messages[-1][content] # 假设模型收到用户任务后先思考再调用搜索工具 if 调研 in last and ACTION not in last: return Thought: 我需要先搜索相关信息。\nACTION: search(Agent开发) # 收到搜索结果后模型决定计算一个指标 if 搜索结果 in last: return Thought: 我看到部分信息还需要估算文档数量。\nACTION: calculate(128*3) return Thought: 信息已经足够。\nANSWER: 已完成调研。 def parse_response(response: str) - dict: if ACTION: in response: action_content response.split(ACTION:, 1)[1].strip() tool_name action_content.split((, 1)[0].strip() tool_arg action_content.split((, 1)[1].rstrip()) return {type: action, tool: tool_name, arg: tool_arg} if ANSWER: in response: return {type: answer, content: response.split(ANSWER:, 1)[1].strip()} return {type: unknown} def run_agent_loop(task: str) - str: messages [{role: user, content: task}] for step in range(1, MAX_STEPS 1): print(f--- 第 {step} 轮 ---) response call_llm_with_loop(messages) print(f模型输出{response}) parsed parse_response(response) if parsed[type] answer: return parsed[content] if parsed[type] action: tool TOOLS[parsed[tool]] observation tool(parsed[arg]) print(f工具执行{parsed[tool]}({parsed[arg]}) - {observation}) messages.append({role: assistant, content: response}) messages.append({role: tool, content: observation}) else: raise RuntimeError(f模型输出格式无法解析{response}) raise TimeoutError(f超过最大步数 {MAX_STEPS}循环强制终止。) if __name__ __main__: result run_agent_loop(帮我调研 Agent 开发并估算现状) print(f\n最终结果{result})这段代码把 Loop 的骨架完整呈现出来了。你在任何 Agent 框架里看到的AgentExecutor、AgentRunner、ReactAgent底层本质都是这个循环只是把“模型输出解析”“工具注册”“记忆管理”这些部分做成了更健壮的组件。3.4 Loop 的局限Loop 虽然解决了“多步迭代”问题但它仍然是一条“默认直线”模型循环执行直到输出答案。如果流程里需要明确的分支判断比如“搜索结果质量低就走人工流程质量高就直接出报告”Loop 就力不从心了。再举几个实际场景某个环节需要人工审批模型跑完一个分支后必须停下来等人确认两个子任务之间没有先后关系可以并行执行一个主流程里嵌套多个不同的子 Agent每个子 Agent 有自己的工具集线上出问题后开发人员想知道“当时 Agent 为什么走了这一步”Loop 的线性日志很难回答。所有这些都指向第三段Graph。4. 第三段Graph 把“自由循环”变成“可控编排”4.1 Graph 解决什么问题Graph 的本质是把 Agent 的执行流程建模成一张有向图。图里有节点Node、边Edge和共享状态State。节点是具体的执行单元比如“调用模型”“执行工具”“人工审批”边定义了节点之间的流转关系比如“判断通过后进入下一步”状态则是整个流程共享的数据相当于一条流水线上的公共传送带。为什么要把 Loop 升级成 Graph因为真实业务的流程从来不是一马平川的直线它需要条件分支根据某一步的结果决定走 A 路还是 B 路。并行执行多个独立节点同时执行提高效率。人工介入在关键节点处暂停等待人工确认后再继续即 human-in-loop。细粒度控制可以指定从任意节点重跑而不是只能从头开始。可观测性每一步的状态变更都能被记录方便排查问题。4.2 用图的思想重新理解 Agent 编排这里要区分一个概念Graph 不只是“画流程图”它更是一种状态管理机制。一个简单的 Agent 流程用 Loop 写是这样用户输入 - [模型推理] - [执行工具] - (结果满意吗?) - 是: 输出答案 - 否: 回到模型推理用 Graph 写则会拆成更明确的节点和边。比如节点职责输入输出run_review调用模型审校文本原始文本审校建议call_tool调用外部检查工具审校建议工具检查报告human_check人工复核建议报告是否通过finalize生成最终结果通过后的内容输出这些节点之间的流转不再靠“模型自由发挥”而是由代码明确定义。这样做的最大好处是关键路径可控异常节点可重试业务规则可沉淀。LangGraph 这类框架的设计思路也是围绕这种“状态图”展开的。很多开发者在里面配 human-in-loop 时发现本质上就是给某个节点配置一个“暂停并等待外部输入”的机制。4.3 什么时候用 Loop什么时候用 Graph有同学会问那我以后是不是都该用 Graph不是。这里的判断依据是流程复杂度。场景推荐方案原因单轮问答、单工具调用单次 Agent简单直接成本最低多步推理、多轮工具调用Agent Loop有循环能力满足大多数场景多分支、多 Agent、人工审批、并行任务Graph 编排流程可控、状态可管理、团队可协作记住一个原则能用简单方案解决就不要一开始上复杂编排。上来就写 Graph 的人往往会先被自己的“流程设计”绕晕。5. Agent、Loop、Graph 对比与选型判断把三段放在一起看会更加清晰维度AgentAgent LoopGraph 编排核心问题让模型拥有工具和目标让模型多步迭代接近目标让多步流程可控可管理执行方式单次判断-执行循环直到满足停止条件节点流转可分支并行状态管理无状态或简单记忆会话消息队列显式共享状态分支能力无弱依赖模型自由输出强规则可配人工介入不支持较弱需额外实现原生支持 human-in-loop调试难度低中靠日志回溯中高但状态可复现适用规模个人工具、小脚本中型的多步任务复杂业务流、多 Agent 协同这段对比也解释了为什么面试官喜欢问“Agent 和 Agent Loop 有什么区别”“Graph 编排解决了什么问题”。因为这三个概念确实构成了 Agent 开发的一条完整主干。理解这条主干你再看任何 Agent 框架都不会有“眼花缭乱”的感觉。6. 从单次到 Loop 再到 Graph 的代码演进只看概念不够我们用一个具体场景演示三段递进做一个技术文章审校小工具判断一段技术文档是否存在术语错误并给出建议。6.1 第一版单次 Agent# 文件review_agent_single.py def call_llm(prompt: str) - str: 占位函数实际项目中替换为具体模型调用。 return 文档没有明显术语问题可以发布。 def review_with_single_agent(doc: str) - str: prompt f 你是一名资深技术编辑。请审校下面的技术文档 {doc} 只返回审校结论。 return call_llm(prompt) if __name__ __main__: doc 本文介绍 Agent Loop 与 Graph 的用法。 print(review_with_single_agent(doc))这一版的问题只要文档稍微复杂一点比如术语检查需要调用外部术语库、字数统计需要调用工具单次 Agent 就做不到了。6.2 第二版Agent Loop# 文件review_agent_loop.py from typing import List, Dict MAX_STEPS 4 def call_llm(messages: List[Dict[str, str]]) - str: 占位函数。真实场景中返回模型的文本输出。 last_user messages[-1][content] if 术语 in last_user and ACTION: not in last_user: return Thought: 需要调用术语检查工具。\nACTION: check_terms if tool_result in last_user: return Thought: 检查完毕没有致命问题。\nANSWER: 审校完成术语可用。 return Thought: 当前信息足够。\nANSWER: 审校完成。 def check_terms() - str: # 模拟外部术语表检查 return tool_result: 发现 1 个疑似术语问题建议人工确认。 def execute_tool(action: str) - str: if action.strip() check_terms: return check_terms() return tool_result: 工具不存在。 def review_agent_loop(task: str) - str: messages [{role: user, content: task}] for step in range(MAX_STEPS): response call_llm(messages) if ANSWER: in response: return response.split(ANSWER:, 1)[1].strip() if ACTION: in response: action response.split(ACTION:, 1)[1].strip() observation execute_tool(action) messages.append({role: assistant, content: response}) messages.append({role: tool, content: observation}) return 达到最大步数流程终止。 if __name__ __main__: task 请审校文档中是否还有未处理的术语问题。 print(review_agent_loop(task))这一版已经具备“模型自主判断是否需要调用工具”的能力。但流程里缺少一个关键角色人工复核。文档上线前任何术语问题都应该由人工最终确认不能只靠模型判断。6.3 第三版Graph 编排含人工复核节点下面用极简方式模拟一个 Graph 编排器。这里故意不引入任何第三方框架而是手写一个最小状态图让你看清节点、边、状态三个要素。# 文件review_agent_graph.py from typing import Dict, Callable # 全局状态相当于 Graph 中的 State state { doc: , review_result: , tool_result: , human_approved: False, final_output: , } def node_review(context: dict) - str: 节点1模型审校 context[review_result] 发现 1 个疑似术语问题。 return need_tool # 返回边的名称 def node_tool_check(context: dict) - str: 节点2工具检查 context[tool_result] 术语库确认建议将 Agent Loop 改为 Agent 循环。 return need_human def node_human_check(context: dict) - str: 节点3人工复核human-in-loop print(f请人工确认以下建议{context[tool_result]}) # 实际项目中这里会等待审批接口回调 context[human_approved] True return approved def node_finalize(context: dict) - str: 节点4生成最终结果 if context[human_approved]: context[final_output] 审校通过已采纳人工确认结果。 return end # 节点注册表 NODES: Dict[str, Callable[[dict], str]] { review: node_review, tool_check: node_tool_check, human_check: node_human_check, finalize: node_finalize, } # 边的路由表当前节点 - 返回值 - 下一节点 ROUTES { review: {need_tool: tool_check}, tool_check: {need_human: human_check}, human_check: {approved: finalize}, finalize: {end: None}, } def run_graph(start_node: str) - str: current start_node while current is not None: print(f- 执行节点{current}) node_fn NODES[current] next_edge node_fn(state) next_node ROUTES[current].get(next_edge) if next_node is None: break current next_node return state[final_output] if __name__ __main__: state[doc] 本文介绍 Agent Loop 与 Graph 的用法。 result run_graph(review) print(f\n最终输出{result})这段代码虽然简单但它把 Graph 编排的三个核心抽象都体现出来了节点NODES字典中的每个函数。边与路由ROUTES定义了“从哪个节点出来下一站去哪”。共享状态state字典在所有节点间传递和修改。对比上一版 Loop你会发现 Graph 的优点非常直观每个人工复核节点可以被单独重跑不需要重跑整个流程。如果某个节点失败可以只看这个节点的输入输出定位问题。流程的路由规则是显式写在代码里的不依赖模型自由发挥。6.4 如何运行验证三个代码文件都是独立的 Python 脚本可以用下面的命令依次运行python review_agent_single.py python review_agent_loop.py python review_agent_graph.py只要本机安装了 Python 3.8 以上版本无需安装第三方库直接运行即可。输出结果应当依次展示“单次审校结论”、“循环审校过程”和“图编排的执行路径”。如果运行时出现中文乱码检查终端编码是否为 UTF-8export PYTHONIOENCODINGutf-8如果是在 Windows 上运行可以在脚本开头加入# -*- coding: utf-8 -*- import sys sys.stdout.reconfigure(encodingutf-8)7. 常见误区与问题排查7.1 常见认知误区误区一Agent 就是大模型 API。只看 API 文档永远学不会 Agent因为 Agent 的关键在工具调用、循环控制、状态管理这些都在模型之外。误区二Loop 越多越好。不是。模型每循环一轮token 消耗和时间成本都会上升。很多任务的正确做法是先规划好最少需要的轮数。误区三Graph 一定比 Loop 高级。从能力上说是但从工程成本上说不是。Graph 的建模、调试和维护成本更高。一个简单的单工具任务用 Graph等于杀鸡用牛刀。误区四human-in-loop 就是让人在最后看一眼结果。真正的 human-in-loop 是在流程中间设置暂停点。比如“模型生成候选方案 - 人工选择方向 - 模型继续执行”人工参与的是决策而不是验收。7.2 代码与运行问题排查问题现象可能原因排查方式解决方案循环不停止token 消耗巨大缺少最大步数限制查看循环代码是否设置max_steps增加步数上限与超时中断模型不调用工具上下文缺少工具说明检查工具描述是否写入系统提示词在系统提示词中明确工具清单与调用格式工具调用格式解析失败模型输出了非预期格式打印原始模型输出对比解析逻辑增加格式校验与重试机制人工审批节点卡死等待人工回调没有超时机制检查是否设置了任务超时为人工节点设置超时和自动告警Graph 状态被污染多个任务共用了同一个全局状态检查状态对象作用域每个任务创建独立状态实例7.3 调试 Agent 流程的实用建议调试 Agent 不像调试普通函数不能只靠断点。建议从一开始就做好三件事打印完整消息链每一轮发给模型的 messages 都要能输出到日志。给每个节点加 trace_id线上一次执行会产生很多日志用统一 ID 把它们串起来。保留工具输入输出快照模型推理出错的根源往往是工具返回值不符合预期快照能帮快速定位。8. Agent 编排的工程化建议从最小 Demo 走向生产环境还需要补齐下面这些工程细节。8.1 安全性Agent 能调用工具意味着模型一旦被诱导可能执行危险操作。生产环境必须做到工具白名单机制不在白名单里的工具不可调用。高危操作删除文件、修改数据库、发送消息必须设置人工审批。对工具传入参数做校验不能直接透传模型输出。对 Agent 的运行过程做审计日志保留每一次工具调用记录。8.2 可观测性Agent 系统的调试比传统系统更难因为模型的行为具有随机性。建议在项目初期就引入步骤级日志每次模型推理、工具调用都记录耗时和 token 消耗。状态快照Graph 每个节点执行前后都保存一次状态。指标监控步数分布、工具失败率、人工审批通过率这几个指标最能反映流程健康度。8.3 错误处理与重试Agent 运行中的错误来源很多模型 API 超时、工具调用失败、输出格式解析失败。工程上要分层处理临时性错误网络抖动、限流采用指数退避重试。业务性错误工具返回业务异常让模型看到错误信息后自行调整方案重试一次。结构性错误多次重试仍然无法推进应该走人工兜底流程而不是无限循环。8.4 版本管理与回滚Agent 的流程是“代码 模型 工具”三者共同决定的。线上出了问题时可能是代码改坏了也可能是模型升级导致行为变化。建议流程定义Graph 结构纳入版本管理每次修改能 diff。模型版本和 Prompt 版本绑定方便复现问题。工具接口变更要先做兼容性测试避免 Agent 侧出现运行时错误。8.5 成本控制Agent 的 token 成本往往比预想高很多。一个看似简单的任务在 Loop 模式下可能调 5 次模型、消耗数千 token。成本控制可以从几个方向入手精简 Prompt把不必要的历史消息裁剪掉。在工具返回值较长时先让模型做摘要再放回上下文。对“是否继续循环”的判定设置明确的成本阈值比如超过 3 次工具调用后自动开启人工确认。9. 学习路线与最终建议如果你刚接触 Agent 开发建议按照本文的三段递进路径安排学习计划第一周理解 Agent 基本单元。不用学框架先自己写一个能调用两个工具的最小 Agent体会“模型决策 工具执行”的感觉。第二周吃透 Agent Loop。至少手写一次 ReAct 循环搞清楚消息链是如何增长的、停止条件如何设计、工具结果如何回填。这一步比刷一万行框架代码都重要。第三周接触 Graph 编排。把手写 Loop 改成简单 Graph加入一个条件分支和一个人工审批节点。你会发现Graph 带来的不是炫技而是可控性。第四周回到真实项目。带着“三段地图”去选型。简单的工具类应用用轻量框架就可以复杂的自动化流程再考虑 LangGraph 这类图编排框架。最后给一个很实际的建议不要一开始就追求“最强大的 Agent 框架”。先用最小代码跑通 Loop再逐步加入节点、状态、人工介入。每一步都验证稳定后再往后走。Agent 开发最大的坑不是某个 API 不会用而是流程不受控时你还不知道问题出在哪一层。把 Agent、Loop、Graph 这张地图记在心里遇到问题就能快速定位到底要调整“模型能力”“循环策略”还是“编排结构”这才是 Agent 工程化真正的分水岭。