Competing installers and checkout-local venv assumptions bypassed PM selection, install consent, and generation lifetimes. Route consumers through PM and installation-bound launchers. Refresh source launchers before obsolete Python entries can be collected. Remove Node, browser, and CUA acquisition engines, obsolete venv-holder handling, detached sync, and unused PM APIs. Keep historical updater exports inert and preserve external tool ownership and native integration. Share product freshness and prepared inputs across builders. Align plugin admission, Docker provisioning, setup instructions, and behavioral tests. Verified targeted Python and JavaScript tests, desktop and web typechecks, scoped lint, real product builds, and the Docker frontend smoke test. The missed post-setup test cleanup is included and verified. Native Windows/macOS execution, full Rust compilation, and the complete repository suite remain unverified. Historical compatibility requirements were preserved and extended, not fully rescanned.
Langfuse Observability Plugin
This plugin ships bundled with Hermes but is opt-in — it only loads when you explicitly enable it.
Enable
# Interactive: credentials + PM preparation of the langfuse extra + enable
hermes tools # → Langfuse Observability
Restart Hermes after setup. If dependency preparation fails, retry through
hermes tools; do not inject the SDK into the selected environment with pip.
For manual source-checkout setup, see the
plugin guide.
Required credentials
Set these in ~/.hermes/.env (or via hermes tools):
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
Without the SDK or credentials the hooks no-op silently — the plugin fails open.
Verify
hermes plugins list # observability/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).
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_CAPTURE=sanitized # content capture mode (see below)
HERMES_LANGFUSE_DEBUG=true # verbose plugin logging
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 always captured in every mode.
| mode | behavior |
|---|---|
metadata |
No 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. |
full |
Raw 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.
Note: sanitized is pattern-based defense in depth, not a DLP guarantee.
For personal sessions or shared Langfuse projects, prefer metadata.
Error + shutdown coverage
- Failed model requests (
api_request_errorhook) close their generation withlevel=ERROR, status code, retry counters, and a capture-mode-scrubbed error message. Non-retryable failures also finish the turn trace. - Session end/finalize closes any still-open traces for that session and flushes queued events, so interrupted or tool-only turns don't dangle.
Disable
hermes plugins disable observability/langfuse