Hermes Agent Loop:一次任务是如何被执行的
Hermes Agent 的核心文件是 run_agent.py,核心类是 AIAgent。如果想理解 Hermes Agent 的基础架构,Agent Loop 是必须先看懂的一层。
Agent Loop 解决的问题很简单:用户给了一个任务,Agent 如何一轮轮调用模型、执行工具、处理结果,并最终返回答案。
一次回合的生命周期
简化后,一次 run_conversation() 大概会经历这些步骤:
11. 生成 task_id
22. 把用户消息加入 conversation history
33. 构建或复用 system prompt
44. 判断是否需要压缩上下文
55. 把内部消息格式转换成当前 provider 需要的 API 格式
66. 注入临时提示,比如预算警告、上下文压力
77. 调用模型
88. 解析响应
99. 如果有 tool calls,执行工具并把结果写回历史
1010. 如果是最终文本,保存会话和记忆后返回这就是 Agent 和普通聊天调用的区别。普通聊天通常到第 7 步就结束了,Agent 则会在工具结果回来后继续循环。
内部消息格式
Hermes Agent 内部使用 OpenAI-compatible 的消息格式:
1{ "role": "system", "content": "..." }
2{ "role": "user", "content": "..." }
3{ "role": "assistant", "content": "...", "tool_calls": [] }
4{ "role": "tool", "tool_call_id": "...", "content": "..." }无论外部模型走 Chat Completions、OpenAI Responses,还是 Anthropic Messages,最后都会汇聚到这套内部格式。
这样做的好处是,Agent Loop 不需要为每个供应商写一套完全不同的核心逻辑。
三种 API 模式
Hermes Agent 支持三类 API 执行模式:
chat_completions:OpenAI-compatible endpointcodex_responses:OpenAI Codex / Responses APIanthropic_messages:Anthropic Messages API
API mode 会影响消息怎么格式化、tool call 怎么表达、响应怎么解析、缓存和 streaming 怎么处理。
但在 Agent 内部,它们最后都会回到统一消息格式。这是 Hermes 能支持很多模型供应商的关键。
工具调用如何执行
当模型返回 tool call 时,Hermes 会把工具名和参数交给工具调度系统。
简化流程是:
1model response with tool_call
2 |
3run_agent.py
4 |
5model_tools.handle_function_call()
6 |
7tools registry dispatch
8 |
9handler 执行
10 |
11tool result 写回 conversation history
12 |
13继续调用模型如果一次返回多个 tool call,Hermes 可以并发执行。对于需要交互的工具,比如 clarify,则会强制顺序执行。
工具结果会按照原始 tool call 顺序插回历史,避免并发完成顺序影响模型理解。
Agent-level tools
不是所有工具都走普通 registry。Hermes 有一些工具需要直接修改 Agent 状态,所以由 run_agent.py 拦截处理:
todo:读写当前任务状态memory:写入长期记忆session_search:搜索历史会话delegate_task:创建隔离上下文的子 Agent
这些工具是 Hermes Agent “长期运行”和“能成长”的关键。
中断、预算和 fallback
一个长期运行的 Agent 必须能处理中断。Hermes 的 API call 是可中断的:当用户发送新消息、执行 /stop 或触发信号时,当前请求可以被放弃,不会把半截响应塞进历史。
它还维护 iteration budget,防止 Agent 无限循环。默认回合数有上限,子 Agent 也有独立预算。
当主模型遇到 429、5xx、401、403 等错误时,Hermes 可以按配置尝试 fallback provider。这样长期任务不会因为一个模型供应商临时不可用就完全失败。
压缩和持久化
上下文窗口不是无限的。Hermes 会在上下文压力变大时触发压缩:
- 先把 memory flush 到磁盘,避免丢失
- 把中间历史总结成更紧凑的摘要
- 保留最近 N 条消息
- 保持 tool call 和 tool result 成对,不拆开
- 创建新的 session lineage
每个回合结束后,Hermes 会把消息保存到 SQLite,会话可以之后继续 resume。
这层架构给我们的启发
如果你自己设计 Agent,也可以借鉴 Hermes 的几个原则:
- 模型 API 适配和内部消息格式分离
- 工具调用必须有统一 registry 和错误包装
- 长任务要有中断机制
- Agent 必须有预算,否则容易无限循环
- 历史压缩前先保存长期记忆
- 会话存储要支持搜索和 lineage
Agent Loop 是 Hermes 的心脏。它不负责所有能力,但所有能力最终都要经过它编排。
参考资料: