☰
Hermes Agent 中的两套 Agent Loop:从配置骨架到运行验证
2026/9/27 15:50:01 网站建设 项目流程

1. 为什么 Hermes Agent 里会有两套 Agent Loop

如果你最近在本地跑 Hermes Agent,大概率会在源码里撞见两个名字很像、职责却完全不同的循环体:AIAgent和HermesAgentLoop。前者服务 CLI、Gateway、Telegram、Discord 这类真人入口,后者被 Atropos 拉起来做 RL rollout。它们都叫 Agent Loop,但目标函数根本不是一回事。

AIAgent这条链路要兜住的是交互过程本身:流式输出、Provider 容错、上下文压缩、用户中断、预算耗尽后的 Grace Call、子 Agent 委派、插件钩子,基本都堆在这里。它的复杂度不来自“调模型”那一步,而来自调模型失败以后怎么办、用户半路打断怎么办、上下文塞不下了怎么办。所以这个循环体膨胀到数千行,它已经不是单纯的推理循环,而是一条完整的交互控制链。

HermesAgentLoop则完全是另一回事。它不面向用户,没有人盯着屏幕,也不需要跨 Provider 兜底。训练场景真正看重的是:必须是 async 才能并发跑大量 rollout;必须拿到真实 token、logprobs、masks 供 GRPO 训练使用;必须把工具执行和 reward 验证放在同一个 sandbox 上下文里;必须保持循环本身足够轻,避免把交互系统里的复杂分支带进训练路径。

这篇就按“配置骨架 → 触发条件 → 启动验证 → 报错排查”的顺序,把两套 Loop 怎么配、怎么切、怎么确认它真的按预期在跑讲清楚。适合已经在本地跑 AI Agent、准备接 RL 训练链路的开发者。

2. 前置准备:TaoToken 接入与目录约定

在动config.toml之前,先把模型侧的通路准备好。Hermes Agent 本身不绑定某一家 Provider,但两套 Loop 都需要一个稳定的 chat completion 端点。我本地统一走 TaoToken 的 API,原因是它在 OpenAI 兼容格式上比较省心,AIAgent的流式和HermesAgentLoop的 async 调用都能直接复用同一套 base_url。

先去控制台拿一个 Key,地址是 https://taotoken.net/api-keys ,创建后复制出来。注意这个 Key 只在创建时完整显示一次,丢了就重新建。

模型侧的基础信息如下,后面config.toml里会直接引用:

项目值
Base URLhttps://taotoken.net/api
鉴权方式Bearer Token(Header: Authorization)
兼容协议OpenAI Chat Completions
控制台https://taotoken.net/console
接入文档https://taotoken.net/doc

目录上建议这样组织,两套 Loop 的配置分开存放,避免互相污染:

hermes-agent/ ├── config/ │ ├── config.toml # 主配置,含 AIAgent 段 │ └── settings.json # HermesAgentLoop / rollout 段 ├── logs/ │ ├── aiagent.log │ └── rollout.log └── run/

环境变量先导出,别把 Key 硬编码进配置文件:

export TAOTOKEN_API_KEY="sk-你的key" export TAOTOKEN_BASE_URL="https://taotoken.net/api"

注意:config.toml里用${TAOTOKEN_API_KEY}这种占位引用,Hermes 启动时会做一次环境变量展开。如果你直接写明文,记得别把配置文件提交到仓库。

3. 可复制配置:config.toml 与 settings.json 骨架

3.1 config.toml —— AIAgent 交互链路

AIAgent段的关键是流式、容错和上下文压缩这三块。下面这份骨架可以直接抄,字段名按你本地 Hermes 版本微调:

[provider] base_url = "${TAOTOKEN_BASE_URL}" api_key = "${TAOTOKEN_API_KEY}" model = "claude-sonnet-4-20250514" timeout = 120 [aiagent] # 交互链路:面向 CLI / Gateway / Telegram / Discord enable_stream = true # 流式输出,前台体验依赖它 max_turns = 40 # 单次会话最大循环轮数 context_compress_at = 0.75 # 上下文占用超过 75% 触发压缩 grace_call_on_budget = true # 预算耗尽后补一次 Grace Call provider_fallback = ["taotoken-primary", "taotoken-backup"] interrupt_enabled = true # 允许用户 Ctrl+C 打断 subagent_delegate = true # 允许子 Agent 委派 plugin_hooks = ["logging", "budget_guard"] [aiagent.retry] max_attempts = 3 backoff_ms = 800 on_empty_response = "retry" # 空响应恢复策略

这里几个字段值得单独说。enable_stream打开后,AIAgent走的是流式分支,和HermesAgentLoop的非流式路径是两条代码。context_compress_at是压缩阈值,设太低会频繁压缩拖慢响应,设太高容易撞上下文上限,0.7 到 0.8 之间比较稳。grace_call_on_budget是预算耗尽后的兜底调用,训练链路里没有这个逻辑。

3.2 settings.json —— HermesAgentLoop rollout 链路

rollout 段的关键词是 async、token 级数据和 sandbox。它不关心流式,也不做 Provider 轮转:

{ "hermes_agent_loop": { "mode": "rollout", "async": true, "max_concurrency": 32, "capture_logprobs": true, "capture_masks": true, "sandbox": { "enabled": true, "reward_in_sandbox": true, "tool_context": "shared" }, "loop": { "max_steps": 20, "stop_on_no_tool_call": true, "emit_managed_state": true }, "atropos": { "endpoint": "http://127.0.0.1:8000", "batch_size": 16 } } }

