尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Hermes Agent 源码架构拆解:从 Agent Loop、Prompt 组装到网关配置,一次读懂

Hermes Agent 源码架构拆解:从 Agent Loop、Prompt 组装到网关配置,一次读懂 1. 为什么值得花时间读 Hermes Agent 源码架构Hermes Agent 是一个把「理解任务—选择工具—观察结果—修正方案」串成闭环的智能体运行时。很多人第一次接触它会把它当成一个更会聊天的模型结果一上手就把文件、网络和高权限命令交出去。真正的问题往往不是命令写错而是没搞清楚它内部到底怎么跑一次用户消息从入口进来经过哪些模块Prompt 在哪一层被拼装工具调用由谁触发网关又在哪里把请求路由到模型端点。这篇围绕 Hermes Agent 源码架构的三个核心模块展开Agent Loop 执行流程、Prompt 组装机制、网关接入层。适合正在使用或准备接入 Hermes Agent 的开发者尤其是想自己改源码、加工具、换模型通道的人。读完之后你应该能做到三件事说清一次 Agent Loop 的完整调用链知道 Prompt 是在哪几个阶段被拼起来的能写出一份可复制的网关配置骨架把模型请求统一走 TaoToken 的 API 通道。我不会只贴架构图而是给出可运行的验证步骤。你可以跟着把 Agent Loop 的关键调用链打上日志观察每一轮循环里 messages 的变化再用网关配置把请求真正发出去。踩过的坑我也会标出来比如 Prompt 里 system 段被重复注入、网关 base_url 少写路径导致 404 这类高频问题。2. 前置准备环境、版本与 TaoToken 通道在动源码之前先把运行环境和模型通道准备好。Hermes Agent 迭代较快本文以写作时的当前稳定版为基线你执行前务必用hermes --version记录实际版本不要照抄旧参数。项目建议基线用途验证方式Hermes Agent当前稳定版智能体运行时hermes --versionPython3.11阅读与运行示例python3 --versionGit2.40变更检查与回滚git --versionTaoToken API Key已创建统一模型通道控制台查看模型通道这块我建议用 TaoToken 做统一入口。它的好处是把不同模型提供方的 Key 收敛成一个网关配置里只维护一个 base_url 和一个 Key换模型时不用改 Agent 源码。你需要先去控制台创建一个 API Key地址是 https://taotoken.net/api-keys 创建后复制保存后面网关配置会用到。注意Key 只放在环境变量或密钥服务里不要写进源码、不要提交到 Git、不要打印到日志。版本号、错误码可以记录凭证值绝不能记录。只读预检命令先跑一遍确认环境没问题# 确认当前 shell 能找到 Hermes该命令不会修改环境 command -v hermes # 记录实际运行版本后续排错必须带上这一行输出 hermes --version # 从当前安装版本获取命令说明避免使用过期参数 hermes --help # 记录 Python 与 Git 版本不输出任何环境变量值或密钥 python3 --version git --version如果hermes --help里的选项和本文不同以本机帮助和官方文档为准。工具升级很快验证比背命令可靠。3. Agent Loop 执行流程拆解Agent Loop 是整个运行时的心脏。它的本质是一个带工具回调的循环把当前对话历史交给模型模型返回要么是最终回复要么是一个工具调用请求执行工具、把结果追加回历史再进入下一轮直到模型给出终止信号或达到最大轮数。3.1 一次循环的调用链从源码角度看一次完整的 Loop 大致经过这几个阶段入口接收用户消息追加到 messages 列表。Prompt 组装层把 system 指令、历史消息、工具描述拼成最终请求体。网关层把请求发往模型端点拿到响应。解析响应如果是工具调用进入工具执行分支如果是文本判断是否终止。工具执行结果以 tool 角色消息追加回 messages。回到第 2 步直到终止或触顶。关键点在于第 2 步和第 5 步messages 是唯一的状态载体Loop 本身不保存额外状态。这意味着你只要在每轮循环打印 messages 的长度和最后一条的角色就能看清整个执行轨迹。3.2 给 Loop 打日志验证调用链下面这段代码不启动守护进程、不写项目文件只在本地模拟一次 Loop 的 messages 演进帮你理解状态是怎么累积的#!/usr/bin/env python3 验证 Agent Loop 的 messages 演进不发起真实网络请求。 from __future__ import annotations from dataclasses import dataclass, field dataclass class LoopTrace: # 记录每一轮循环的 messages 快照便于比对状态累积 messages: list[dict] field(default_factorylist) max_turns: int 5 def append_user(self, text: str) - None: self.messages.append({role: user, content: text}) def append_tool_result(self, tool_name: str, result: str) - None: # 工具结果以 tool 角色回填这是 Loop 能继续推理的关键 self.messages.append( {role: tool, name: tool_name, content: result} ) def snapshot(self, turn: int) - str: last self.messages[-1] return ( fturn{turn} messages{len(self.messages)} flast_role{last[role]} last_name{last.get(name, -)} ) def main() - int: trace LoopTrace() trace.append_user(读取当前目录下的 README 并总结) print(trace.snapshot(0)) # 模拟模型决定调用 read_file 工具 trace.append_tool_result(read_file, README 内容摘要……) print(trace.snapshot(1)) # 模拟模型基于工具结果给出最终回复 trace.messages.append({role: assistant, content: 总结完成}) print(trace.snapshot(2)) return 0 if __name__ __main__: raise SystemExit(main())保存为loop_trace.py后执行python3 loop_trace.py预期输出类似turn0 messages1 last_roleuser last_name- turn1 messages2 last_roletool last_nameread_file turn2 messages3 last_roleassistant last_name-看到last_role从 user 到 tool 再到 assistant就说明你理解了 Loop 的状态推进方式。真实源码里这个循环外面还包了一层终止判断和最大轮数保护但核心状态流转就是这三步。3.3 终止条件与最大轮数Loop 必须能停下来。源码里通常有两类终止信号模型主动返回不含工具调用的文本或者轮数达到上限。前者是正常结束后者是保护机制。你在改源码时如果发现 Agent 一直循环不退出先检查这两处工具结果是否被正确回填回填失败会导致模型反复请求同一个工具以及最大轮数配置是否被设成了无限。4. Prompt 组装机制Prompt 组装决定了模型看到什么。Hermes Agent 的 Prompt 不是一段固定文本而是分层拼出来的system 指令、工具描述、对话历史、当前用户输入各层在不同阶段注入。4.1 分层结构层内容注入时机system角色设定、行为约束、安全边界每次请求固定在最前tools可用工具的名称、参数、描述随工具集变化动态生成history历史 user/assistant/tool 消息从 messages 累积current当前用户输入每轮追加最容易出问题的是 system 层。如果你在 Loop 里每轮都重新拼一次 system而没做去重模型会看到重复的指令行为变得不稳定。源码里通常有一个组装函数专门负责这件事你改的时候要保证 system 只注入一次。4.2 组装函数骨架def build_prompt(system: str, tools: list[dict], history: list[dict]) - list[dict]: 把各层拼成最终请求体system 只注入一次。 prompt: list[dict] [] if system: prompt.append({role: system, content: system}) if tools: # 工具描述通常以结构化字段传给模型端点而非塞进文本 prompt.append({role: system, content: render_tools(tools)}) prompt.extend(history) return prompt def render_tools(tools: list[dict]) - str: # 简化示例真实实现会按端点要求序列化 lines [可用工具] for tool in tools: lines.append(f- {tool[name]}: {tool[description]}) return \n.join(lines)验证组装是否正确最直接的办法是打印最终 prompt 的角色序列prompt build_prompt(你是 Hermes Agent, [{name: read_file, description: 读取文件}], [{role: user, content: hi}]) print([m[role] for m in prompt]) # 预期[system, system, user]如果看到多个连续的 system说明去重没做好。这是 Prompt 组装里最高频的坑。5. 网关接入层与可复制配置网关层负责把组装好的请求发到模型端点并把响应解析回来。它屏蔽了不同提供方的差异让 Agent Loop 和 Prompt 组装不用关心底层是谁在提供模型。5.1 网关配置骨架下面是一份可复制的网关配置骨架把模型请求统一走 TaoToken 的 API 通道。base_url 用 https://taotoken.net/api Key 从环境变量读取# gateway.yaml —— Hermes Agent 网关配置骨架 gateway: provider: openai-compatible base_url: https://taotoken.net/api api_key_env: TAOTOKEN_API_KEY # 从环境变量读取不写明文 timeout_seconds: 60 max_retries: 2 models: default: claude-sonnet fallback: gpt-4o-mini headers: Content-Type: application/json设置环境变量后再启动export TAOTOKEN_API_KEY你的Key # 确认变量名存在不打印值 env | grep -o ^TAOTOKEN_API_KEY注意base_url 末尾不要多加/v1之类的路径除非端点文档明确要求。少写或多写路径是 404 的头号原因。5.2 网关请求验证配置好后用一条最小请求验证通道是否打通curl -sS https://taotoken.net/api/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: claude-sonnet, messages: [{role: user, content: 只回复 ok}] }预期返回里能看到choices字段和模型回复内容。如果返回 401检查 Key 是否有效、环境变量是否真的导出如果返回 404检查 base_url 路径如果超时先缩小请求体再重试不要无限重试。想直接在网页上验证模型通道是否正常可以打开模型对话页面 https://taotoken.net/models 发一条消息确认 Key 和通道都没问题再回到源码里调试。6. 本篇常见错排查现象、原因、处理方式对照如下现象常见原因排查与解决command not found: hermes未安装或 PATH 未刷新command -v hermes回到官方安装说明401 / 403Key 无效、权限不足不打印 Key检查变量名与授权范围404base_url 路径写错核对端点文档去掉多余路径段timeout网络、端点或任务过大缩小任务设明确超时不无限重试Agent 循环不退出工具结果未回填或轮数无限检查 tool 消息回填与最大轮数Prompt 行为不稳定system 重复注入打印角色序列确认 system 只出现一次路径被拒绝工作区白名单不匹配只把必需目录加入允许范围排障时优先看日志里的角色序列和 messages 长度这两个信息能定位大部分 Loop 和 Prompt 问题。接入相关的细节可以对照接入文档 https://taotoken.net/doc 里面有端点和参数的完整说明。7. 长期编码与 Agent 场景的通道选择如果你只是偶尔验证模型用按量计费的 API Key 就够了。但如果你要把 Hermes Agent 长期跑在编码、自动化任务上每天大量调用按量计费的成本和额度管理会变得麻烦。这种场景更适合用 Coding Plan它面向长期编码和 Agent 工作流额度更稳定适合把 Agent 挂在后台持续跑。选择逻辑很简单验证模型走模型对话接入调试走 API Key长期编码和 Agent 走 Coding Plan。三条路径对应不同的使用强度别用同一种方式硬扛所有场景。8. 把架构理解变成可维护的实践读懂 Agent Loop、Prompt 组装和网关这三层之后你改源码时就有了定位能力行为不对先看 Prompt 角色序列循环异常先看 messages 回填请求失败先看网关配置。这三层各管一段边界清晰。建议你保留本文的loop_trace.py和gateway.yaml每加一个工具或换一个模型通道都沿用同一套验证节奏先打日志看状态再发最小请求验通道最后才接进主流程。这样每次扩展都有证据而不是靠猜。如果你在接入网关时遇到 404 或 401先回到 API Keys 页面 https://taotoken.net/api-keys 确认 Key 状态再对照接入文档核对 base_url 和请求体格式。把这两步做完大部分通道问题都能自己解决。
返回列表