用 Litefuse 追踪 Hermes Agent
Hermes Agent 是 Nous Research 的终端 AI 助手,采用可插拔的工具调用和网关架构。本集成以 Hermes 插件 形式安装到 ~/.hermes/plugins/litefuse/。插件在 Hermes 的 Python 解释器中以同进程方式运行,订阅十个生命周期 hook 事件,为每个用户回合生成一条 Litefuse trace(与 Pi、Claude Code 集成同一套 trace 形态,一条看板查询横跨你的所有 agent)。
该插件适用于 Hermes 的所有界面 —— CLI(hermes -z、hermes chat -q)、Gateway(飞书、Discord、Slack、Telegram、WhatsApp、IRC)和 TUI。
给 AI —— 自动安装
如果你正在和 Hermes Agent 对话,把下面这段 prompt 粘贴过去,Agent 会端到端完成整个安装:
Read https://litefuse.ai/SKILL.md and follow the instructions to install and configure Litefuse for Hermes Agent.
skill 会向你索取 Litefuse 的 API Key(如果还没有账号,会引导你注册),然后在本地完成全部配置。如果你想手工一步步配置,请继续往下看。
会捕获哪些数据
| 数据 | 捕获方式 | 备注 |
|---|---|---|
| 用户 prompt | trace input | trace 头随第一个完成的 observation 一起到达 Litefuse —— 不必等回合结束 |
| 每次 LLM API 调用 | plan (n tools) #N / response / think #N generation | 按模型做了什么命名,绝不用模型名;真实请求延迟来自 pre_api_request → post_api_request |
| 完整请求/响应内容 | generation 的 input(完整 messages)/ output(thinking + 正文 + toolCall 块) | 回合结束时从对话历史回填 —— thinking 会被捕获 |
| token 用量 | 每个 generation 的 usage_details | Anthropic 风格 key(input、output、cache_read_input_tokens、cache_creation_input_tokens),Litefuse 成本映射直接可用 |
| 工具调用 | tool: <name> (<关键信息>) #N tool observation | input = 参数对象,output = 结果,agent_duration_ms;关键信息 = 命令词 / 文件 basename / pattern,截断到 24 字符 |
| 工具错误 | tool observation level=ERROR + status_message | JSON 感知判定:"error": null / exit_code: 0 不会误报 |
子 agent 委派(delegate_task) | tool (n subagents) #N → 嵌套 subagent AGENT 容器 → 子步骤 | 三层子树;子 agent 的 usage 汇入父 trace 总成本 |
| 助手最终回复 | response generation 就是最后一次 LLM 调用本身 | 携带它真实的 usage 和延迟;没有重复的总结 observation |
| 模型名称 | 每个 generation 上的 model,trace tag model:<name> | Litefuse 用它来计算成本 |
| 会话分组 | trace 的 session_id | Hermes 的 YYYYMMDD_HHMMSS_<6or8hex> session id |
| 用户身份 | trace 的 user_id | $LITEFUSE_USER_ID,回退到 $USER |
| 回合编号 | trace 名 Hermes Agent — Turn N + agent_turn_number | 按用户消息计数,恢复会话时继续递增 |
| Agent 元数据 | metadata 中打平的 agent_* key | 与其他所有 agent 集成同一套 key —— 跨 agent 的看板过滤器开箱即用 |
Trace 结构
一个既调用多个工具又委派子 agent 的回合,产生的 trace 形如:
Hermes Agent — Turn 7 (AGENT, root, 真实回合时长)
├── plan (2 tools) #1 (GENERATION, usage + 真实延迟, thinking + toolCalls)
├── tool: terminal (grep) #2 (TOOL, input=参数, output=结果)
├── tool: read_file (index.ts) #3 (TOOL)
├── plan (1 tool) #4 (GENERATION, usage)
├── tool (1 subagent) #5 (TOOL —— delegate_task 的批次容器)
│ └── subagent (AGENT —— 子容器, input=任务, output=子 agent 回答)
│ ├── plan (1 tool) #1 (每个容器内编号从 #1 重新计数)
│ ├── tool: read_file (README.md) #2
│ └── subagent response (GENERATION —— 子 agent usage 汇入 trace 成本)
└── response (GENERATION —— 最后一次 LLM 调用本身, usage + 延迟)设计说明:
- 按行为命名 generation。 模型发出工具调用时叫
plan (n tools) #N,最终回答叫response,只有 thinking 的步骤叫think #N。模型名只是 generation 的model属性 —— 换模型永远不会破坏你按名字建的过滤器和看板。 - 一个共享的步骤计数器。 generation 和 tool 从同一个容器级序列取
#N,名字里的数字就是 metadata 里的agent_step_index—— 只有一套编号,不是两套。 - tool 与 plan 的关联用 metadata 表达,不靠树深度。 每个 tool 携带
agent_plan_step(发起它的 generation 的步骤序号)和agent_tool_call_id。树保持扁平,关联可查询。 - 真实 wall-clock 时间戳。 generation span 在
pre_api_request打开、用post_api_request捕获的时刻关闭 —— 时间线展示真实的 LLM 延迟。tool span 走pre_tool_call→post_tool_call。 - 完整 I/O 靠回合结束时回填。 Hermes 的 hook payload 只给计数不给内容 —— 插件把 generation span 保持打开,在
post_llm_call时从对话历史回填input(完整消息数组)和output(thinking / 正文 / toolCall 块)后再导出。每个 span 仍然只发送一次。 - trace 头随每个 span 携带。 第一个 observation 完成时 trace 就出现在 Litefuse(name / session / input / tags),不需要额外的 bootstrap observation。
- 子 agent 子树。 一次
delegate_task调用产生一个tool (n subagents) #Nspan,每个子 agent 一个subagentAGENT 容器嵌在其下。tool span 与容器之间的时间差就是真实的委派开销(进程启动、结果解析)。
快速开始
前置条件
- 在 https://litefuse.cloud 创建一个 Litefuse 项目,拿到 public + secret key。
- 已安装 Hermes Agent —— 用
hermes --version检查。较新版本(≥ v0.12)在所有界面(含 TUI 和 oneshot)都会加载插件。
把 Langfuse SDK v4 安装到 Hermes 自己的 venv
插件在 Hermes 的 Python 解释器中以同进程方式运行,所以 SDK 必须装在 Hermes 的 venv 中(不能放到单独的 venv):
~/.hermes/hermes-agent/venv/bin/pip install 'langfuse>=4,<5'
# Verify
~/.hermes/hermes-agent/venv/bin/python3 -c "import langfuse; print(langfuse.__version__)"
# Expect: 4.x.y把插件文件放进 ~/.hermes/plugins/litefuse/
mkdir -p ~/.hermes/plugins/litefuse
curl -fsSL https://litefuse.ai/integrations/hermes-agent/plugin.yaml \
-o ~/.hermes/plugins/litefuse/plugin.yaml
curl -fsSL https://litefuse.ai/integrations/hermes-agent/__init__.py \
-o ~/.hermes/plugins/litefuse/__init__.py插件源码也在同一 URL 上 —— 部署前可以先读一遍。
把 Litefuse 凭据加到 ~/.hermes/.env
插件从进程环境读取凭据(Hermes 启动时会自动加载自己的 .env 文件):
cat >> ~/.hermes/.env <<'EOF'
# Litefuse observability
LITEFUSE_PUBLIC_KEY=pk-lf-xxx
LITEFUSE_SECRET_KEY=sk-lf-xxx
LITEFUSE_BASE_URL=https://litefuse.cloud
EOF把占位值替换成真实值。LITEFUSE_* 变量优先;同名的 LANGFUSE_* 变量作为回退仍然有效,所以用 LANGFUSE_PUBLIC_KEY / LANGFUSE_HOST 配置的存量安装无需任何改动。插件还会加载 ~/.hermes/state/litefuse.env(其次 ~/.hermes/litefuse.env)作为回退的 env 文件。
启用插件
需要在 Hermes 中显式开启:
hermes plugins enable litefuse
hermes plugins list # confirm: status = enabled重启正在运行的 gateway
gateway 守护进程在启动时会缓存自己的插件管理器,因此需要重启来加载新插件:
hermes gateway restart # only if you have `hermes gateway` runningCLI 调用每次运行都会重新加载插件 —— 不用重启。
验证
hermes -z "用 shell 工具数一下 ~/.hermes/config.yaml 有多少行,然后告诉我行数"
tail -3 ~/.hermes/state/litefuse_plugin.log
# Expected: "litefuse plugin v0.2.0 registered (10 hooks, spec v1.2)"
# + "turn closed session=YYYYMMDD_HHMMSS_xxxxxx turn=1 steps=3 api=2 tools=1 final=True"打开 https://litefuse.cloud,看名为 Hermes Agent — Turn 1 的最新 trace。它应当包含:
- 正确的
name/sessionId/input/output,以及 tagshermes-agent、model:<name> - 一个 AGENT root;其余全部扁平挂在它下面
[GENERATION] plan (1 tool) #1,带 token 用量、真实延迟、output 里有模型的 thinking[TOOL] tool: terminal (wc) #2,带 input 参数、output 结果和agent_plan_step: 1[GENERATION] response,携带最终回答和它自己的 usage
环境变量
| 变量 | 必填 | 说明 |
|---|---|---|
LITEFUSE_PUBLIC_KEY | 是 | Litefuse 项目 public key(pk-lf-...)。回退到 LANGFUSE_PUBLIC_KEY。 |
LITEFUSE_SECRET_KEY | 是 | Litefuse 项目 secret key(sk-lf-...)。回退到 LANGFUSE_SECRET_KEY。 |
LITEFUSE_BASE_URL | 否 | 默认 https://cloud.langfuse.com。设为 https://litefuse.cloud(或你的自托管 URL)。别名:LITEFUSE_HOST、LANGFUSE_BASE_URL、LANGFUSE_HOST。 |
LITEFUSE_TRACING_ENVIRONMENT | 否 | 发出 trace 的 Litefuse environment(例如设为 test 把实验流量隔离出生产看板)。回退到 LANGFUSE_TRACING_ENVIRONMENT。 |
LITEFUSE_USER_ID | 否 | 覆盖 trace 的 user_id。回退到 $USER,再回退到 "hermes-user"。 |
LITEFUSE_RELEASE | 否 | 发出 trace 的 release 标签。回退到 LANGFUSE_RELEASE。 |
HERMES_LITEFUSE_DEBUG | 否 | 设为 "true" 启用 ~/.hermes/state/litefuse_plugin.log 中的详细插件日志。 |
HERMES_LITEFUSE_MAX_CHARS | 否 | span 输入/输出的截断阈值(字符数)。默认 1000000(约 1MB 文本)。 |
凭据查找顺序:进程环境 → ~/.hermes/state/litefuse.env → ~/.hermes/litefuse.env(取第一个存在的文件;环境变量永远优先于文件)。
工作原理
插件通过 ctx.register_hook(...) 订阅十个 Hermes 插件 hook 事件:
| Hook | 作用 |
|---|---|
on_session_start | 缓存 session 的 model / platform 元数据。 |
pre_llm_call | 打开本回合的 AGENT root 容器,从对话历史计算回合编号(恢复的会话接着数),并附上 trace 头。同时检测子 agent 会话(见下文)。 |
pre_api_request | 在真实的请求开始时刻打开一个 generation span,并分配下一个共享步骤编号。 |
post_api_request | 把本次调用的结果记到打开的 generation 上 —— usage、finish_reason、工具调用数、真实结束时刻 —— 并临时命名(plan (n tools) #N / response)。span 保持打开,等待内容回填。 |
pre_tool_call | 打开一个 tool: <name> (<关键信息>) #N span:input = 参数对象,agent_plan_step 指向发起它的 generation,编号取自共享计数器。对 delegate_task 会登记一个待挂载的委派,让子会话能挂上来。 |
post_tool_call | 用 output、agent_duration_ms、agent_tool_call_id 关闭对应的 tool span;失败时置 ERROR 级别 + status_message。用按 session 分隔的 FIFO 队列匹配(Hermes v0.12 调用 pre_tool_call 时不传 session_id / tool_call_id)。 |
post_llm_call | 回合结束:从对话历史回填每个挂起 generation 的 input(完整 messages)和 output(thinking / 正文 / toolCall 块),定稿命名,按记录的真实结束时刻逐个关闭,最后用最终回答和回合统计关闭 root。 |
on_session_end | 防御性清理被中断的回合 —— 泄漏的 tool span 以 WARNING 收尾("turn ended before tool completed"),没有最终文本时 root 以 WARNING 关闭。 |
on_session_reset / on_session_finalize | 在 session 真正销毁时清空内存状态。 |
子 agent 子树。 Hermes 的 delegate_task 子 agent 在同进程的工作线程里运行,hook 不携带父会话关联 —— 所以插件用启发式:在某个 delegate_task tool span 打开期间启动首个回合的会话,被视为该委派的子会话。子容器(subagent,AGENT 类型)通过 trace context 挂在委派 tool span 下;子步骤从 #1 重新编号;子 agent 的 generation 携带各自的 usage,Litefuse 自动汇入父 trace 总成本。容器 metadata 中以 agent_subagent_link: "heuristic" 记录这种关联方式。
该插件是 fail-open 的:任何意外错误都会写入 ~/.hermes/state/litefuse_plugin.log,回调静默返回,所以永远不会阻塞 Hermes 的主循环。一个 Langfuse 客户端在模块级状态中跨 Hermes 进程整个生命周期保留,并由线程锁保护,多个并发的 gateway 会话可以安全共享。
Trace metadata 参考
所有 metadata 都是打平的、带 agent_ 前缀的标量 —— 与其他 Litefuse agent 集成完全同一套 key,所以 metadata.agent_duration_ms > 60000 这样的过滤器在 Hermes、Pi、Claude Code 的 trace 上通用。源数据中不存在的字段完全不出现(没有 null 占位)。
Trace root(AGENT observation):
agent_turn_number、agent_session_id、agent_cwd、agent_model、agent_platform、agent_history_messages- 关闭时补充:
agent_api_calls、agent_tool_calls、agent_steps、agent_message_count、agent_duration_ms
Generation(plan / response / think):
agent_turn_number、agent_step_index、agent_provider、agent_api(api_mode)、agent_stop_reason、agent_api_duration_ms、agent_tool_call_count、agent_message_count- 消息带 reasoning 时有
agent_thinking_chars
Tool(tool: ...):
agent_tool_name、agent_step_index、agent_plan_step(join 键:等于发起它的 generation 的agent_step_index)、agent_tool_call_id、agent_duration_ms、agent_is_error- 触发截断时有
agent_output_truncated/agent_output_orig_len
子 agent 容器(subagent):
agent_subagent: true、agent_subagent_link: "heuristic"、agent_model、agent_platform、agent_session_id(子会话的)
故障排查
Litefuse 中没有出现 trace。 用 tail 查看 ~/.hermes/state/litefuse_plugin.log:
tail -20 ~/.hermes/state/litefuse_plugin.log期望:启动时出现 "litefuse plugin v0.2.0 registered (10 hooks, spec v1.2)",然后是 "Litefuse client ready" 和每回合的 "turn closed session=... turn=N steps=N api=N tools=N final=True"。如果文件是空的,说明插件没加载:
hermes plugins list # confirm: litefuse → enabled
hermes plugins enable litefuse # if not enabled
hermes gateway restart # if gateway is running插件日志显示 Litefuse credentials not set。 插件在环境变量和回退 env 文件中都没找到 key。把它们加到 ~/.hermes/.env:
cat >> ~/.hermes/.env <<'EOF'
LITEFUSE_PUBLIC_KEY=pk-lf-...
LITEFUSE_SECRET_KEY=sk-lf-...
LITEFUSE_BASE_URL=https://litefuse.cloud
EOF然后重新执行任何 hermes -z "..." 或重启 gateway。(LANGFUSE_* 命名作为回退同样有效。)
插件日志显示 langfuse SDK not importable。 Langfuse SDK 没装在 Hermes 的 venv 中:
~/.hermes/hermes-agent/venv/bin/pip install --upgrade 'langfuse>=4,<5'generation 要等回合结束才出现。 这是设计使然:generation 的内容(完整 messages、thinking)只有在回合结束时才拿得到,所以 generation span 在那时才导出 —— 但带着真实记录的时间戳。tool span 在每个工具完成时实时导出,trace 头随第一个完成的 observation 出现。
看到旧的 trace 形态(api: <model> #N、user message event、metadata.hermes_agent.*)。 你在运行插件 v0.1.0。从 https://litefuse.ai/integrations/hermes-agent/ 重新拉取两个文件并重启 gateway。
TUI 或 hermes -z oneshot 不产生 trace。 只影响 v0.12 之前的旧版 Hermes —— 升级 Hermes,或改用一直会加载插件的 hermes chat -q "..."。
局限
- 执行中的步骤在结束前不可见。 每个 span 恰好发送一次、在它结束时 —— 长时间运行的工具或流式 LLM 调用在完成前不会出现在 live 视图里。委派进行中,子步骤可能先于其父容器出现(列表尾部的”孤儿”行);回合结束后树视图完整且正确。
- 子 agent 关联是启发式的。 在繁忙的多用户 gateway 上,与委派同一瞬间启动的无关会话可能被误挂(会带
agent_subagent_link: "heuristic"标记)。单用户场景不受影响。 - 没有 TTFT / 采样参数。 Hermes hook 不暴露首 token 时刻和 temperature/top_p,所以
completion_start_time与完整的model_parameters(max_tokens之外)缺失。
资源
- Hermes Agent hooks 用户指南
- Hermes Agent 插件参考
- Langfuse Python SDK v4
- Litefuse Cloud
- 插件源码:
plugin.yaml·__init__.py