AI Agent 执行闭环五节点:Hermes Loop 工程落地拆解 聊到 AIAgent 的落地很多人一开始都被“智能体”三个字带偏了以为只要把大模型 API 接进去再配一套提示词它就能像人一样把事情办完。真上手做过一轮就会发现问题根本不在于模型“聪不聪明”而在于整个执行过程是不是真的闭环了。我长期做 Agent 工程习惯把自己常用的这套执行链路叫Hermes Agent Loop——信使之神负责传递信息而一个 Agent 的有效执行恰恰就是靠一轮一轮的信息传递、反馈和修正来完成的。这篇文章就把这个执行流程彻底拆开讲清楚每一个环节的使命、容易炸的坑以及一套可以直接落到工程里的最小实现。这套内容适合正在做或者准备做 Agent 应用的人看尤其是那些已经被“任务跑到一半就卡死”“循环不收敛、反复执行同一个动作”“上下文越滚越长、最后丢掉了最初目标”折磨过的朋友。它不是某个商业化产品的使用说明书而是我把大量实战经验压缩之后的一份执行流程拆解。1. 拆解前先搞明白Hermes Agent Loop 到底是什么1.1 名字的来历与循环的五个节点Hermes 是希腊神话里的信使神负责把众神的旨意传递到人间再把凡间的反馈带回去。这个意象放在 Agent 上特别贴切一个智能体对外提供能力本质上就是在“接收需求—产生行动—观察结果—修正下一步”之间不断循环。我把它拆成五个必须存在的节点意图识别把用户说过的话转换成机器可执行的任务描述。任务规划把一个大目标拆成若干子任务并确定它们之间的依赖关系。工具调用执行规划好的动作比如查数据库、调 API、执行代码。结果评估判断这一轮动作的结果是否达标是否需要进行纠正。记忆更新把有用的信息写入短期或长期记忆并准备进入下一轮循环。这五步合在一起就是一次完整的 Loop。用生活里的场景类比你请一个外包助理替你办事你先说清需求意图识别助理拆解成“订机票、定酒店、做行程表”任务规划然后用电脑查航班、下订单工具调用检查订单是否成功结果评估把出行偏好记录下来下次直接用记忆更新。一个靠谱的助手就是把这些动作循环到任务完成。1.2 为什么 Agent 不能是一次性的“提问—回答”很多人在做 Agent 时犯的第一个错误是试图用一次大模型调用来解决所有问题。如果任务只是“给我的周报起个标题”那一次调用确实够了。但真实场景往往是“读取这个目录下的财务报表提取关键指标生成一份对比图表并按指定格式发送到工作群”。这类任务有几个共同特点需要访问外部数据、依赖工具的实时返回结果、过程中可能出现异常需要重试或换方案。你让模型一次性生成完整回复它只能靠“猜”。你让它在循环里一步步做它就能做到“看一眼真实结果再决定下一步”。所以 Hermes Loop 的本质是把决策与执行进行分离模型负责思考和判断工具负责真实地改变外部状态评估步骤负责检验结果是否符合预期。至于循环是把这三者缝合起来的胶水。1.3 循环的边界它必须有终止条件很多人一听到“循环”就觉得是无限转圈。真正的 Agent 循环必须有明确的边界否则轻则消耗大量 Token重则在生产环境里闯祸。我自己的项目里一般设四类终止条件优先级从高到低排列终止条件类型说明典型阈值任务完成标志评估节点判定目标已达成根据业务定义最大迭代次数防止死循环的硬边界1020 轮成本预算上限消耗超过阈值立即终止按 Token 金额计算用户中断信号人工介入强制停止任意时刻生效我早期有个项目没设置最大迭代次数结果一个报价计算任务在凌晨三点还在循环里反复尝试同一个报错接口直到云厂商账单把我叫醒。自那以后我的循环代码里第一行永远是终止条件检查而不是“调用模型”。2. 五个节点逐个拆核心细节与难点2.1 意图识别节点把用户的话转成“任务规格”意图识别不是简单地把用户输入拼接进 System Prompt。它要做的是把模糊的自然语言映射成包含目标、约束、可用工具、成功标准的结构化规格。举个例子用户说“帮我整理一下这个月的账看看有没有异常”合格的 Agent 应该先把它转换成类似这样的 JSON{ task: 月度账单异常检测, data_source: user_uploaded_bill.xlsx, constraints: [只分析本月数据, 不修改原文件], success_criteria: [输出异常项目列表, 每个异常附说明], allowed_tools: [load_file, query_database, plot_chart] }后面所有节点都依赖这份规格。如果这个环节做得粗糙规划节点就会瞎拆工具调用就会瞎调评估节点也会失去参照物。这个节点最容易犯的错有两个一是只提取了目标却没提取约束导致 Agent 用错了数据源二是没有明确成功标准最后任务做完了Agent 和用户对“完成”的理解不一致。2.2 规划节点拆解任务的粒度与依赖规划节点的输入是结构化任务规格输出是一个可执行的任务序列。它要回答三个问题总共要做什么、哪些事可以并行、哪些事必须等前一步结果出来才能继续。我常用的处理方式是让模型输出一个轻量级的任务图描述而不是长篇大论的计划书。比如“写一份季度总结并发到群聊”可以拆成这样1. 读取季度项目数据依赖数据文件存在 2. 生成总结正文依赖第 1 步完成 3. 生成图表附件依赖第 1 步完成可与第 2 步并行 4. 调用群聊机器人发送总结正文和图表依赖第 2、3 步完成这里有一个容易被忽略的问题规划不要做得过长。你让模型一次性规划 20 个子任务后续执行只要有一个步骤失败整个计划就作废了。更好的做法是只规划接下来 35 步执行完再继续规划。这样每一步都基于最新的事实而不是旧计划规划本身也稳定得多。2.3 工具调用节点Function Calling 的可靠性问题工具调用是 Hermes Loop 里最需要“防守”的环节因为模型生成的参数天然会有不稳定性。常见的故障包括数字参数被当成字符串、可选参数被漏掉、参数里有多余的大括号导致 JSON 解析失败、甚至调用了一个根本不存在的工具名。我自己做项目时给工具调用加了一层严格校验所有工具定义都使用 JSON Schema。比如一个发送群消息的工具长这样{ name: send_group_message, description: 向指定的群聊发送一条文本消息。, parameters: { type: object, properties: { group_id: {type: string, description: 群聊的唯一ID}, content: {type: string, description: 要发送的消息内容} }, required: [group_id, content] } }工具描述写得越精确模型选错工具的概率就越低。我见过很多团队把工具描述写成一句话模型一看几十个工具全长得差不多自然乱选。工具描述本身就是面向模型的产品文案值得花时间打磨。2.4 结果评估与记忆更新节点闭环的关键很多 Agent 项目跑起来像“无头苍蝇”是因为少了结果评估这一步。执行完一个动作就直接进入下一轮结果错了也照样往下走最后错误像滚雪球一样越滚越大。结果评估可以是规则判断比如检查返回状态码是否为 200、可以是用测试用例断言、也可以让模型当“裁判”来评价。生产环境我一般混合使用能用规则判断的绝不用模型判断规则覆盖不了的地方才用 LLM Judge。记忆更新则是把这一轮产生的信息压缩并存储。这里的核心不是“记录所有事”而是只记录对未来决策有用的信息。每次执行完一轮我保留的信息大概包括当前任务的原始目标、已完成动作的摘要、失败原因及更正建议、最新获得的外部数据。记忆窗口不宜无限扩大。我常用的做法是通过滑动窗口保留最近几轮完整信息更早的内容用摘要替代。这样才能保证无论循环进行到第几步最核心的“用户最初要什么”永远不会被挤出去。3. 实操过程把 Hermes Loop 落到产物工程里3.1 最小技术栈与选型思路先说明一点如果你刚开始做 Agent 流程研究不要急着上重型框架。我见过不少同学一上来就引入编排框架结果框架本身的学习成本比 Agent 逻辑还高。要做到“看懂每行代码在干什么”一开始完全可以用最朴素的方式实现。我的最小技术栈是Python 3.10、一个大模型 API 的访问封装、一组普通 Python 函数充当工具、以及一个你顺手就能写的日志模块。这套组合足够跑通整个 Hermes Loop还能让你清楚感知每一步发生了什么。等最小的循环稳定之后再考虑要不要上 LangChain、LlamaIndex 这类开源生态里的辅助工具。至于开源 AI Agent 平台怎么选我的原则是先用裸代码跑通自己的逻辑再去对照平台是否兼容你的循环设计。别反过来被平台的设计哲学绑架。3.2 一个最小循环的骨架代码下面是一个浓缩版的 Hermes Loop 骨架用伪 Python 写出来只有几十行但它包含了全部关键节点import json from typing import Any def call_llm(messages: list, tools: list) - dict: 调用大模型返回解析后的结构化响应。 # 实际项目中这里是调用模型 API 并解析结果 pass def exec_tool(tool_name: str, arguments: dict) - str: 在工具注册表里查找并执行指定的工具函数。 # 实际项目中这里是工具分发逻辑 return tool result def judge_step(result: str, success_criteria: list) - tuple[bool, str]: 根据任务成功标准判断本轮结果。 # 可组合规则判断和 LLM 判断 return False, need fix def summarize_history(history: list) - str: 对过长的历史记录做摘要压缩。 return compressed context def agent_loop(user_input: str, max_iterations: int 10) - Any: # 1. 意图识别 spec call_llm(messages[{role: user, content: user_input}]) history [] iteration 0 while iteration max_iterations: if iteration 0 and iteration % 3 0: history [summarize_history(history)] # 2. 规划基于当前状态生成下一步动作 plan call_llm(messageshistory [spec], toolsspec[allowed_tools]) # 3. 执行调用工具并获取真实结果 result exec_tool(plan[tool_name], plan[arguments]) # 4. 评估检验结果是否达标 done, feedback judge_step(result, spec[success_criteria]) # 5. 更新记忆保存本轮关键信息 history.append({step: iteration, plan: plan, result: result, feedback: feedback}) if done: return {status: completed, result: result} iteration 1 return {status: max_iterations_reached, result: None}这段代码刻意精简到只剩骨架真实项目里每个函数都会变成独立的模块。但有一点值得反复强调循环的每一轮都必须有可观测的输出你在第 20 轮还能复盘第 3 轮做了什么决定、为什么这么做这是 Agent 工程和普通脚本的本质区别。3.3 关键参数怎么设才不翻车模型参数的选择会直接改变循环的“性格”。我踩过不少坑后总结出几个比较稳妥的起点参数建议值原因temperature0.10.3执行型任务需要稳定输出不需要创造性发散top_p0.80.9配合 temperature 抑制低概率的胡说max_tokens尽量充裕但不浪费规划结果要完整输出太短会被截断max_iterations1020太少解决不了复杂问题太多容易失控记忆窗口长度最近 58 轮保留足够上下文又不会超过模型输入上限我早期的 Agent 项目为了“更有创造力”把 temperature 调到了 0.9结果它在工具选择上异常活跃同一个错误反复用不同方式犯一遍。做执行任务模型需要的不是发挥而是稳定。temperature 压低之后循环的收敛性好了一个数量级。3.4 让循环可观测日志、轨迹与还原Agent 跑起来之后最怕的是“黑盒”——你不知道它现在在做什么、下一轮打算做什么、为什么卡住。我的方案是全程输出结构化日志每个事件按节点类型打标记。一条典型的运行日志长这样2025-05-18 14:03:21 [PLAN] iteration2 toolquery_database args{sql: SELECT SUM(amount) FROM orders WHERE date 2025-05-01} 2025-05-18 14:03:22 [EXEC] toolquery_database statussuccess rows128 time_ms340 2025-05-18 14:03:22 [JUDGE] resultmatched success_criteriatotal_amount exist decisioncontinue 2025-05-18 14:03:25 [MEMORY] summary已获取5月订单总额下一步生成趋势图这套日志的价值不只是帮你排查问题还能让你把一次完整的执行轨迹保存下来之后可以像回放录像一样重新演算。我建议每个项目都在早期就把日志设计好不要等项目跑出问题再补因为补日志意味着要重跑一遍完整流程隐性成本很高。4. 真枪实战中踩过的坑常见问题与排查方法4.1 循环不收敛Agent 在原地打转最常见的故障就是 Agent 反复做同样的事每次都报同一个错但每次都提出一个和上一轮几乎一样的方案。根治的办法是在记忆里保存最近几轮的“动作指纹”一旦发现连续三轮动作雷同就强制切换策略或者直接终止。我在评估节点里加了一个检测函数把每轮的 (tool_name, arguments) 哈希后存进列表如果最近三次哈希值重复就返回一个强制反馈——内容大致是“你已经连续执行相同动作并失败请停止当前路线重新分析原因或请求用户帮助”。这一招几乎消灭了所有转圈问题。4.2 上下文被撑爆执行到一半忘了用户最初要什么循环轮次一多上下文里塞满了中间结果到了第 15 轮模型很可能已经忘了原始任务是什么。我见过一个极端案例Agent 原本要“找出上周流失的前十个客户”结果在第 20 轮开始生成“总结本周工作”的内容因为上下文里全是工具返回结果最初的指令早就被淹没了。解决办法有两个第一把用户最原始的目标锚点始终放在 System Prompt 的最前端并用格式固定下来不让它被滚动窗口挤出去第二每执行几轮就对历史做一次摘要压缩把零散的工具返回提炼成“已完成事项待办事项”的简短清单。两招配合上下文膨胀问题基本可控。4.3 工具调用参数错乱与幻觉工具模型偶尔会生成一个不存在的工具名或者给现有工具塞进一堆多余的参数。这不是模型太笨而是工具定义不够清晰或数量太多导致区分度下降。排查思路是三步走将所有工具的 JSON Schema 打印出来检查有没有描述歧义。在调用层做白名单校验工具名和参数 schema 不匹配就立即拦截。把拦截后的报错信息回传给模型作为反馈进入下一轮循环。第三步特别重要。把“你调用了不存在的工具 get_group_member可用工具列表是 send_message、get_member_list”作为 Prompt 的一部分喂回去模型大概率会自己纠正。Agent 不怕犯错怕的是错了以后没有任何反馈信号。4.4 成本与延迟失控多轮循环意味着多次模型调用复杂任务的 Token 消耗可能是单次问答的几十倍。以平均一轮消耗 3k6k Token 为例一个 15 轮的任务总消耗轻松到 6 万甚至 10 万 Token。如果不加控制一个高频使用的 Agent 每月光是 Token 开销就很可观。我常用的成本控制策略包括尽量把评估节点做成规则判断而不是模型判断、对工具返回的过长结果先截断再写入上下文、在预算达到阈值时主动提前终止并向用户报告已完成的部分。延迟问题则靠减少串行轮次来缓解——能并行的子任务尽量并行能复用的中间结果不要重复计算。5. 延伸与经验收尾从单一循环到多智能体协作5.1 把一个大循环拆成多个小循环当任务足够复杂时单个巨型循环会变得臃肿且难排查。一个常用演进方向是把“规划—执行—评估”分别拆成独立的循环由三个各司其职的 Agent 角色协同完成规划者 Agent只负责拆任务、排顺序不亲自执行工具。执行者 Agent接收明确的任务卡片调用工具并返回结果摘要。评审者 Agent对执行结果提出整改意见评审不通过就退回执行者重新处理。这样设计的好处是每个循环都足够短职责单一出了问题能快速定位到具体环节。这算是对 Hermes Loop 的一种自然延伸不是另起炉灶只是把原来的五个节点组合成了多个专业化循环的嵌套。5.2 给循环装上护栏与审计机制Agent 一旦接上真实工具比如能发消息、能操作线上系统就必须考虑安全问题。我的几个固守原则是危险操作必须二次确认、工具权限遵循最小化原则、每一步调用都留下完整审计日志。我碰到过不止一次 Agent 因为一个模糊指令把测试环境的配置改动同步到了线上。责任不完全在模型而是我的循环里缺少了“危险操作拦截”。从那之后我让所有写操作工具都要求调用者提供“操作原因”当原因不明确或与任务目标不一致时直接拒绝执行并把这个拒绝理由作为反馈写回循环。最后想分享一点个人体会Hermes Loop 不是一个需要背下来的固定公式而是一种工程思维。每次看到 Agent 表现不佳不要急着怪模型能力不行先检查循环的五个节点里有没有哪一个断了或者被跳过。意图识别模糊就回退到明确需求规划不合理就缩小规划粒度工具调用报错就把错误变成反馈重新注入。当这套循环真正闭合Agent 的状态就从“一个会聊天的接口”变成了“一个能把事办完的执行者”。这套经验是我在多次重构 Agent 执行流程之后沉淀下来的希望对正在搭建自己 Agent 的你有帮助。