Backends overview
hermes-otel speaks plain OTLP/HTTP, so any OTLP-compatible backend should work — but these are the ones that ship with first-class support, docker-compose files, and (where relevant) smoke-test coverage.
Supported today
| Backend | Signals | Deployment | Account / cost |
|---|---|---|---|
| Phoenix | Traces only | Local (single container) · Arize AX cloud | OSS, no account · commercial cloud |
| Langfuse | Traces | Local (docker compose) · Cloud | OSS, no account · free tier + paid |
| LangSmith | Traces | Cloud only (self-host = enterprise) | Free personal tier · paid tiers |
| SigNoz | Traces + metrics + logs | Local (docker compose) · Cloud | OSS, no account · free tier + paid cloud |
| Jaeger | Traces | Local (single container) | OSS, no account needed |
| Grafana Tempo | Traces | Local (docker compose) · Grafana Cloud | OSS, no account · free tier + paid cloud |
| Grafana LGTM | Traces + metrics + logs | Local (single container) | OSS, no account |
| Uptrace | Traces + metrics + logs | Local (docker compose) · Self-hosted | OSS · premium license for HA features |
| OpenObserve | Traces + metrics + logs | Local (single container) · Self-hosted HA | OSS, no account |
| Parseable | Traces + metrics + logs | Self-hosted · Cloud | OSS · paid cloud |
| Honeycomb | Traces + metrics + logs | Cloud (US / EU) | Generous free tier · paid plans |
| W&B Weave | Traces | W&B Cloud · Dedicated Cloud · Self-Managed | W&B account |
| Elastic | Traces + metrics + logs | Elastic Cloud (mOTLP) · self-hosted EDOT Collector | Elastic license / cloud plan |
| OpenLIT | Traces + metrics + logs | Local (docker compose, 2 containers) · Helm | OSS (Apache-2.0), no account |
| MLflow | Traces | Local (docker compose, 1 container) · Helm · Databricks | OSS (Apache-2.0), no account |
| Comet Opik | Traces | Local (docker compose, 7 containers) · Helm · Comet cloud | OSS (Apache-2.0) · free cloud tier |
| Laminar | Traces + logs | Local (docker compose, 5 containers) · Helm · Laminar cloud | OSS (Apache-2.0) · free cloud tier |
| LangWatch | Traces + metrics + logs | Local (docker compose, 5 containers) · Helm · LangWatch cloud | OSS (Apache-2.0) · free cloud tier |
| Latitude | Traces | Local (docker compose, 13 containers) · Helm · Latitude cloud | OSS (MIT) · free cloud tier |
telemetry.dev (via generic otlp) | Traces + metrics + logs | Cloud | Free tier + paid plans |
| Generic OTLP | Depends on collector | Anywhere | — |
Quick picks
"I just want to see a trace, right now, on my laptop" → Phoenix — one container, open the UI on port 6006, done.
"I want pretty LLM-specific UI and I'm fine running a stack" → Langfuse — polished UI for LLM traces, free cloud tier, robust self-host.
"I want traces and the token/tool/cost metrics dashboard" → SigNoz, LGTM or OpenObserve — they accept OTLP metrics as well as traces (Phoenix does not).
"I want all three signals — traces, metrics, AND logs — in Grafana, in one container"
→ Grafana LGTM — grafana/otel-lgtm bundles Grafana + Tempo + Loki + Mimir + a collector. Pair with capture_logs: true and you get trace-id-correlated logs out of the box.
"I'm already on LangChain / LangSmith" → LangSmith — free personal tier, zero extra infra.
"Standard distributed tracing stack, no LLM-specific UI needed" → Jaeger or Grafana Tempo — both are traces-only; pair with Prometheus if you need metrics.
"I want a cloud backend with a generous free tier and all three signals"
→ Honeycomb — OTLP-native; set OTEL_HONEYCOMB_API_KEY and a region.
"I want W&B's Agents and Traces UI for Hermes runs"
→ W&B Weave — direct OTLP trace ingest with OTEL_WEAVE_API_KEY, wandb.entity, and wandb.project.
"I want Hermes agent runs plus traces, metrics, and logs in Parseable" → Parseable — direct OTLP ingest into three datasets, with Agent Observability and a ready-made dashboard.
"I want a hosted backend purpose-built for LLM/agent telemetry, gen_ai.*-native"
→ telemetry.dev — OTLP ingest with a single Authorization: Bearer header, via the generic otlp type.
"I want an OTel-native LLM UI with all three signals, self-hosted and light"
→ OpenLIT — two containers, gen_ai.*-aware views, traces + metrics + logs on the standard /v1/* paths.
"We already run MLflow for experiments" → MLflow — traces land in an experiment next to your runs, with MLflow's own token and cost roll-ups.
"I want the richest LLM-trace view of the self-hosted batch: threads, span types, cost per call"
→ Comet Opik — maps both gen_ai.* and llm.* conventions; thread_id is the Hermes session.
"An agent-focused trace UI that also keeps the agent's log lines" → Laminar — span types, tokens and cost per call, plus log records next to the trace; metrics are off because Laminar drops them.
"An LLM platform with all three signals and an evaluation workflow"
→ LangWatch — traces, metrics and logs under one /api/otel prefix; thread id = the Hermes session.
"Our observability is already Elastic (self-hosted or Elastic Cloud)"
→ Elastic — one type: elastic entry covers the managed OTLP endpoint (ApiKey auth) and a self-hosted EDOT Collector (no key needed).
"My company already has an OTel collector / New Relic / Datadog" → Generic OTLP — point at its ingest endpoint and it just works.
"I want several of the above simultaneously" → Multi-backend fan-out — same spans, parallel, non-blocking.
Signal support
Backends differ in which OTel signals they accept. The plugin auto-skips signals a backend can't take — you don't need to configure anything.
| Backend | Traces | Metrics | Logs |
|---|---|---|---|
| Phoenix | ✅ | ❌ (rejects /v1/metrics; the plugin defaults metrics: false) | ❌ |
| Langfuse | ✅ | ❌ | ❌ |
| LangSmith | ✅ (via HTTP Run API, not OTLP) | ❌ | ❌ |
| SigNoz | ✅ | ✅ | ✅ |
| Jaeger | ✅ | ❌ | ❌ |
| Grafana Tempo | ✅ | ❌ | ❌ |
| Grafana LGTM | ✅ | ✅ | ✅ |
| Uptrace | ✅ | ✅ | ✅ |
| OpenObserve | ✅ | ✅ | ✅ |
| Parseable | ✅ | ✅ | ✅ |
| Honeycomb | ✅ | ✅ | ✅ |
| W&B Weave | ✅ | ❌ | ❌ |
| Elastic | ✅ | ✅ | ✅ |
| OpenLIT | ✅ | ✅ | ✅ |
| MLflow | ✅ | ❌ | ❌ |
| Comet Opik | ✅ | ❌ | ❌ |
| Laminar | ✅ | ❌ (accepted and dropped; off by default) | ✅ |
| LangWatch | ✅ | ✅ | ✅ |
| Latitude | ✅ | ❌ | ❌ |
| telemetry.dev | ✅ | ✅ | ✅ |
| Generic OTLP | ✅ | depends on collector | depends on collector |
If you care about token / tool / cost metrics on a traces-only backend, pair it with a Prometheus-compatible sink or fan out to SigNoz / LGTM / OpenObserve alongside. See OTel logs for the logs pipeline.
Metrics and your backend
Two metric settings depend on the backend (since 1.15; details on the metrics reference):
| Backend | Temporality it wants | Preset | Exponential histograms |
|---|---|---|---|
| Grafana LGTM, Tempo-side Prometheus, Mimir | cumulative (delta is dropped unless otlp-deltatocumulative is on) | cumulative (default) | Prometheus 3.8+ native histograms; Mimir only with native-histogram ingestion enabled |
| OpenObserve | cumulative works; delta handling undocumented | cumulative (default) | not documented |
| SigNoz | recommends delta; exponential histograms are delta-only and self-hosted-only | delta | self-hosted only |
| Uptrace | prefers delta, converts cumulative | delta | recommended |
| Honeycomb | either | cumulative (default) | not verified |
Parseable, generic otlp | depends on the collector behind it | cumulative (default) | depends |
| Elastic | delta required (ES does not handle cumulative histograms) | delta | accepted |
| OpenLIT | cumulative stored as-is (verified) | cumulative (default) | stored (exponential histogram type) |
Datadog, New Relic, Logfire (via generic otlp today, explicit types tracked in #232) | delta required (Datadog rejects cumulative sums; Logfire dashboards stay empty on cumulative; New Relic prefers delta) | set metrics_temporality: delta on the entry | Datadog and New Relic accept them |
Override per entry with metrics_temporality: cumulative | delta, or for every backend with the top-level metrics_temporality. metrics_histogram: exponential switches every backend to base-2 exponential histograms, so use it only when all of them accept those.
Short-lived runs. hermes -z exports metrics once, when it exits. A single cumulative point from a fresh process counts as zero on Datadog and New Relic (they treat the first point as a baseline) and goes stale after five minutes on Prometheus; the same run exported as delta counts in full on every delta-capable backend. Long-lived gateways are unaffected either way.
Selecting a single backend
Single-backend selection is env-var-driven. First match wins:
LANGSMITH_TRACING=true→ LangSmith- Langfuse credentials + at least one
OTEL_LANGFUSE_*variable (OTEL_LANGFUSE_PUBLIC_API_KEY,OTEL_LANGFUSE_SECRET_API_KEYorOTEL_LANGFUSE_ENDPOINT) → Langfuse OTEL_SIGNOZ_ENDPOINTset → SigNozOTEL_UPTRACE_ENDPOINT+ DSN set → UptraceOTEL_OPENOBSERVE_ENDPOINT+ credentials set → OpenObserveOTEL_PARSEABLE_ENDPOINT+PARSEABLE_API_KEYset → ParseableOTEL_WEAVE_API_KEY(orOTEL_WEAVE_ENDPOINT/OTEL_WEAVE_BASE_URL) +WANDB_ENTITY+WANDB_PROJECTset → W&B WeaveOTEL_HONEYCOMB_API_KEY(orOTEL_HONEYCOMB_ENDPOINT) set → HoneycombOTEL_ELASTIC_ENDPOINTset → Elastic (OTEL_ELASTIC_API_KEYoptional: a local EDOT Collector needs none, and a key alone never opts in because Elastic has no default host)OTEL_OPENLIT_ENDPOINTset → OpenLIT (OTEL_OPENLIT_API_KEYoptional, same rule)OTEL_MLFLOW_ENDPOINTset → MLflow (MLFLOW_EXPERIMENT_IDoptional, default0)OTEL_OPIK_API_KEY(cloud, withOPIK_WORKSPACE) orOTEL_OPIK_ENDPOINTset → Comet OpikOTEL_LAMINAR_API_KEYset (cloud, or withOTEL_LAMINAR_ENDPOINT) → LaminarOTEL_LANGWATCH_API_KEYset (cloud, or withOTEL_LANGWATCH_ENDPOINT) → LangWatchOTEL_LATITUDE_API_KEY+LATITUDE_PROJECTset (cloud, or withOTEL_LATITUDE_ENDPOINT) → LatitudeOTEL_JAEGER_ENDPOINTset → JaegerOTEL_TEMPO_ENDPOINTset → TempoOTEL_PHOENIX_ENDPOINTset → Phoenix
Vendor SDK variables (LANGFUSE_PUBLIC_KEY / LANGFUSE_SECRET_KEY, WANDB_API_KEY, HONEYCOMB_API_KEY, ELASTIC_API_KEY, OPENLIT_API_KEY, MLFLOW_TRACKING_TOKEN, OPIK_API_KEY, LMNR_PROJECT_API_KEY, LANGWATCH_API_KEY, LATITUDE_API_KEY) only fill in credentials. On their own they never switch export on, because they are often set for other tools and Hermes loads $HERMES_HOME/.env into the process; one plugin-namespaced OTEL_* variable is the explicit opt-in. When such credentials are present without the opt-in, the startup log says which OTEL_* variable would enable export, and the dashboard's OTel → Settings → Environment view shows the same notice.
Setting backends: in config.yaml overrides the env-var flow entirely — see Multi-backend fan-out.
Running one locally
Every self-hostable backend above, plus the candidates tracked in #232, has its own folder under docker-compose/ in the repo: docker compose -f docker-compose/<name>/docker-compose.yaml up -d, and down -v to remove it with its data. Each folder has a README (why pick it, logins, the backends: snippet, verification query, caveats), and docker-compose/README.md is the manual: the comparison table, the port map, disk/memory budgets and the test loop.
Backends without an explicit type: yet are driven through the generic otlp type; each was verified end to end on 2026-10-05 with hermes-otel 1.19.0 (OpenLIT, MLflow, Opik, Laminar, LangWatch and Latitude have explicit types since 1.23):
| Backend | Compose file | Stored from a Hermes turn | Plugin config |
|---|---|---|---|
| OpenLIT (#222) | openlit/ | traces + metrics + logs | type: openlit, http://localhost:4338 (explicit type since 1.23) |
| MLflow (#221) | mlflow/ | traces (with MLflow's own token and cost roll-ups) | type: mlflow, http://localhost:5001 (explicit type since 1.23) |
| Comet Opik (#220) | opik/ | traces (threads, span types, cost) | type: opik, http://localhost:5173 (explicit type since 1.23) |
| Laminar (#223) | laminar/ | traces + logs; metrics accepted and dropped | type: laminar, http://localhost:8100, api_key_env (explicit type since 1.23) |
| LangWatch (#229) | langwatch/ | traces + metrics + logs | type: langwatch, http://localhost:5560, api_key_env (explicit type since 1.23) |
| Langtrace (#224) | langtrace/ | traces (string and int attributes only) | type: otlp, http://localhost:3040/api/trace, header x-api-key, metrics: false, logs: false |
| Sigiro (#71) | sigiro/ | traces + metrics + logs | type: otlp, http://localhost:4378/v1/traces |
| Maple Local (#49) | maple/ | traces + metrics + logs | type: otlp, http://localhost:4388/v1/traces |
| Parseable OSS (#238) | parseable/ | traces + metrics + logs, through the bundled collector | type: otlp, http://localhost:4348/v1/traces |
| Latitude (#230) | latitude/ | traces (13 containers, ~15 GB of images) | type: latitude, http://localhost:3002, api_key_env + project (explicit type since 1.23) |
Elastic (elastic/: Elasticsearch + Kibana + EDOT Collector, type: elastic) was added on 2026-10-07 and verified with hermes-otel 1.21.0. Two of these are not open source: Sigiro publishes only a binary image, and Maple is source-available under FSL-1.1. Jaeger v2 (jaeger-v2/) and Langfuse v4 (LANGFUSE_VERSION=4) have their own stacks so the read-side issues #245 and #246 can be reproduced locally.
Planned
These are OTLP-compatible and should work today with the generic OTLP backend — first-class docs, docker-compose files, and smoke tests are on the roadmap:
File an issue if you've tried one of these and hit friction — we'll prioritise.