Opt-in Langfuse tracing plugin for Hermes.
This repository is the canonical source for the Langfuse tracing runtime plugin. In the intended Hermes architecture, Hermes setup or an optional skill installs this plugin into the active profile; Hermes core and this plugin are updated independently.
- Recommended install path: use Hermes setup or the official
langfuse-tracingoptional skill when that installer path is available in your Hermes build. - Fallback install path: manually copy this repo's plugin files into
$HERMES_HOME/plugins/langfuse_tracing/. - Configuration lives in
$HERMES_HOME/.env. hermes updateupdates Hermes core only. It does not overwrite the installed plugin under$HERMES_HOME/plugins/.- Plugin updates are separate: either rerun the installer or use a symlink workflow and
git pullthis repo.
This repo is meant to be installed through the normal Hermes setup/install surface rather than by making users manually copy plugin files.
The intended Hermes flow is:
- The user opts into Langfuse tracing in
hermes setupor installs the officiallangfuse-tracingoptional skill. - Hermes asks for or detects the Langfuse settings it needs.
- Hermes installs the
langfusePython package if needed. - Hermes fetches this repo.
- Hermes copies
__init__.pyandplugin.yaml(at the repo root) into:$HERMES_HOME/plugins/langfuse_tracing/
- Hermes writes Langfuse env vars into
$HERMES_HOME/.env. - Hermes verifies
hermes plugins list. - On the next Hermes start, the plugin is discovered and becomes active.
Alternatively, install via the Hermes plugins CLI:
hermes plugins install kshitijk4poor/hermes-langfuse-tracingAfter that, do not load langfuse-tracing as a prompt skill for normal sessions. The skill/setup path is only the installer and updater; the plugin is auto-on for new sessions whenever it is installed under $HERMES_HOME/plugins/langfuse_tracing/ and HERMES_LANGFUSE_ENABLED=true.
If your current Hermes build does not expose that installer path yet, use the fallback manual install below.
PLUGIN_DIR="$HOME/.hermes/plugins/langfuse_tracing"
mkdir -p "$PLUGIN_DIR"
cp __init__.py "$PLUGIN_DIR/__init__.py"
cp plugin.yaml "$PLUGIN_DIR/plugin.yaml"For named profiles, install into:
$HOME/.hermes/profiles/<profile>/plugins/langfuse_tracing/Then set env vars in the matching profile's $HERMES_HOME/.env.
Tracing stays dormant unless enabled and both keys are present.
Required:
HERMES_LANGFUSE_ENABLED=true
HERMES_LANGFUSE_PUBLIC_KEY=pk-lf-...
HERMES_LANGFUSE_SECRET_KEY=sk-lf-...Optional:
HERMES_LANGFUSE_BASE_URL=https://cloud.langfuse.com
HERMES_LANGFUSE_ENV=development
HERMES_LANGFUSE_RELEASE=v0.1.0
HERMES_LANGFUSE_SAMPLE_RATE=1.0
HERMES_LANGFUSE_MAX_CHARS=12000
HERMES_LANGFUSE_DEBUG=trueCompatibility aliases supported by the plugin:
CC_LANGFUSE_*- bare
LANGFUSE_* TRACE_TO_LANGFUSEas a legacy enable flag alias
Resolution priority is:
HERMES_*CC_*- bare
LANGFUSE_*
After install or update:
- restart Hermes
- run:
hermes plugins list- verify
langfuse_tracingappears - run a simple Hermes prompt
- confirm Langfuse shows:
- one Hermes turn trace
- nested LLM spans
- nested tool spans when tools are used
If debugging is needed:
HERMES_LANGFUSE_DEBUG=true hermes chat -q "hello"This repo is the runtime plugin repo, not the setup wizard.
There are three layers:
- Hermes setup / optional skill
- installer and user-facing configuration layer
- this repo
- canonical source for the runtime plugin code
$HERMES_HOME/plugins/langfuse_tracing/- installed local plugin artifact that Hermes discovers at startup
- asking whether the user wants Langfuse tracing
- collecting or validating Langfuse credentials and base URL
- installing the Python dependency if needed
- fetching and copying the plugin into the active profile
- writing env vars into the correct
$HERMES_HOME/.env - telling the user to restart Hermes if needed
- the Hermes plugin manifest
- the hook handlers and trace/span logic
- payload normalization and fail-open behavior
- plugin-side compatibility with Hermes hook evolution
That split is the NanoClaw-like packaging idea here: the integration is presented through the assistant's setup/skill system, while the runtime implementation still lives in a separate repo.
When you run:
hermes updateHermes updates the Hermes codebase, not this repo and not the installed plugin directory under $HERMES_HOME/plugins/.
That means Hermes core updates should not clobber your Langfuse plugin installation.
Conceptually:
- Hermes repo updates core code
- installed plugin lives under Hermes home
- external plugin source lives in this repo
- those are separate layers
Plugin updates are separate from Hermes updates.
- update this repo source
- rerun the Hermes
langfuse-tracinginstaller path - it recopies the latest plugin files into
$HERMES_HOME/plugins/langfuse_tracing/ - restart Hermes
Pros:
- simple
- profile-aware
- matches the intended Hermes setup/skill UX
Instead of copying files into the plugin directory, symlink this repo:
PLUGIN_DIR="$HOME/.hermes/plugins/langfuse_tracing"
rm -rf "$PLUGIN_DIR"
ln -s /path/to/hermes-langfuse-tracing "$PLUGIN_DIR"Then updates are just:
cd /path/to/hermes-langfuse-tracing
git pulland restart Hermes.
Pros:
- best for development
- no recopy step
The plugin uses Hermes hook signatures and intentionally tries to absorb upstream evolution safely.
Still, when Hermes core adds or changes hook kwargs, you may need a plugin update from this repo.
Practical expectation:
- Hermes core can update independently
- most Hermes updates should keep the plugin working
- if hook contracts evolve, update this repo and reinstall or restart
Hermes upstream emits the following hooks:
- Turn-level:
pre_llm_call,post_llm_call - Request-level:
pre_api_request,post_api_request - Tool-level:
pre_tool_call,post_tool_call
The plugin registers handlers under both the pre_api_request/post_api_request names
(current upstream) and pre_llm_request/post_llm_request (forward-compatible alias)
so it works with existing and future Hermes builds.
Per Hermes turn, the plugin can capture:
- root Hermes turn trace
- LLM generations
- tool calls
- normalized tool outputs
- session and task metadata
- optional environment and release tagging
The plugin also normalizes some payloads so traces stay useful:
- parses JSON tool payloads when possible
- preserves trailing hint text
- summarizes
read_fileoutput as structured previews - omits large raw binary or base64 payloads
This plugin is designed to fail open.
That means:
- if
langfuseis not installed, Hermes still runs - if env vars are missing, Hermes still runs
- if Langfuse is unreachable, Hermes still runs
- if plugin initialization fails, Hermes still runs
Tracing simply becomes dormant instead of breaking the agent.
Open docs/hermes-langfuse-flow.excalidraw in Excalidraw to edit the diagram.
High-level flow:
- Hermes setup or the
langfuse-tracingoptional skill installs this plugin into the active profile. - Hermes startup discovers the plugin in
$HERMES_HOME/plugins/. - Hermes invokes plugin hooks around LLM calls and tool calls.
- The plugin emits traces and spans to Langfuse when enabled.
- If env vars or dependency are missing, the plugin stays dormant.
hermes-langfuse-tracing/
├── __init__.py # Plugin runtime (hook handlers, trace/span logic)
├── plugin.yaml # Hermes plugin manifest
├── README.md
├── after-install.md
└── docs/
└── hermes-langfuse-flow.excalidraw
Potential next steps:
- publish tagged releases for plugin compatibility with Hermes versions
- add a small self-check CLI for plugin diagnostics
- document a version matrix: Hermes version <-> plugin version
- add more explicit background-review and turn-type tagging once the corresponding Hermes hooks are standardized