All plugins

Official

langfuse

Langfuse observability for Hermes: one trace per turn, one generation per LLM call (usage and cost from Hermes' own pricing, cache and reasoning tokens included), one observation per tool call and subagent. Content capture is sanitized by default (metadata-only and full are opt-in); sends traces only to the Langfuse project whose keys you set. Formerly built into Hermes core as observability/langfuse; existing users are migrated automatically.

NousResearch676Generalv2.0.0Updated 7 days ago

About

Langfuse observability for Hermes: one trace per turn, one generation per LLM call (usage and cost from Hermes' own pricing, cache and reasoning tokens included), one observation per tool call and subagent. Content capture is sanitized by default (metadata-only and full are opt-in); sends traces only to the Langfuse project whose keys you set. Formerly built into Hermes core as observability/langfuse; existing users are migrated automatically.

Langfuse for Hermes Agent

Part of the Hermes Official Plugins, Nous Research's official plugins for Hermes Agent. Formerly bundled with Hermes core as observability/langfuse.

Official Hermes Agent plugin that traces Hermes turns,
LLM calls and tool invocations to Langfuse, the open-source LLM observability
platform. One span per turn, one generation per API call, one observation per tool call and subagent.
Usage totals, per-type token counts and cost estimates come from Hermes' own pricing, so Langfuse sees
the same breakdown (input / output / cache read / cache write / reasoning tokens) as hermes logs.
Reasoning is reported as output_reasoning_tokens and left out of output, so the per-type counts
add up to the total.

The plugin fails open: no SDK, no credentials or a transient Langfuse error all turn into a no-op in
the hook (a missing SDK or missing/placeholder keys log one warning). The agent loop is never affected.

If you already used Langfuse with Hermes, you don't need to do anything. hermes update (or the
first start after updating) installs and enables this plugin for every profile that had
observability/langfuse enabled. Your keys and every HERMES_LANGFUSE_* setting stay exactly as they
were.

Install

From the Hermes plugin catalog:

hermes plugins install langfuse

Install asks for your project keys and saves them to the profile's .env. For a self-hosted Langfuse,
also set the server URL:

HERMES_LANGFUSE_PUBLIC_KEY=pk-lf-...
HERMES_LANGFUSE_SECRET_KEY=sk-lf-...
HERMES_LANGFUSE_BASE_URL=https://cloud.langfuse.com   # or your self-hosted URL

Keys pasted straight from a template (pk-lf-..., your-key, ...) are refused with a warning. The
pk-lf- / sk-lf- prefix is enforced only for Langfuse Cloud (*.langfuse.com); on any other
host a key without it logs a one-time warning and is still used, since a custom
Langfuse-compatible endpoint may issue its own keys and authenticates them itself.

Restart Hermes and the next turn ships a trace. Plugins are installed per profile: use
hermes -p <profile> plugins install langfuse for another profile. The only Python dependency is the
langfuse SDK, which install prepares for you.

Verify

hermes plugins list                 # langfuse should show "enabled"
hermes chat -q "hello"              # then check Langfuse for a "Hermes turn" trace

Generation observations include the Hermes system prompt when the provider uses a separate system
param (Anthropic Messages API). Open an LLM call child span to inspect role: system (truncated
via HERMES_LANGFUSE_MAX_CHARS).

Root traces carry platform:<name> and trigger:cron|interactive tags (cron runs also
cron-job:<job-id>), and their metadata names the Hermes profile the turn ran for, so scheduled
runs and profiles sharing one project can be filtered apart. Kanban worker turns also carry
kanban_task_id / kanban_run_id, so a trace joins back to its board card.

End-user attribution (opt-in)

Langfuse can group traces by the person who sent the message (its Users view). That needs a
third-party identifier, so it is off until you turn it on for a profile:

hermes config set plugins.entries.langfuse.settings.end_user_attribution true

In the Desktop app it is a switch on the plugin's page under Settings → Plugins. With it on, a
gateway turn's trace gets the sender's platform ID as its userId, exactly as the platform reports it
(for Matrix, the full @user:server ID), and subagents carry the user of the turn that spawned them.
Turns with no sender, such as CLI and cron runs, stay without a userId. The setting is read every
turn, so no restart is needed. The ID goes to your Langfuse project unhashed, even when
privacy.redact_pii is on.

How it works

HookBehaviour
pre_api_request / pre_llm_callOpen (or reuse) a per-turn root span "Hermes turn". Start a generation child observation for this API call with serialized recent messages as input.
post_api_request / post_llm_callClose the generation, attach usage_details, cost_details, finish_reason, assistant output + tool calls. If no tool calls and non-empty content, close the turn.
api_request_errorClose the failed generation with level=ERROR, status code, retry counters and a capture-mode-scrubbed error message. Non-retryable failures also finish the turn.
pre_tool_callStart a tool child observation with sanitized args.
post_tool_callClose the tool observation with sanitized result. read_file payloads get summarized (head + tail + omitted-line count) so a huge file read stays under HERMES_LANGFUSE_MAX_CHARS.
subagent_start / subagent_stopOne observation per delegated subagent under the parent turn.
on_session_end / on_session_finalizeClose any still-open traces for the session, so interrupted or tool-only turns don't dangle. Only process exit flushes.

Ended observations export through the SDK's bounded background queue: turn completion, API errors
and session rotation (/new, /reset, expiry) never wait for flush(), so a slow or unavailable
Langfuse backend cannot hold up a finished turn (or a cron job past its watchdog). Process exit
still flushes and can wait for the SDK. Traces may appear after the SDK's next batch; a full queue,
failed export or abrupt kill can lose telemetry (there is no offline spool).

Session grouping keys off the Hermes session ID (or task ID for subagents) via
langfuse.propagate_attributes, so everything in one hermes chat session lives under one Langfuse
session. Under a multiplexed gateway each profile traces with its own keys.
Each turn is its own trace, so HERMES_LANGFUSE_SAMPLE_RATE samples individual turns, not whole
conversations.

Optional tuning

HERMES_LANGFUSE_ENV=production       # environment tag
HERMES_LANGFUSE_RELEASE=v1.0.0       # release tag
HERMES_LANGFUSE_SAMPLE_RATE=0.5      # sample 50% of traces
HERMES_LANGFUSE_MAX_CHARS=12000      # max chars per field (default: 12000)
HERMES_LANGFUSE_MAX_DEPTH=4          # max payload depth (default: 4)
HERMES_LANGFUSE_CAPTURE=sanitized    # content capture mode (see below)
HERMES_LANGFUSE_DEBUG=true           # verbose plugin logging to agent.log
OTEL_SERVICE_NAME=my-agent           # OTel service.name on traces (default: hermes-agent)

The standard SDK names (LANGFUSE_PUBLIC_KEY, LANGFUSE_SECRET_KEY, LANGFUSE_BASE_URL) are
accepted too; the HERMES_-prefixed ones win when both are set.

HERMES_LANGFUSE_MAX_DEPTH controls nested payload capture in both sanitized and full modes,
including tool arguments and JSON tool results. The root is depth 0; each dictionary value or array
element adds one level. Values beyond the limit become <max-depth>, including scalars. For deeper MCP
responses, set it to a higher non-negative integer (for example, 10). Unset or blank values default
to 4; invalid or negative values log a warning and fall back to 4. 0 keeps only the root level.
Increasing the depth exports more content and may produce larger traces; secret redaction,
string-length limits and the 50-item collection limit remain unchanged. metadata mode still omits
content.

Capture modes

HERMES_LANGFUSE_CAPTURE controls how much content (prompts, responses, tool arguments/results) is
exported. Structural metadata (IDs, roles, tool names, token usage, cost, timing) is captured in every
mode.

modebehavior
metadataNo content. Each content field is replaced by a shape/size stub ({"omitted": true, "type": "text", "chars": N}).
sanitized(default) Content is exported after secret-pattern redaction (API keys, tokens, JWTs, private keys, password=-style assignments) and truncation. Redaction runs before truncation.
fullRaw content, truncated only. Explicit opt-in: traces will contain whatever passed through the conversation, including injected memory and file contents.

The active mode is recorded on every trace as metadata.capture_mode. sanitized is pattern-based
defense in depth, not a DLP guarantee. For personal sessions or shared Langfuse projects, prefer
metadata.

Disable or remove

hermes plugins disable langfuse     # keep it installed, stop tracing
hermes plugins remove langfuse      # uninstall

The Langfuse client is cached after the first hook call. If credentials or the SDK are missing, that
decision is cached too, so later hooks return immediately.

Development

git clone https://github.com/NousResearch/hermes-agent
git clone https://github.com/NousResearch/hermes-official-plugins
cd hermes-official-plugins/langfuse
HERMES_AGENT_REPO=../../hermes-agent PYTHONPATH=../../hermes-agent python -m pytest -q

On a Hermes core that still bundles observability/langfuse, an installed copy of this plugin stays
inactive (the bundled copy keeps tracing) so traces are never sent twice.

README from the reviewed commit e7a218f; it updates when the author re-pins.

More by NousResearch

29 plugins by NousResearch in the catalog.

NousResearchaccent-pickerOKLCH accent colour picker for the Hermes Desktop status bar: drag it and the whole theme retints live, with palette commands to reset to the theme default or copy the current colour. A theme-authoring tool; the colour is scratch state and is never persisted. Desktop-only (desktop/plugin.js inside the plugin SDK surface); no agent tools, hooks, middleware or env vars.OfficialDesktop app676NousResearchadvanced-delegationTwo extra delegation modes for delegate_task, next to the built-in default. Model routes (delegation.backend: model_map): the agent picks a named model route per subagent from a list you define (e.g. fast, deep, local). Profile routes (delegation.backend: profile_routes): the agent runs a subagent as one of your Hermes profiles, with that profile's own model, credentials, skills and SOUL.md. Only route names and their one-line descriptions reach the model. Adds hermes delegation config (pick the mode and edit its routes; --show prints the setup) and the /delegation slash command (save a mode for the next session, or --now to apply it to the current chat). Needs Hermes 0.22.5 or newer, the first release with pluggable delegation providers; Hermes 0.22.0 to 0.22.4 refuses to install it, and on a core older than 0.22.0 it installs, logs one warning and does nothing. A model route can set daybreak: true to run its model with OpenAI's Daybreak trusted-access program; it is sent only from your own CLI, TUI or Desktop chats, on openai-codex, for models your Codex catalog lists, and a route that breaks a rule is refused. Disclosure — no Python dependencies and no network or model calls of its own, except that a Daybreak route checks the Codex catalog through core's cached lookup with your existing Codex login; subagents run through core's delegate_task on the routes you configured. Writes only delegation.backend and delegation.backends.* (model_map / profile_routes) in the active profile's config.yaml, through core's config writer. A model route's optional api_key is stored in config.yaml in plain text (provider: keeps keys in .env / auth.json). Listing a profile under profile routes lets this profile's subagents use that profile's credentials, SOUL.md and terminal policy.Officialtools676NousResearchagent-importershermes import-agent: import an OpenClaw (~/.openclaw, or legacy ~/.clawdbot / ~/.moltbot), Claude Code (~/.claude), Codex CLI (~/.codex), Cursor (~/.cursor), Grok Bot (a self-export the Bot writes from a prompt the importer prints) or OpenBot desktop (its openbot.db) setup into Hermes in one command; always previews first and asks before applying. Claude Code / Codex / Cursor: instructions, Cursor rules and memories become memory entries, Bash permission rules become command allow/deny lists, MCP servers land in config.yaml, skills are copied, and --sync re-imports sources that changed. OpenClaw (core's former hermes claw migrate; the plugin keeps that spelling, hermes claw cleanup and the openclaw-migration skill): persona, memories, skills, model and messaging settings, MCP servers and agent behaviour. Formerly built into Hermes core; hermes setup offers to install it when it finds one of these agents, and profiles with a registered sync source are migrated automatically. Disclosure — no Python dependencies, no network calls and no model calls. Claude Code / Codex / Cursor: reads those agents' local config trees (never their credential files; secret-looking MCP env vars and headers are stripped and listed) and writes only into the active profile (memories/MEMORY.md with a backup, config.yaml, skills/ and import-sync.json). OpenClaw: reads the OpenClaw dir (openclaw.json, its .env, workspace files such as SOUL.md / MEMORY.md / USER.md, skills); API keys and bot tokens come over only with --migrate-secrets (allowlisted names, shown in the preview). It writes into the active profile (config.yaml, .env, SOUL.md, memories/, skills/openclaw-imports/, a migration/openclaw/<time>/ report with item backups, and a backups/pre-migration-*.zip restore point), plus a workspace dir only when --workspace-target names one. It runs local pgrep / systemctl / tasklist checks to warn when OpenClaw or a Hermes gateway is still running, and hermes claw cleanup renames the OpenClaw dir to *.pre-migration after a confirmation. Grok Bot / OpenBot: instructions become SOUL.md, memories and user facts become memory entries, skills land in skills/<source>-imports/, scheduled routines become paused cron jobs (--activate-routines to start them) and event routines a notes file; credential-looking export keys refuse the file, and secret MCP env vars and headers are stripped and listed. OpenBot's database is opened read-only (or read from a scratch copy that is deleted after the read).Officialtools676NousResearchblenderOfficial Blender Lab MCP server over stdio, pinned to upstream v1.0.3, with a Blender workflow skill. Needs Git and uv; Blender 5.1+ is not needed at install. The skill opens Blender itself when a task needs it and, after you agree, installs Blender and Blender Lab's MCP add-on. First startup downloads Python dependencies; prepare the uv environment before connecting. Disclosure — tools execute arbitrary Python in Blender with your privileges; the skill starts Blender with online access for that session only (your saved preference is unchanged), and the add-on's local server on port 9876 has no password, so any program on this computer can use it while Blender is open; only after you agree does the skill download Blender from download.blender.org (about 400 MB, about 1.5 GB unpacked), check it against blender.org's sha256 list and install it in your own folder without administrator rights (Linux ~/.local/opt, macOS ~/Applications, Windows %LOCALAPPDATA%\Programs\Blender Foundation; never over an existing Blender), and download the v1.0.3 add-on, check its hash and install or enable it; first start downloads the pinned Blender Lab MCP server and its Python dependencies with uv. Server discovery does not prove scene readiness.Officialtools676

Developer Mode

Explore built-in Hermes toolsets and actions.

HermesAgent

Developer?

Create a Hermes extension for Desktop or agent workflows.

Developer Section