Hermes Agent 完整拆解:AI 代理的工具调用循环如何运转
把任务丢给聊天机器人,它往往回一段"建议你试试 grep"就结束对话;Hermes Agent 是一个自我改进的 AI 代理,它会自己反复"想一步、调一个工具、读回结果",直到任务做完才停手。
它到底是什么
一句话定位:一个把"多轮工具调用"自动化掉的对话引擎。普通工具的交互模式是你说一步、它做一步;Hermes Agent 替你跑完整个决策-执行回路——模型只负责决定"下一步调哪个工具",循环负责真正执行、把结果喂回模型、判断要不要再来一轮。你只需要描述目标,过程不用盯着。
分层拆解架构
核心逻辑集中在agent/目录,按数据流方向可以拆成三层:
循环引擎层:决定"何时再问一次模型"
agent/conversation_loop.py 中的run_conversation是整条流水线的主体。它把消息历史、系统提示、工具定义打包成一次模型请求,收到响应后做一个二选一判断:带工具调用就交给执行层,纯文本就退出循环。它不关心工具内部怎么跑,只管轮次推进;轮数由max_iterations与迭代预算双重封顶,防止失控空转。
工具执行层:把一批调用并行跑完
agent/tool_executor.py 接收模型一次响应里的工具调用批次,按批次数量临时创建线程池,每个工具独立线程执行——慢工具不拖累同批其他工具,单工具抛错只把错误文本写回该调用的结果位,循环本身不崩。执行前会先把本轮记录落库到会话数据库(持久化先于副作用),中断后也能从断点恢复。
结果收尾层:打包"这一轮换回了什么"
agent/turn_finalizer.py 的finalize_turn在循环结束后接管收尾:最终回复、完整对话历史、API 调用次数、是否被中断,全部装进一个结果字典。用量统计、轨迹导出等下游能力都从这个字典取数。
跟一次数据流:任务如何跑完
以"跑一遍测试并汇报失败原因"为例,跟一次完整数据流:
- 开场准备。输入:你的任务消息。处理:刷新凭证、重建系统提示、检查上下文是否逼近压缩阈值,发出第一次模型请求。输出:携带完整历史的 API 请求。
- 第一轮工具调用。输入:模型返回"调用 terminal 工具执行 pytest"。处理:先把该 assistant 消息记入历史,校验工具名在启用列表内并解析参数,丢进线程池执行。输出:stdout 被包成一条 tool 消息回填历史。
- 第二轮跟进。输入:带上测试输出的历史。处理:模型看到失败用例,决定"读一下报错的测试文件",同样的校验-执行-回填再走一遍。输出:新的工具结果进入历史。
- 收敛落库。输入:模型给出纯文本总结,不再带工具调用。处理:循环退出,
finalize_turn收尾并持久化。输出:最终回复与用量统计。若轮数撞上max_iterations,它会在此明确告知预算用尽,而非静默截断。
3 个常见误解(及坑)
- 模型本身不干活。模型只输出"调哪个工具+参数",真正读写文件、跑命令的是本地工具层——把它当成"更聪明的 GPT"就无法理解它为什么在 $5 的 VPS 上也能干活。
- 多轮不免费,预算有硬顶。每次请求都携带完整历史,token 成本随轮次乘积式增长;撞上限会停下并告知预算用尽,调优时优先看这一层。
- 工具报错 ≠ 程序崩溃。单个工具异常只会把错误文本写回结果位,由模型在下一轮自行处理失败;但注意历史记录必须先落库成功才会执行工具,本地调试时若会话库不可写,该轮会直接终止为失败。
适用场景与上手路径
三类典型场景:① 长任务自动化,定时日报、夜间备份,内置 cron 调度器跑完后把结果投递到 Telegram/Slack;② 本地开发代理,在你机器上读写文件、跑命令,可配容器等后端隔离风险;③ 研究 Agent 循环写法的开发者,每一轮都能打断点,没有黑盒。
最小上手序列:先执行 git clone https://gitcode.com/GitHub_Trending/he/hermes-agent 获取源码并安装,再运行hermes setup走完向导并选择模型后端,然后执行hermes进入终端界面,丢一个"列出当前目录结构"的小任务,就能看到工具被逐个调用的实时过程。
循环、线程池、结果容器,三者构成 Hermes Agent 的全部核心,其余记忆、技能、调度模块都是挂在这条主线上的插件。下一步可以直接给run_conversation打个断点单步走一轮,你对 AI 代理的理解会完全不同。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考