跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
编程语言Agent Runtime工程化陈堂会开源二开

《Agent Runtime 工程化》第十二章 hermes-agent 产品级实战

第十二章 hermesagent 产品级实战 前面十一章讲的是方法。最后这一章,我们把方法放进一个真实开源项目里。 本章选择 NousResearch/hermesagent。原因不是它“功能多”这么简单,而是它已经把 Agent Runtime 从一个工具调用循环扩展成了产品系统:CLI/TUI、Desktop、messaging gateway、多 pr

站点编辑发布于 2026/8/15更新于 2026/9/3053 浏览
《Agent Runtime 工程化》第十二章 hermes-agent 产品级实战

《Agent Runtime 工程化:生产级 AI Agent 架构、运行时与工程实践》封面

书名:《Agent Runtime 工程化:生产级 AI Agent 架构、运行时与工程实践》

作者:陈堂会

平台:极客日志(https://zeeklog.com)

X:@Megick_com

联系邮箱:[email protected]

章节:第十二章 hermes-agent 产品级实战

第十二章 hermes-agent 产品级实战

前面十一章讲的是方法。最后这一章,我们把方法放进一个真实开源项目里。

本章选择 NousResearch/hermes-agent。原因不是它'功能多'这么简单,而是它已经把 Agent Runtime 从一个工具调用循环扩展成了产品系统:CLI/TUI、Desktop、messaging gateway、多 provider、MCP、工具注册、上下文压缩、skills、memory、cron、checkpoint、monitoring 都在一个项目里并存。读这样的项目,最容易看见 Runtime 工程化的真实样子。

本章基于截至 2026 年 8 月 14 日公开仓库 NousResearch/hermes-agent 的 main 分支,研究 commit 为 c69231270432914be78de4641651806f30654109。以下分析只基于 README、公开源码和项目文件结构,不推断未公开实现。

hermes-agent Runtime 实战地图

图 12-1:hermes-agent 的产品级 runtime 运行面示意。真实 Agent 产品不是一个 loop,而是入口、provider、工具、上下文、记忆、技能、权限、checkpoint 和观测系统围绕 loop 组成的运行面;具体模块名以源码文件为准。

12.1 读这种项目,先别急着找'主循环'

面对一个成熟 Agent 项目,新手最容易犯的错,是打开仓库就搜索 while、tool_call、chat.completions。这当然能找到东西,但很快会被分支、兼容层、回调、配置和历史包袱淹没。

更稳的读法是先画源码地图。你要先回答七个问题:

问题在 hermes-agent 中的线索
用户从哪里进入cli.py、hermes_cli/*、gateway/*、apps/desktop/*
Agent 对象在哪里run_agent.py 的 AIAgent
turn prologue 在哪里agent/turn_context.py
主循环在哪里agent/conversation_loop.py
工具怎样注册和执行tools/registry.py、model_tools.py、agent/tool_executor.py
上下文怎样管理agent/context_engine.py、agent/context_compressor.py
状态和恢复在哪里tools/checkpoint_manager.py、session DB、gateway session

这个顺序比直接追模型调用更有效。真实项目里,模型调用通常只是中间一段;前面有上下文、记忆、权限、平台来源,后面有工具执行、持久化、压缩、回调、监控。只看模型调用,会漏掉 runtime 的大部分责任。

12.2 AIAgent 是门面,不是全部实现

run_agent.py 里保留了 AIAgent 主类。构造函数参数很长,这反而是一份 runtime 边界清单:provider、api mode、toolsets、callbacks、platform、session、memory、context files、checkpoint、fallback model、credential pool 都从这里进入。

不过,AIAgent 并不是所有实现都塞在一个类里。源码注释显示,许多大块逻辑已经抽到 agent/* 模块,并由 AIAgent 保留 forwarder 以兼容旧调用。

这是一种真实项目常见的演进形态:主类仍是公共门面,内部实现逐步模块化。二开时不要急着'重构主类'。先确认哪些方法只是 forwarder,真正逻辑在哪个模块。

例如:

run_agent.AIAgent.run_conversation
  ↓ forwarder
agent.conversation_loop.run_conversation

工具执行也是类似:

AIAgent._execute_tool_calls
  ↓ 判断 sequential / concurrent / segmented
agent.tool_executor.execute_tool_calls_*

这种结构告诉我们:如果要改工具执行证据、并发策略或结果预算,真正切入点很可能在 agent/tool_executor.py 和 agent/tool_dispatch_helpers.py,而不是在 run_agent.py 顶层硬插逻辑。

12.3 turn prologue 是产品 runtime 的重地

agent/turn_context.py 负责单个 turn 的前置准备。它的源码说明很明确:这里处理 stdio guarding、runtime wiring、retry counter reset、用户消息清洗、系统 prompt、session row、preflight compression、plugin hook、external memory prefetch 和崩溃韧性持久化。

这正好对应本书前面讲的 Context Builder 与 Session State。真实项目里,turn 开始前并不是简单追加一条用户消息。它要回答:

  • 当前消息从 CLI 还是 gateway 来;
  • 是否需要注入 memory context;
  • 是否有 plugin user context;
  • 是否要创建 session DB row;
  • 是否触发上下文压缩;
  • API-bound content 和用户可见 content 是否要分开;
  • prompt cache 前缀能否保持稳定。

Hermes 用 api_content sidecar 处理'存储内容'和'发给模型内容'不完全一致的问题。这是非常值得学习的点:用户看到的 transcript 应保持干净,但 provider replay 又需要字节稳定。简单地把 memory 或 gateway note 拼到用户消息正文里,会污染会话;完全不持久化,又会破坏后续 replay。

产品级 runtime 经常就在这种细节里拉开差距。

12.4 工具系统:注册、筛选、调度三层分开

Hermes 的工具系统有三条线:

第一,tools/registry.py 是中心注册表。工具文件通过 registry.register() 声明 schema、handler、toolset、availability check 等信息。这个设计比'手写一个工具数组'更适合大项目,因为工具数量多、依赖多、可用性会变。

第二,model_tools.py 是 orchestration layer。它触发工具模块发现,提供 get_tool_definitions() 和 handle_function_call() 等公共 API,并处理 toolset 启用/禁用、同步/异步桥接。

第三,agent/tool_executor.py 负责工具调用执行。源码说明它支持 sequential 和 concurrent dispatch,还会处理分段执行。run_agent.py 中 _execute_tool_calls 的注释提到,segment planner 会把 batch 拆成可并发的连续片段和 sequential barriers。只读、非重叠文件目标、部分 MCP 工具可以并行;交互式、不安全或未识别工具形成顺序屏障。

这正好印证第四章的观点:模型可以提出多个 tool calls,但并行执行必须由 runtime 判断。

12.5 MCP:外部接入和反向暴露同时存在

Hermes 里有两种 MCP 方向。

第一种是接入外部 MCP。tools/mcp_tool.py 负责 MCP Client 支持。源码说明它支持 stdio、HTTP/StreamableHTTP、SSE transport,从 ~/.hermes/config.yaml 的 mcp_servers 读取配置,把外部工具发现并注册进 Hermes 工具系统。它还提到自动重连、环境变量过滤、credential stripping、per-server timeout、后台 event loop、sampling 支持和 per-server 并行工具调用开关。

第二种是把 Hermes 工具反向暴露为 MCP Server。agent/transports/hermes_tools_mcp_server.py 的注释写得很清楚:当 Codex app-server runtime 接管 loop 时,Hermes 的 web search、browser automation、vision、image generation、skills、TTS、kanban 等部分工具会通过 stdio MCP 暴露给 Codex 子进程。它也明确列出了不暴露的工具,例如 terminal、read/write file、patch、delegate_task、memory、session_search、todo 等,并说明原因。

这个设计很适合作为产品 runtime 案例:MCP 不只是'我能接外部工具',还可以成为 runtime 之间交换能力的边界。但边界要谨慎。哪些工具能暴露,哪些工具不能暴露,要看它们是否依赖当前 AIAgent 上下文、是否和宿主 runtime 的工具重复、是否会绕过审批。

12.6 上下文压缩:摘要必须是 reference-only

agent/context_engine.py 定义了可插拔 Context Engine。默认引擎是 compressor,也允许第三方引擎替换。接口包含 update_from_response()、should_compress()、compress(),还有 select_context() 这种每 turn 的上下文选择钩子。

agent/context_compressor.py 的注释非常有工程味。它强调:

  • 用辅助模型总结中间 turn;
  • 保护 head 和 tail;
  • 做 tool output pruning;
  • 使用结构化 summary;
  • summary 是 reference-only,不应被当作新的用户任务;
  • 压缩后要避免'摘要驱动下一轮模型继续旧任务'。

这正是第五章讲的风险:摘要不是事实替代品,也不是新的指令来源。Hermes 的 SUMMARY_PREFIX 设计把这个边界写得很明确:压缩摘要是背景引用,最新用户消息才是当前任务来源。

如果读者要二开上下文策略,建议不要直接改 summarizer prompt。先做三件事:

  1. 输出 context breakdown 或 debug report,证明哪些消息进入了模型;
  2. 构造长会话回归用例,覆盖'压缩摘要里有旧任务,但新用户要求停止';
  3. 确认工具调用和 tool result 配对在压缩后仍合法。

12.7 Memory 与 Skills 是运行时能力,不只是内容库

Hermes README 强调 memory 和 skills。源码里,这两类能力都有明确运行时边界。

agent/memory_manager.py 负责 memory provider 编排。它可以构建 system prompt、在 turn 前 prefetch、turn 后 sync,也能注入外部 memory provider 的 tool schema。源码中还有 context fencing 和 streaming scrubber,用于防止 memory context 标签或内部系统 note 泄漏到用户可见输出。

agent/skill_bundles.py 说明 skill bundle 是一组技能的别名,可以通过 slash command 一次加载多项 skill。tools/write_approval.py 则显示 memory 和 skill 写入有审批机制:memory 可以在交互式前台走 inline approval;skills 通常更大,适合 stage 后通过命令查看 diff 再批准。

这里有一个产品级经验:长期记忆和技能不是'多读几个文件'。它们会改变模型可见上下文,也可能改变用户长期行为。因此写入必须有来源、审批、待处理状态和 diff。否则 Agent 的自改进能力会变成不可控的自我污染。

12.8 Checkpoint:透明基础设施,不是模型工具

tools/checkpoint_manager.py 的开头说明很直接:Checkpoint Manager 通过单个共享 shadow git store 创建透明文件系统快照;它不是一个工具,LLM 不直接看见它;由 checkpoints config 或 --checkpoints CLI flag 控制。

这个设计和第八章高度一致。Hermes 的方案有几个工程点值得学:

  • 使用共享 store,让不同项目或 worktree 的 git objects 可以去重;
  • 使用 GIT_DIR、GIT_WORK_TREE、GIT_INDEX_FILE,避免 git 状态污染用户项目;
  • 默认排除依赖目录、构建产物、缓存、虚拟环境、VCS、媒体、大压缩包、secret 和日志;
  • 做 checkpoint pruning,清理不存在项目、过期引用和超出大小限制的快照;
  • 对 commit hash 和文件路径做输入校验,避免 git 参数注入和路径穿越。

这也提醒我们:checkpoint 不应该完全交给模型控制。模型可以请求写文件,runtime 在文件变更前后自动建立恢复点。恢复能力越底层,越能保护上层不确定性。

12.9 产品改造实战:工具调用证据面板

现在设计一个可交付的产品级 runtime feature:工具调用证据面板。

它解决的问题很实际。用户看到 Agent 最终回答时,经常不知道它到底读了哪些文件、跑了哪些命令、哪些工具失败过、哪些输出被截断、哪些操作经过审批。工程师排障时也需要这些信息。我们不直接重写主循环,而是在现有工具执行和观测边界上加一层证据投影。

目标

为每个 turn 生成一份 Tool Evidence Report,记录工具调用证据,并可被 CLI、Desktop、gateway 或 debug 页面展示。

报告至少包含:

  • runId、turnId、toolCallId;
  • 工具名、toolset、风险等级;
  • 参数摘要,敏感字段脱敏;
  • 是否经过审批;
  • 执行状态、耗时、错误分类;
  • 输出大小、是否截断、artifact 引用;
  • 文件变更摘要或 checkpoint id;
  • 并发 segment 信息;
  • 这条证据是否进入模型上下文。

切入点

不要从 run_agent.py 顶层硬改。更合理的切入点是:

目标可能文件
工具开始/结束事件agent/tool_executor.py
工具结果归一化和预算tools/tool_result_storage.py、tools/budget_config.py
工具注册元数据tools/registry.py、model_tools.py
审批上下文tools/approval.py
文件 checkpointtools/checkpoint_manager.py
内容无关监控事件agent/monitoring/events.py

第一版不要把完整工具结果写进报告。报告保存摘要和引用,完整输出仍走 artifact 或 session store。这样能避免泄露 secret,也避免报告本身变成上下文噪声。

数据结构

可以新增一个内容安全的证据事件:

from dataclasses import dataclass, field, asdict
import time
from typing import Any, Optional

def now_ns() -> int:
    return time.time_ns()

@dataclass(slots=True)
class ToolEvidenceEvent:
    turn_id: str
    tool_call_id: str
    tool_name: str
    toolset: str | None = None
    risk_level: str | None = None
    approval: str | None = None
    status: str = "unknown"
    duration_ms: int | None = None
    error_code: str | None = None
    output_chars: int | None = None
    truncated: bool = False
    artifact_ref: str | None = None
    checkpoint_id: str | None = None
    context_included: bool | None = None
    ts_ns: int = field(default_factory=now_ns)

    def to_dict(self) -> dict[str, Any]:
        return {"event": "tool_evidence", **asdict(self)}

注意,这个事件不包含原始 prompt、完整参数、完整工具输出或用户私密内容。它是证据索引,不是内容仓库。

UI 表达

CLI 可以在 turn 结束后显示一行摘要:

Tool evidence: 7 calls, 1 approval, 2 truncated outputs, checkpoint ckpt_42

Desktop 或 Web 可以展示表格:

工具状态耗时审批输出证据
read_fileok12msauto6.1K charsincluded
run_commandfailed120sapprovedtruncatedartifact
apply_patchok34msapprovedpatchckpt_42

这比'Agent 完成了'更像产品。用户能看见执行证据,工程师能复现问题,eval 能读取结构化结果。

12.10 PR 级交付计划

一个真正能提交的改造,不应只包含代码。建议按以下 PR 结构交付。

第一部分:设计说明。说明为什么需要 Tool Evidence Report,哪些用户场景受益,哪些内容不会记录。

第二部分:数据模型。新增内容安全的 evidence event 类型,并写清楚字段脱敏策略。

第三部分:采集点。先只接 tool_executor 的开始、完成、失败,不碰 provider 调用和 memory/skills 写入。

第四部分:持久化。第一版可写 JSONL 或 session DB side table。长输出只保存 artifact ref。

第五部分:展示。CLI 先展示摘要,Desktop/gateway 后续再做表格。

第六部分:测试。覆盖正常工具、失败工具、输出截断、审批拒绝、并发工具和 checkpoint 写入。

第七部分:文档。说明如何打开、如何读取、隐私边界和已知限制。

12.11 验收标准

这章的实战验收不是'把 Hermes 跑起来'。那只是使用者层面的成功。工程实战要证明你读懂了 runtime,并做了一个边界清楚的产品改造。

验收标准:

项目证据
能画出源码地图入口、turn、tool、context、MCP、checkpoint 路径清楚
能定位改造点不在 run_agent.py 里粗暴硬插
证据事件内容安全不含完整 prompt、secret、长输出
工具结果可追踪tool call id、状态、耗时、截断、artifact ref 可见
审批和 checkpoint 可关联高风险工具能看到 approval 与 checkpoint
有测试计划覆盖失败、截断、并发、拒绝和恢复
有发布风险说明说明性能、隐私、存储增长和兼容性风险

完成这一章,读者应该能把前面十一章的知识迁移到真实大型项目:不是重写一个 Agent,而是在已有系统里找到 runtime 边界,做一项能被用户、维护者和测试共同验证的改造。


系列文章目录

  • 《Agent Runtime 工程化》完整目录
  • 《Agent Runtime 工程化》第一章 Agent Runtime 全景
  • 《Agent Runtime 工程化》第二章 TypeScript / Node Runtime 基础
  • 《Agent Runtime 工程化》第三章 最小 Agent Loop
  • 《Agent Runtime 工程化》第四章 工具系统设计
  • 《Agent Runtime 工程化》第五章 上下文工程
  • 《Agent Runtime 工程化》第六章 MCP 与 Provider 抽象
  • 《Agent Runtime 工程化》第七章 权限与安全边界
  • 《Agent Runtime 工程化》第八章 Checkpoint、Resume、Rollback
  • 《Agent Runtime 工程化》第九章 可观测与 Trace
  • 《Agent Runtime 工程化》第十章 Eval Harness 与 CI 回归
  • 《Agent Runtime 工程化》第十一章 Agent Runtime 进阶学习路线
  • 《Agent Runtime 工程化》第十二章 hermes-agent 产品级实战
  • 《Agent Runtime 工程化》附录

目录

  1. 第十二章 hermes-agent 产品级实战
  2. 12.1 读这种项目,先别急着找“主循环”
  3. 12.2 AIAgent 是门面,不是全部实现
  4. 12.3 turn prologue 是产品 runtime 的重地
  5. 12.4 工具系统:注册、筛选、调度三层分开
  6. 12.5 MCP:外部接入和反向暴露同时存在
  7. 12.6 上下文压缩:摘要必须是 reference-only
  8. 12.7 Memory 与 Skills 是运行时能力,不只是内容库
  9. 12.8 Checkpoint:透明基础设施,不是模型工具
  10. 12.9 产品改造实战:工具调用证据面板
  11. 目标
  12. 切入点
  13. 数据结构
  14. UI 表达
  15. 12.10 PR 级交付计划
  16. 12.11 验收标准
  17. 系列文章目录

更多推荐文章

查看全部
  • Vivado 生成 MCS 文件并烧录 Flash 实现掉电保存
  • M2FP 模型在 AR 导航中的人体交互应用
  • FPGA加速图像处理:核心算法全解析
  • Windows 下安装 OpenClaw 并接入飞书机器人教程
  • 北理工 Fira:低秩约束下实现 LLM 全秩训练的新探索
  • 2026 年 3 月 13 日 AI 热点:芯片大战、Agent 爆发与安全争议
  • AI绘画实战:从DALL·E 3到Stable Diffusion 3,手把手教你搭建自己的AI画室(含ControlNet配置)
  • 大模型训练核心算法:损失函数详解
  • 容器化时代的挑战与监控体系建设
  • 开源大模型技术对比:LLaMA 3、Qwen 与 DeepSeek 深度解析
  • AI 时代后端程序员开发前端的技术选型与实践
  • 前端问卷系统评分题保存草稿报错解决方案
  • LangChain 实战:工具调用与结构化输出
  • AI 大模型通信机制:流式传输与数据封装逻辑解析
  • Llama-3.2-3B 实战:使用 Ollama 生成营销文案
  • 全 Web 化智慧 PACS/RIS 系统架构解析
  • 基于 Microi 吾码的服务器虚拟化资源管理与网络配置实践
  • 渗透测试实战:获取与破解 Net-NTLMv2 哈希详解
  • 二级 Python 考试真题及参考代码合集(基本操作题)
  • 基于 exo 的 Mac mini AI 推理集群构建:架构与实战

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online