capture_logprobs和capture_masks必须为 true,否则 GRPO 训练拿不到 token 级信号,rollout 白跑。reward_in_sandbox保证工具执行和 reward 验证在同一个 sandbox 上下文里完成,这是HermesAgentLoop和AIAgent在工具调度层复用的关键点。stop_on_no_tool_call对应 excerpt 里那四步流程的最后一步:没有工具调用就认为任务完成,退出循环。

3.3 两套 Loop 的触发条件与切换方式

配置写完后,怎么决定跑哪套?Hermes 的入口是分开的,不是运行时动态切换:

入口触发的 Loop典型场景
hermes chat/ CLIAIAgent本地对话、调试
Gateway / Telegram / DiscordAIAgent面向真人的产品入口
Atropos rollout 调度HermesAgentLoopRL 训练数据生产
benchmark 脚本HermesAgentLoop批量评测

也就是说,切换不是改一个 flag,而是走不同入口。你如果想让交互链路跑 rollout,那是用错了入口,AIAgent不会产出managed_state和 token 级数据。

4. 启动与验证:日志和请求回显怎么确认 Loop 在跑

4.1 启动 AIAgent 并观察日志

hermes chat --config config/config.toml --log-level debug 2>&1 | tee logs/aiagent.log

启动后你应该在日志里看到类似这样的行,确认走的是交互链路:

[aiagent] loop=AIAgent stream=true max_turns=40 [aiagent] provider=taotoken-primary model=claude-sonnet-4-20250514 [aiagent] context_compress_at=0.75 grace_call=true [aiagent] turn=1 -> chat_completion(stream)

发一句会触发工具调用的话,比如让它读一个本地文件。日志里会出现工具执行和结果回填:

[aiagent] tool_call name=read_file args={"path":"./README.md"} [aiagent] tool_result ok=true bytes=2048 [aiagent] turn=2 -> chat_completion(stream) [aiagent] no_tool_call -> finish

最后那行no_tool_call -> finish就是循环退出的信号,和 excerpt 里描述的四步流程一致。

4.2 启动 HermesAgentLoop rollout 并验证

rollout 一般由 Atropos 拉起,本地手动验证可以这样跑:

python -m hermes.rollout \ --settings config/settings.json \ --dataset ./data/sample.jsonl \ --log logs/rollout.log

日志里要重点确认三件事:async 并发是否生效、token 级数据是否产出、reward 是否在 sandbox 里算出来。

[rollout] loop=HermesAgentLoop async=true concurrency=32 [rollout] item=0 format_prompt ok [rollout] item=0 run() steps=3 tool_calls=2 [rollout] item=0 managed_state emitted tokens=512 logprobs=true masks=true [rollout] item=0 compute_reward in_sandbox=true reward=0.83 [rollout] ScoredDataItem -> GRPO trainer

看到managed_state emitted和compute_reward in_sandbox=true,说明这条 rollout 链路是通的。如果logprobs=false,回去检查capture_logprobs是不是被覆盖了。

4.3 请求回显验证

想确认请求真的打到了 TaoToken,可以在 debug 日志里看回显的 base_url 和 model:

[provider] POST https://taotoken.net/api/v1/chat/completions [provider] model=claude-sonnet-4-20250514 stream=true [provider] status=200 first_token_ms=420

rollout 侧是非流式,回显里stream=false,并且会带logprobs字段。两边回显的 base_url 应该一致,都是https://taotoken.net/api。

5. 本篇常见错排查

5.1 报错managed_state is None

这是 rollout 侧最典型的错。原因通常是emit_managed_state没开,或者你误用了AIAgent入口跑 rollout。检查settings.json里loop.emit_managed_state是否为 true,并确认启动命令走的是hermes.rollout而不是hermes chat。

5.2 报错logprobs missing in response

训练侧拿不到 logprobs,多半是 Provider 侧没返回。先确认capture_logprobs=true,再确认请求里带了logprobs和top_logprobs参数。如果走的是流式分支,logprobs 可能不完整,rollout 必须用非流式。

5.3 AIAgent 卡在turn=N不退出

循环不退出一般是max_turns设太大,或者模型一直返回工具调用。先看日志里tool_call是不是在重复同一个工具同一个参数,如果是,说明工具结果没被正确回填。检查handle_function_call()那一层的返回格式,工具结果必须追加回消息列表。

5.4 上下文压缩触发过于频繁

日志里频繁出现context_compress说明context_compress_at设太低。调到 0.75 到 0.8 之间,同时确认压缩后消息列表长度确实下降了,而不是压缩完又立刻涨回去。

5.5 rollout 并发上不去

max_concurrency=32但实际只有个位数在跑,检查async=true是否生效,以及 Atropos 的batch_size是否和并发匹配。另外 sandbox 如果串行执行工具,也会成为瓶颈,tool_context=shared能缓解一部分。

6. 继续往下走

配置和验证跑通之后,下一步通常是把它接进真实的训练或产品链路。如果你还在调交互链路的流式和容错,可以先用模型对话入口快速验证模型侧是否正常:https://taotoken.net/models 。如果准备长期跑编码类 Agent、需要稳定的额度和并发,可以看 Coding Plan:https://taotoken.net/coding-plan 。接入细节和参数说明都在文档里:https://taotoken.net/doc ,Key 管理在控制台:https://taotoken.net/api-keys 。

我自己的习惯是,每次改完config.toml或settings.json,先跑一遍最小验证:交互侧发一句触发工具的话,rollout 侧跑一条 dataset item,两边日志都对上了再上量。两套 Loop 的边界清楚之后,排错会快很多,因为你知道该看哪份日志。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询