Agent Loop 源码导读:一次 Hermes 任务的完整生命周期¶
Ch04.053 Agent Loop 源码导读:一次 Hermes 任务的完整生命周期¶
📊 Level ⭐⭐ | 22.1KB |
entities/hermes-agent-loop-source-code-anatomy.md
核心发现¶
金句:Agent 不是一次性的调用,而是一个循环。 Chat 是 request-response 模式(问一句答一句);Agent 是 task-completion 模式(给定目标,循环跑直到完成)。
主循环 5 阶段抽象¶
不同框架(Hermes、LangGraph、Cursor、Claude Code)命名不同,但本质都是这 5 个阶段:
| 阶段 | 职责 | Hermes 命名 |
|---|---|---|
| 1. 接收输入 | 拿到 user message 或上一轮 tool result | Receive Input |
| 2. 拼装 Prompt | 读 Memory + Skill + Context + 对话历史 | Build Prompt (Prompt Builder) |
| 3. 调用模型 | 发请求 / 等响应 / 解析结果 | Call LLM (LLM Adapter) |
| 4. 执行工具 | 模型要调工具就执行,不要就跳过 | Execute Tool (Tool Runner) |
| 5. 检查退出 | 任务完成了?完了就退出,没完就回第 1 步 | Check Done (Orchestrator) |
4 个核心模块¶
模块 1:Loop Orchestrator(循环主控)¶
200 行主循环本体。职责极窄:
- 维护当前是第几轮(turn count)
- 在 5 个阶段之间调度
- 检查终止条件
- 把每一步事件丢给下层记录
它不知道 prompt 怎么拼,不知道模型怎么调,不知道工具怎么跑。它只知道"下一步该叫谁"。
设计原则:主循环应该是最薄的那一层,重逻辑要推到下面。
模块 2:Prompt Builder(提示词组装)¶
每轮要做的事:
- 读 system prompt 模板
- 注入相关 Memory 条目
- 检索并注入相关 Skill
- 把可用 Tools 序列化成 schema
- 拼上整个对话历史
- 控制总长度不超过模型 context window
好处:改 prompt 策略不需要动主循环。想加一种新的注入方式(比如加 RAG 检索结果),只改 Prompt Builder,Loop 完全不知道。
模块 3:执行层(LLM Adapter + Tool Runner)¶
- LLM Adapter:屏蔽不同模型 API 差异(OpenAI / Anthropic / Bedrock),上层只传 prompt、拿回结构化响应
- Tool Runner:找到工具实现、传参、捕获异常、包装成统一格式
两个模块都是无状态的,方便测试和并发。
模块 4:Trajectory Recorder(轨迹记录)¶
把循环里每一个事件写到结构化的 session trace 里。是后续 Nudge Engine 和 Review Agent 的输入。
把记录和执行解耦:即使关闭自学习功能,主循环照样能跑(trace 写到 /dev/null 就行)。
一轮内完整时序¶
Orchestrator → Prompt Builder: buildPrompt(state)
Prompt Builder → Orchestrator: return prompt # 50-200ms(含 Memory 检索、Skill 匹配)
Orchestrator → LLM Adapter: callModel(prompt)
LLM Adapter → Orchestrator: return assistant message # 1-5秒(最慢)
Orchestrator 自检:has tool_calls?
Orchestrator → Tool Runner: execute(tool_call) # 默认串行
Tool Runner → Orchestrator: return tool result
Orchestrator 自检:task done?
- 无 tool_calls → 任务完成,退出
- 有 tool_calls → 回到第1步,开新一轮
金句:一轮 = 一次模型调用 + 0~N 次工具调用。 很多人以为"一轮 = 一次模型调用",结果 token 和耗时算偏了。如果模型调了 5 个工具,实际是 1 次 LLM + 5 次 Tool。
工具默认串行的原因: 工具之间可能有顺序依赖(如先 read_file 再 write_file),并发会出竞态。除非工具明确声明"只读、纯函数、可并发",否则一律串行。
4 种退出姿势¶
退出 1:任务自然完成(约 70% 任务)¶
退出 2:达到最大 turn 上限¶
Hermes 默认 25 轮(小任务)或 50 轮(复杂任务)。
关键: 达到 turn 上限的退出不能算"任务完成",否则 Review Agent 会把"卡住"当成"成功"去复盘。Hermes 显式标注 terminated_by: "max_turns",让下游知道是异常结束。
退出 3:用户主动打断¶
用户按 Ctrl+C 或点击取消按钮。需要处理:
- 中断模型 stream 生成
- 尝试 cancel 正在执行的工具(不是所有工具都支持)
- 已完成工具调用保留结果,正在执行的中断
退出 4:不可恢复错误¶
模型 API 挂了、工具抛未捕获异常、内存 OOM。处理原则:
- 把错误信息记到 trajectory(让 Review Agent 知道原因)
- 释放占用的资源
- 给用户能看懂的错误提示,不甩 stack trace
金句:一个好的 Loop,必须有 4 种退出姿势。
源码发现¶
发现 1:Loop 内不做任何业务判断¶
Hermes 的 Loop 里没有任何 if 任务类型 == X 那么... 的代码。
业务差异(如"代码任务要先 lint"、"文档任务要先 outline")全通过 Skill 注入 prompt,由模型自己判断。Loop 永远是同一个流程。
这种"通用循环 + 差异化 prompt"的设计让 Loop 可以在所有场景复用,不会因为加新功能而越来越臃肿。
发现 2:每一步事件实时落盘¶
Trajectory Recorder 不是任务结束才一次性写入,而是每一步事件实时写到磁盘。
如果任务跑到一半挂了,没落盘的事件就丢了,Review Agent 拿不到完整 trace。实时落盘的代价是每秒多写几次 disk,收益是任何异常情况下都能事后复盘。
发现 3:Tool 调用默认串行¶
改成默认并发跑 100 个真实任务,7% 出现"读到了上一步还没写完的数据"竞态。并发应该是个 opt-in 选项,不能是默认。
发现 4:刻意避免状态机¶
Hermes 没用显式状态机。Loop 就是个简单的 while 循环,状态全在变量里。
显式状态机会让每种状态都需要预先定义,新增能力时改动巨大。简单 while 循环灵活得多。
适用场景:任务种类有限、流程稳定 → 状态机(如客服对话);任务种类无限、高度灵活 → 简单 Loop(如通用 Coding Agent)。
设计哲学¶
"主循环克制,外围灵活" — 所有复杂逻辑推到 Prompt Builder/Tool Runner/Trajectory Recorder
"自进化"是叠加能力,不是嵌入逻辑 — Memory/Skill/Nudge/Review 从外部叠加到 Loop 上,Loop 不知道它们存在。哪天不想要自学习了,拔掉这些模块,Loop 照样跑
"先想清楚怎么停,再想怎么跑" — 从 Hermes 学到的最重要的一条
与 Hermes Agent 自进化系统的关系¶
Agent Loop 是 Hermes 自进化能力的执行基础设施:
- Trajectory Recorder → Nudge Engine / Review Agent 的输入数据
- Skill 注入 → 通过 Prompt Builder 实现
- Memory 注入 → 通过 Prompt Builder 实现
- 自进化闭环:Loop 跑任务 → Trajectory 记录 → Review Agent 分析 → Nudge Engine 生成改进 → Skill/Memory 更新 → 下一次 Loop 效果更好
Loop 本身不包含任何自进化逻辑,自进化是靠 Skill/Memory/Nudge/Review 从外部叠加的。这保证了 Loop 的简洁性和可替换性。
深度分析¶
Insight 1: Agent Loop 的 5 阶段抽象揭示了当前主流框架的共同范式
不同框架(Hermes、LangGraph、Cursor、Claude Code)命名不同,但本质都是这 5 个阶段:接收输入、拼装 Prompt、调用模型、执行工具、检查退出。这种一致性说明当前的 Agent 设计已经形成了相对稳定的设计模式。
Insight 2: "通用循环 + 差异化 Prompt"是解耦复杂度的关键设计
Hermes 的 Loop 不处理任何业务判断,差异化全部通过 Skill 注入 Prompt 实现。这种"通用循环 + 差异化 prompt"的设计让 Loop 在所有场景复用,不会因为加新功能而越来越臃肿。相比之下,LangGraph 的状态图、Cursor 的 IDE 绑定,本质上都是"差异化 prompt"的不同实现方式。
Insight 3: 无状态模块是并发和可测试性的基础
LLM Adapter 和 Tool Runner 都是无状态的。无状态意味着可并发、可单独测试。工具之间的共享状态通过 Trajectory Recorder 或 Memory 实现,而不是让执行层自己维护状态。
Insight 4: 工具调用串行是默认设置,并发是例外
改用并发执行工具后,7% 的任务出现竞态问题。工具之间存在隐含的顺序依赖,当前 Hermes 选择串行作为默认策略,并发需显式 opt-in。
Insight 5: 简单循环优于状态机,取决于任务复杂度
Hermes 选择简单 while 循环而非状态机,因为状态机需要预先定义所有状态,新增能力时改动巨大。适用场景不同:任务种类有限、流程稳定 → 状态机(如客服对话);任务种类无限、高度灵活 → 简单循环(如通用 Coding Agent)。
实践启示¶
-
Loop 应该只做调度,业务逻辑全部外推:如果需要根据场景差异化行为,应该通过 Skill/Prompt 注入实现,而不是在 Loop 里加
if 任务类型 == X。 -
先设计退出条件,再实现执行流程:从 Hermes 学到的最重要的一条。明确 4 种退出姿势(自然完成、达到上限、用户打断、不可恢复错误),特别是要标注
terminated_by字段让下游能区分正常结束和异常结束。 -
Trajectory 实时落盘,不要等任务结束:每次事件立即写入磁盘。虽然会多几次 disk IO,但任何异常崩溃都能事后复盘。
-
工具默认串行,并发需显式声明:除非工具明确声明"只读、纯函数、可并发",否则一律串行,避免隐含顺序依赖引发的竞态问题。
-
用 Skill 机制管理业务差异,保持 Loop 通用:不同场景的差异化通过独立的 Skill 模块注入,Loop 本身保持稳定。这样加新功能不需要修改核心循环。
相关概念¶
- Agent Loop 设计模式
- Loop Orchestrator
- Prompt Builder
- Tool Runner
- Trajectory Recorder
- Agent 自进化
相关实体¶
- Hermes Agent Loop Architecture
- Small Hermes Self Evolving Agent Architecture
- Hermes Agent Operator上手 把一个 Agent 养成可运营系统 若飞
- Hermes Observability Aliyun
- Gateway Architecture Openclaw Claude Hermes Comparison
→ 原文存档
第 2 来源 — 微信公众号「烟花星空 AI」"Hermes Agent 内部的 8 个 Loop" (2026-06-12)¶
Source: 第2原文存档 Author: YanXbt (烟花星空 AI) Original: https://x.com/IBuzovskyi/status/2064377155476193362 Date: 2026-06-12 09:53
本来源是 第 1 来源 winty 源码解剖 的同主题 1 个月后的演进——把"Hermes 单一主循环"扩展为"8 个 Loop 跨时间尺度同时运行"的复利系统。本来源补全了第 1 来源未涉及的关键维度: 跨 Loop 复利 / FlowZap 4 类 taxonomy / 迭代预算分层 / 可中断 API / ThreadPoolExecutor 并发。
核心数据¶
- GitHub stars: 95,600(发布 7 周后,2026 年增长最快 agent framework, TokenMix 2026 年 4 月)
- 自创建 skills 提速: 让研究型任务耗时相比全新 agent 实例缩短 40% (TokenMix benchmark) — 这是 Loop 复利效应的可量化证据
- 核心代码量: AIAgent 类 15,000+ 行(
run_agent.py) - 官方文档验证: 所有技术细节已对照 hermes-agent.nousresearch.com/docs 验证
FlowZap 4 类 Loop Taxonomy¶
| 类型 | 含义 | 框架实现度 |
|---|---|---|
| Retry loops | 失败后重试(最简单) | 大多数 framework |
| Reflection loops | 下一个 pass 开始前由另一个 agent 评价输出 | 少数 framework |
| Memory loops | 把经验存下来影响未来运行 | 极少数 framework |
| Skill loops | 把 procedure 编码为技能改变未来执行方式 | 仅 Hermes 等少数 |
Hermes 原生支持 4 类全部能力 + 额外 Orchestration Loop = 共 8 个 Loop。
8 个 Loop 详解(本来源独家分解)¶
Loop 1: Core Agent Loop(心跳)¶
- 时间尺度: 每 turn 内,毫秒到几分钟
- 9 步流程(比第 1 来源 5 阶段更具体):
- 接收用户消息(或
/goaljudge 继续信号) - 追加到 conversation history
- 构建或复用缓存的 system prompt(
prompt_builder.py) - 检查 compression(>50% context)
- 从 history 构建 API messages
- 注入临时 prompt layer(预算警告 / 上下文压力)
- 应用 prompt caching markers(Anthropic)
- 发起可中断 API call
- 解析 response: 有 tool calls → 执行 → 回到第 5 步;是文本 → 持久化 + flush memory + 返回
迭代预算: 默认 session 90 次(agent.max_turns); Subagents 50 次(delegation.max_iterations)
可中断调用: 后台线程 + interrupt event(用户消息//stop/signal)→ 放弃 API 线程,不写入部分 response
Tool 执行: 单 tool 主线程; 多 tool ThreadPoolExecutor 并发(完成后按原始顺序重排)
没有这个 Loop: 一切都会坏 — 这是 kernel。
Loop 2: Ralph Loop(goal)¶
- 时间尺度: 每 goal 几分钟到几小时
- 命名来源: Ralph Wiggum; 灵感来自 Eric Traut Codex CLI 0.128.0
- 核心: 辅助 judge model 每 turn 判断 done/continue
- 迭代上限 20; 与 kanban 集成:
kanban_create --goal/goal_mode=True - judge 把卡片 title + body 视为 acceptance criteria
Loop 3-8(本来源概览)¶
- Memory Loop: 跨 session 持久化经验(与 Hermes Agent Memory System Architecture 同源)
- Skill Loop: 把 procedure 编码为 SKILL.md 改变未来执行(与 Hermes Skill System 同源)
- Reflection Loop: 输出经另一 agent 评价后进入下一 pass(与 Hermes Self Improving Loop Winty 同源)
- Orchestration Loop: 跨 agent 跨时间协调(本来源独家扩展)
- Retry Loop: 失败自动重试(基础能力)
- Compression Loop: >50% 触发,Loop 1 内部步骤
复利效应理论(本来源独家)¶
"每一个 Loop 都会让其他 Loop 更有效。叠在一起形成复利系统——每跑完一次 session,系统都比之前更强。"
复利路径: Memory 沉淀经验 → Skill 用经验生成 skills → Skill 让下次 session 更高效 → Reflection 评价新 skill 质量 → 新 skill 改进 Memory 质量
与第 1 来源对比表¶
| 维度 | 第 1 来源(winty 2026-05-20) | 第 2 来源(烟花星空 AI 2026-06-12) |
|---|---|---|
| 核心定位 | 5 阶段 + 4 模块抽象 | 8 Loop 跨时间尺度复利系统 |
| Loop 数量 | 1 个主循环 | 8 个 Loop(Core/Ralph/Memory/Skill/Reflection/Orchestration/Retry/Compression) |
| 时间维度 | 单次任务生命周期 | 毫秒 → 数周(8 时间尺度) |
| 理论框架 | 5 阶段调度 | FlowZap 4 类 taxonomy + orchestration |
| 复利效应 | 未涉及 | 核心金句(本来源独家) |
| Core Loop 步骤 | 5 阶段 | 9 步详细(每步代码定位) |
| 迭代预算 | 未涉及 | session 90 / subagent 50 / Ralph 20(三层独立) |
| prompt caching | 未涉及 | Anthropic markers 集成(本来源独家) |
| 可中断 API call | 用户打断处理 | interrupt event + 放弃 API 线程(本来源独家细化) |
| 并发执行 | 工具默认串行 | ThreadPoolExecutor 并发 + 顺序重排(本来源独家) |
| 量化数据 | 无 | 95,600 stars / 自创建 skills 40% 提速(TokenMix) |
| 没有 Loop 会坏什么 | 未涉及 | 每 Loop 都有"会坏什么"(本来源独家设计鲁棒性视角) |
| 设计哲学 | 主循环克制 / 自进化是叠加 / 避免状态机 / 退出条件先行 | 复利效应 / 时间尺度差异化 / 预算分层 / 4 类 taxonomy checklist |
与其他 Hermes 实体的关系¶
- Memory Loop 与 Hermes Agent Memory System Architecture 直接对应 — Hermes 记忆系统
- Skill Loop 与 Hermes Skill System 直接对应 — Hermes 技能系统
- Reflection Loop 与 Hermes Self Improving Loop Winty 直接对应 — Hermes 自进化
- Orchestration Loop 与 Hermes Agent Operator上手 把一个 Agent 养成可运营系统 若飞 互补 — Loop 视角 vs Operator 视角
- Core Loop / Ralph Loop 与 Hermes Agent Loop Architecture 直接对应 — 主循环概念
- Core Loop 9 步 与 Hermes Agent Goal And Kanban 的
/goal+ kanban 集成直接对应 — 同一架构的两种视角
关键独到判断¶
- 8 Loop 复利是 Hermes 与其他 agent framework 的本质差距: 单 Loop 看不出价值,8 Loop 叠在一起形成复利
- FlowZap 4 类 taxonomy 是业界首个系统化 Loop 分类法: Retry/Reflection/Memory/Skill 是 Loop 设计的"自然认知映射"
- Core Loop 9 步补全 winty 5 阶段: 更具体到每步代码定位(
prompt_builder.py/ compression 检查 / prompt caching markers 等) - 迭代预算三层分层: session 90 / subagent 50 / Ralph 20 — 三层独立预算,互不干扰(对比 Hermes Agent Loop Architecture 早期版本 25/50 轮简化)
- 可中断 API call 是工程底线: interrupt event + 放弃 API 线程 — 比 winty 早期版本"用户打断处理"更精细
- 40% 提速是 Loop 复利的可量化证据: TokenMix benchmark 是 Loop 系统价值的"客观度量",其他 framework 应学这种度量
实践启示¶
- 复利效应是 Loop 系统的设计目标: 不应只看单 Loop 价值,要问"它如何让其他 Loop 更有效"
- 时间尺度差异化: Loop 应在不同时间尺度运行(毫秒/分钟/小时/天/周),避免所有决策挤在同一尺度
- 预算分层: 不同 Loop 给独立预算(session/subagent/Ralph),防止一个 Loop 占用全部 token
- 可中断性是基础设施: Core Loop 的可中断 API call 是"用户友好性"的工程底线
- 4 类 taxonomy 是设计 checklist: Retry/Reflection/Memory/Skill + Orchestration,任何一个缺失都是能力短板
- 复利需要测量: TokenMix 40% 提速是 Loop 复利效应的"可量化证据",应作为 Loop 系统的标准度量
→ 与 第2原文存档 互补阅读 — 本篇是 Hermes 8 Loop 的"完整分解"