Skip to main content

Config schema

Every key of the plugin's config file. The plugin reads the first file it finds: the path in HERMES_OTEL_CONFIG, then ~/.hermes/hermes_otel.yaml, then the legacy ~/.hermes/plugins/hermes_otel/config.yaml (which a reinstall deletes). See config.yaml for a guided tour.

The field table below is generated from HermesOtelConfig by scripts/gen_config_docs.py, and a test fails if it drifts from the code.

A numeric field's Bounds are checked at load (#487). A value outside them, in the yaml or an env override, logs a warning naming the field, and the default is used instead. An export batch size larger than its queue size is lowered to the queue size. (Before 1.30.1 such a value reached the OpenTelemetry SDK, which raised during startup, so every backend logged traces init failed and nothing was exported.)

Top level​

FieldTypeDefaultDescription
enabledbooltrueMaster switch; false registers no hooks and exports nothing
sample_ratefloat | nullnullParent-based trace-ID ratio 0.0–1.0; null = AlwaysOn (no sampling). Bounds: 0.0–1.0
root_span_ttl_msint600000Orphan-sweep TTL: a turn root older than this with no end hook is closed. Bounds: ≥ 1
subagent_span_ttl_msint86400000Delegation-span TTL: a subagent.* span whose subagent_stop never arrives is closed after this (it outlives the parent's turn by design). Bounds: ≥ 1
flush_interval_msint60000Metrics export cadence (PeriodicExportingMetricReader). Bounds: ≥ 1
preview_max_charsint1200Cap on preview strings (tool args/results, user message, assistant response). Bounds: ≥ 1
capture_previewsbooltrueDeprecated spelling of content_capture: off (when false); kept consistent with content_capture
tool_input_preview_max_charsint | nullnullPer-category cap for tool args previews; null = preview_max_chars. Bounds: ≥ 1
tool_output_preview_max_charsint | nullnullPer-category cap for tool result previews; null = preview_max_chars. Bounds: ≥ 1
llm_input_preview_max_charsint | nullnullPer-category cap for LLM input previews; null = preview_max_chars. Bounds: ≥ 1
llm_output_preview_max_charsint | nullnullPer-category cap for LLM output previews; null = preview_max_chars. Bounds: ≥ 1
headersmap(unset)Extra HTTP headers on every OTLP request; per-backend headers: are merged onto these
global_tagsmap(unset)Deprecated: merged into resource_attributes at load (which wins on a key conflict)
resource_attributesmap(unset)Merged into the Resource on top of the defaults service.name=hermes-agent, service.instance.id (per-process UUID), service.version, process.pid, hermes.profile
common_attributesmap(unset)Stamped on every span, log record and metric point (not the Resource), for backends that do not index resource attributes per signal; scalar values, keys of at most 64 chars outside hermes. / gen_ai. / service.. A plugin attribute of the same name wins; changing a value starts new metric series
project_namestring | null(unset)openinference.project.name on the Resource (Phoenix project); overrides OTEL_PROJECT_NAME
service_name_from_profileboolfalseA named profile exports as service.name=<profile> with service.namespace=hermes-agent; the default profile stays hermes-agent. resource_attributes.service.name still wins
span_batch_max_queue_sizeint2048Max buffered spans per backend before drops. Bounds: ≥ 1
span_batch_schedule_delay_msint1000BatchSpanProcessor worker wake-up cadence. Bounds: ≥ 1
span_batch_max_export_batch_sizeint | nullnullMax spans per OTLP POST; null = 512, or 64 when content_capture is full. Bounds: ≥ 1
span_batch_export_timeout_msint30000Per-export HTTP timeout. Bounds: ≥ 1
force_flush_on_session_endbooltrueFlush every backend's span queue at the end of each turn, from a background thread (500 ms per backend, coalesced)
force_flush_wait_msint1500How long the turn waits for that background flush (spans, then metrics and logs on a second thread) before returning to Hermes; a one-shot run exits right after, so this bounds what it exports; 0 = do not wait. Bounds: ≥ 0
capture_conversation_historyboolfalseAttach the full message JSON to llm.* spans
conversation_history_max_charsint20000JSON cap when conversation capture is on. Bounds: ≥ 1
content_capturestring"full"full (default): complete prompt and response on every api.* span · preview: clipped previews only · off: no content, metadata only; see Conversation capture
capture_full_promptsbooltrueDeprecated: derived from content_capture; false keeps prompts as previews in full mode
capture_full_responsesbooltrueDeprecated: derived from content_capture; false keeps responses as previews in full mode
capture_sender_idboolfalseGateway sessions add hermes.sender.id and user.id (platform:sender)
capture_logsboolfalseAttach an OTel LoggingHandler to Python logging; see OTel logs
log_levelstring"INFO"Handler level: DEBUG / INFO / WARNING / ERROR / CRITICAL
log_attach_loggerstring | null(unset)Logger to attach to; null = root, hermes_otel = the plugin only
log_exclude_loggerslist of strings (env: comma-separated)[opentelemetry, urllib3, httpx, httpcore, requests, openai, asyncio, hpack, grpc, websockets, charset_normalizer, markdown_it]Logger-name prefixes never forwarded (loop guard + Hermes' noisy third-party loggers); logs.exclude_loggers
log_logger_levelsmap(unset)Per-logger minimum level, e.g. {gateway.config: WARNING}; logs.logger_levels
log_only_in_turnboolfalseDrop records the plugin cannot attribute to a session; logs.only_in_turn
log_max_attribute_lengthint4096Longest exported string attribute on a log record (characters); logs.max_attribute_length. Bounds: ≥ 1
log_batch_schedule_delay_msint1000Log batch processor: export every N ms; logs.batch.schedule_delay_ms. Bounds: ≥ 1
log_batch_max_queue_sizeint2048Log batch processor: queued records before drops; logs.batch.max_queue_size. Bounds: ≥ 1
log_batch_max_export_batch_sizeint512Log batch processor: records per export request; logs.batch.max_export_batch_size. Bounds: ≥ 1
log_batch_export_timeout_msint30000Log batch processor: per-export timeout; logs.batch.export_timeout_ms. Bounds: ≥ 1
log_live_min_levelstring"INFO"Floor for the dashboard's live Logs tab (INFO default; the OTLP path keeps log_level); logs.live_min_level
log_eventsboolfalseEmit structured hermes.* / GenAI events (log records with an event name) from the hooks; logs.events.enabled
log_events_contentstring"inherit"Content on events: inherit (follow content_capture) / full / preview / off; logs.events.content
emit_genai_metricsbooltrueAlso emit the OTel GenAI spec metrics (gen_ai.client.*, gen_ai.agent.*)
metrics_temporalitystring | null(unset)Metric temporality for OTLP export: cumulative (Prometheus family) or delta (Datadog, New Relic, Logfire); unset = SDK default; a backend entry's own value wins
metrics_histogramstring"explicit"Histogram aggregation: explicit (spec bucket boundaries) or exponential (base-2, for backends that accept it)
metrics_label_limitint100Distinct values a metric label such as model may take per process before the rest fold into other (0 = no cap). Bounds: ≥ 0
metric_name_compatstring"off"off · claude_code · both — export session count, token usage, cost and active time under Claude Code's metric names, units and labels (claude_code.*) instead of (claude_code) or beside (both) the hermes.* twins, so dashboards built for Claude Code read Hermes; see Claude Code dashboards
metric_name_compat_session_idboolfalseAlso put session.id on the claude_code.* instruments, as Claude Code does by default (per-session panels need it; one series per session)
disable_metricslist of strings (env: comma-separated)[]Instruments never created, recorded or exported: hook keys (tool_duration), dotted (tool.duration) or OTLP names (hermes.tool.duration), or all; an unknown name warns at load. See Disabling metrics and span families
disable_spanslist of strings (env: comma-separated)[]Span families never recorded (tool, api, llm, approval, skill, subagent, kanban, auxiliary, human_input); a child of a disabled span parents to the nearest recording ancestor. all is refused (use a backend's traces: false)
skill_spansbooltrueOpen a skill.<name> span on each successful skill load, closed at turn end
remote_parentbooltrueParent the turn root under the span named by HERMES_OTEL_TRACEPARENT (+ HERMES_OTEL_TRACESTATE) when an outer process exported them; false ignores the variables. The kanban worker hand-off (TRACEPARENT) is separate
probe_backendsbooltrueAt init, open one TCP connection to each backend endpoint on a background thread and log reachable / unreachable per backend; once, never periodic, no bytes sent, exports never wait for it
discovery_promptboolfalseRegister a system-prompt section advertising hermes_otel:observability (changes what the model sees every turn; opt-in)
dashboard_livebooltrueKeep recent spans/metrics/logs in $HERMES_HOME/hermes_otel_live.db for the dashboard's Live mode
dashboard_live_max_spansint1000Rows kept per kind (spans, metrics, logs) in the live store. Bounds: ≥ 1
dashboard_live_retention_hoursfloat168.0Rows older than this are dropped from the live store (0 = only the row cap applies). Bounds: ≥ 0.0
host_metricsboolfalseSample CPU/GPU and emit process.* / system.* / hw.* metrics; see Host & GPU metrics
host_metrics_gpustring"auto"auto · amd · nvidia · off — which GPU SDK to probe
host_metrics_interval_msint1000Host sampling cadence (floor 50 ms). Bounds: ≥ 1
suppress_mcp_ping_spansbooltrueDrop successful MCP keepalive ping spans before export
backendslist(unset)Multi-backend fan-out list; see the backends[] section

When backends: holds at least one usable entry, single-backend env-var detection is skipped. If every entry is dropped while loading (an entry with no type, for example), env-var detection runs after all.

backends[] entries​

Shared fields (all optional unless noted):

FieldTypeDescription
typestringRequired. One of: phoenix, langfuse, signoz, jaeger, zipkin, greptime, clickstack, victoria, aspire, gigapipe, agenta, tempo, otlp, lgtm, uptrace, openobserve, parseable, honeycomb, weave, langsmith, elastic, openlit, mlflow, opik, laminar, langwatch, latitude (see backends). Aliases: hyperdx (clickstack), victoriatraces (victoria), qryn (gigapipe), openobserver (openobserve)
namestringFriendly name shown in logs (default: type)
endpointstringFull HTTP traces URL, or gRPC host:port / https://host:port origin (no signal path). Required, either here or in the type's OTEL_<TYPE>_ENDPOINT variable, except for the types that have a default: langfuse and weave (built from base_url), honeycomb, agenta and langsmith (built from region), and opik, laminar, langwatch and latitude (their cloud hosts)
metrics_endpoint, logs_endpointstringThe full URL (gRPC: the target) for that signal, used as written instead of the one derived from endpoint; victoria reads them as its store origins (below)
protocolstringhttp/protobuf (default), or grpc for a generic type: otlp entry. Applies to traces, metrics and logs; headers_helper needs http/protobuf
insecureboolgRPC only: true selects plaintext, false forces TLS. Unset: SDK INSECURE env vars, then the endpoint scheme (http is plaintext; HTTPS / bare targets are TLS). HTTPS cannot be combined with true
certificate_filestringPEM CA bundle for server verification; unset uses SDK CERTIFICATE env vars or system trust
client_certificate_filestringPEM client certificate chain for mTLS; gRPC requires client_key_file too
client_key_filestringPEM client private key for mTLS; requires client_certificate_file
ui_urlstringWhere the backend's web UI is, for the dashboard's Settings tab to link its card to. Optional. Without it the tab works the link out from the type: the endpoint origin for types whose UI is served there, query_port for Jaeger and SigNoz, the known SaaS UI for Honeycomb, W&B Weave and LangSmith, and no link for otlp and elastic. It never guesses a port
tracesboolOverride trace-export default (true). Set false for dashboard/query-only backends that should not receive span exports. trace is accepted as an alias.
metricsboolOverride metrics-export default for this backend
metrics_temporalitystringcumulative or delta for this backend's metric reader; overrides the top-level default and the type preset (signoz, uptrace, elastic → delta)
root_usageboolSend the turn's token roll-up (gen_ai.usage.* / llm.token_count.* on the agent / cron root) to this backend. Preset false for opik and langwatch, which sum usage over every span and would double the trace total (#327); true everywhere else. Only this entry's exporter is affected: the span is rebuilt without those keys on its way out, the api.* spans and hermes.cost.* stay
logsbool or mapOverride the logs-export default. On for signoz, greptime, clickstack, victoria (with logs_endpoint), aspire, gigapipe, uptrace, openobserve, parseable, honeycomb, elastic, openlit, laminar, langwatch, lgtm and otlp; off for the rest. A mapping (level, exclude_loggers, logger_levels, only_in_turn, events) turns logs on with per-backend overrides
headersmapPer-backend HTTP headers / gRPC metadata (merged onto top-level headers; gRPC names are lowercased)
headers_helperstringA command (argv string, no shell) whose stdout, a JSON object or Name=value lines, mints headers merged over headers and the type's own auth header on every signal of this entry; on a 401/403 it is re-run once and the batch retried once (short-lived credentials, #483)
headers_helper_timeout_msintHow long one helper run may take; default 5000

TLS paths support ~ and ${VAR_NAME}. Explicit paths override signal-specific SDK environment variables, then global variables. Invalid files or TLS credentials on a plaintext endpoint are rejected. See gRPC and TLS for examples, environment variables and certificate rotation.

Type-specific fields​

Keys marked "Dashboard read path" are read only by the dashboard tab and the query tool, never by the exporter. Where a service_name defaults to the plugin's resource_attributes.service.name, else hermes-agent, the named profile comes in between when service_name_from_profile: true.

phoenix​

FieldTypeDescription
endpointstringRequired. e.g. http://localhost:6006/v1/traces. Traces only (Phoenix rejects /v1/metrics)

langfuse​

FieldTypeDescription
public_keystringLangfuse public key (inline; discouraged)
public_key_envstringEnv var name holding the public key
secret_keystringLangfuse secret key (inline; discouraged)
secret_key_envstringEnv var name holding the secret key
base_urlstringLangfuse base URL; the plugin appends /api/public/otel/v1/traces. Default: LANGFUSE_BASE_URL, else https://cloud.langfuse.com
query_apistringDashboard read path: v3 (trace endpoints), v4 (events_only: v2 observations + v2 metrics), or auto (default: probed once per query URL)
endpointstringOverride; skips base_url construction

Both keys are required (an entry with one is skipped with a warning). The plugin builds the Basic Auth header from them.

signoz​

FieldTypeDescription
endpointstringOTLP endpoint (self-host: http://localhost:4328/v1/traces; cloud: https://ingest.<region>.signoz.cloud:443/v1/traces)
ingestion_keystringSigNoz Cloud ingestion key (inline; discouraged)
ingestion_key_envstringEnv var name holding the ingestion key
query_portintDashboard read path: the SigNoz UI/API port (default 3301; 443 behind an HTTPS ingress)
api_key / api_key_envstringDashboard read path: a SigNoz API key, sent as SIGNOZ-API-KEY (current SigNoz issues them from a service account). Ingestion never needs it

When an ingestion key is set, the plugin adds the signoz-ingestion-key header.

jaeger​

FieldTypeDescription
endpointstringRequired. e.g. http://localhost:4318/v1/traces. Traces only (metrics/logs off)
query_portintDashboard read path: the Jaeger UI/query port. Default: the endpoint's own port, else 16686, so with an OTLP endpoint on 4318 set this to 16686
query_apistringDashboard read path: v1 (classic /api/traces), v3 (Jaeger v2's /api/v3), or auto (default: probed once per query URL)
service_namestringDashboard read path: the service every search names (default: the plugin's resource_attributes.service.name, else hermes-agent)

zipkin​

FieldTypeDescription
endpointstringRequired. The Zipkin origin, e.g. http://localhost:9411 (a /v1/traces suffix is added; /v1/metrics or /v1/logs is rewritten). Also via OTEL_ZIPKIN_ENDPOINT. Traces only (metrics/logs off). Needs the zipkin-otel image: stock Zipkin has no OTLP endpoint
query_portintDashboard read path: the port serving API v2 and the UI (default: the endpoint's port, else 9411)
service_namestringDashboard read path: the service every search names (default: the plugin's resource_attributes.service.name, else hermes-agent)
api_key / api_key_envstringDashboard read path: a bearer token for an authenticating proxy in front of Zipkin; none upstream

See Zipkin.

greptime​

FieldTypeDescription
endpointstringRequired. The GreptimeDB HTTP origin, e.g. http://localhost:4398 (bundled stack) or http://<host>:4000; a /v1/otlp prefix or any /v1/otlp/v1/<signal> URL also works. Also via OTEL_GREPTIME_ENDPOINT. Traces carry X-Greptime-Pipeline-Name: greptime_trace_v1; metrics and logs do not
db / db_envstringOptional database (X-Greptime-DB-Name on every signal; fallback OTEL_GREPTIME_DB; server default public)
user / user_env, password / password_envstringOptional Basic auth for a server with a user provider (fallbacks OTEL_GREPTIME_USER / OTEL_GREPTIME_PASSWORD); omitted when either is missing
metrics / logs / tracesboolPer-signal toggles; all three default on
query_portintDashboard read path: the HTTP port (default: the endpoint's port, else 4000)
query_pathstringDashboard read path: where the Jaeger-compatible API hangs (default /v1/jaeger)
search_fetchintDashboard read path: traces asked for per search before the page is cut here (default 500; GreptimeDB's limit keeps arbitrary traces, not the newest)
logs_tablestringDashboard read path: the OTLP logs table (default opentelemetry_logs)
metrics_matchstringDashboard read path: a PromQL series selector narrowing the metric list (default: the plugin's namespaces)
service_namestringDashboard read path: the service every trace search names (default: the plugin's resource_attributes.service.name, else hermes-agent)

See GreptimeDB.

clickstack​

FieldTypeDescription
endpointstringRequired. The ClickStack Collector's OTLP/HTTP base, e.g. http://localhost:4408 (bundled stack) or http://<host>:4318. Also via OTEL_CLICKSTACK_ENDPOINT. A base URL gets /v1/traces; the other two signals are derived
api_key / api_key_envstringRequired. The team's ingestion API key, sent as a bare authorization: <key> header (fallbacks OTEL_CLICKSTACK_API_KEY, HYPERDX_API_KEY); a missing key skips the entry
metrics / logs / tracesboolPer-signal toggles; all three default on
query_portintDashboard read path: the ClickHouse HTTP port (default 8123; 8124 on the bundled stack)
user / user_env, password / password_envstringDashboard read path: ClickHouse credentials (api / api on the all-in-one image; its default user only answers from inside the container)
databasestringDashboard read path: the ClickHouse database (default default)
traces_table, logs_tablestringDashboard read path: table names (defaults otel_traces, otel_logs)
metrics_matchstringDashboard read path: a regular expression on metric names (default: the plugin's namespaces)
ui_urlstringDashboard read path: the HyperDX UI origin for the "open in" search link
service_namestringDashboard read path: the service every trace search names (default: the plugin's resource_attributes.service.name, else hermes-agent)

See ClickStack.

victoria​

FieldTypeDescription
endpointstringRequired. VictoriaTraces origin or ingest URL (http://localhost:10428 → /insert/opentelemetry/v1/traces). Also via OTEL_VICTORIA_ENDPOINT
metrics_endpointstringVictoriaMetrics origin or ingest URL (http://localhost:8428 → /opentelemetry/v1/metrics); metrics are off without it. Also via OTEL_VICTORIA_METRICS_ENDPOINT
logs_endpointstringVictoriaLogs origin or ingest URL (http://localhost:9428 → /insert/opentelemetry/v1/logs); logs are off without it. Also via OTEL_VICTORIA_LOGS_ENDPOINT
user / user_env, password / password_envstringOptional Basic auth sent to all three stores (fallbacks OTEL_VICTORIA_USER / OTEL_VICTORIA_PASSWORD)
headersmapExtra headers on every signal; a VL-Stream-Fields entry replaces the default service.name the type sends on logs
metrics / logs / tracesboolPer-signal toggles; an explicit metrics: true / logs: true needs the matching store named, else the entry is skipped with a hint
prometheus_url, logs_urlstringDashboard read path: the VictoriaMetrics and VictoriaLogs origins (default: metrics_endpoint / logs_endpoint)
query_port, query_path, search_fetchint / string / intDashboard read path: VictoriaTraces' port (default the endpoint's, else 10428), the Jaeger-compatible API prefix (default /select/jaeger) and the traces fetched per search before the page is cut (default 500)
metrics_match, service_namestringDashboard read path: a PromQL series selector for the metric list; the service every trace search names

See VictoriaMetrics family.

aspire​

FieldTypeDescription
endpointstringRequired. The Aspire Dashboard's OTLP/HTTP base, e.g. http://localhost:4418 (bundled stack) or http://<host>:18890. Also via OTEL_ASPIRE_ENDPOINT. A base URL gets /v1/traces; the other two signals are derived
api_key / api_key_envstringOptional OTLP API key → x-otlp-api-key (fallback OTEL_ASPIRE_API_KEY); only with DASHBOARD__OTLP__AUTHMODE=ApiKey. The dashboard adapter sends the same value as x-api-key
metrics / logs / tracesboolPer-signal toggles; all three default on
query_portintDashboard read path: the UI port serving /api/telemetry/* (default 18888)
ui_urlstringDashboard read path: the UI origin for the /traces/detail/{traceId} link (default: the query URL)
search_fetch, logs_fetchintDashboard read path: traces and log records fetched per query before the window and filters are applied client-side (defaults 500, 5000)
service_namestringDashboard read path: the service whose Aspire resources (one per Hermes process, resolved through /api/telemetry/resources) the API is asked for (default: the plugin's resource_attributes.service.name, else hermes-agent)

See Aspire Dashboard.

gigapipe​

FieldTypeDescription
endpointstringRequired. Gigapipe's origin, e.g. http://localhost:3110 (bundled stack) or http://<host>:3100; a base URL gets /v1/traces, the other two signals are derived. Also via OTEL_GIGAPIPE_ENDPOINT
user / user_env, password / password_envstringOptional Basic auth (fallbacks OTEL_GIGAPIPE_USER / OTEL_GIGAPIPE_PASSWORD); omitted when either is missing
metrics / logs / tracesboolPer-signal toggles; all three default on
query_port, prometheus_url, loki_urlint / stringDashboard read path: all default to the endpoint's origin (one port serves the Tempo, Prometheus and Loki APIs); loki_url: off disables the Logs tab
search_fetch, metrics_match, loki_selector, ui_urlas for lgtmDashboard read path

See Gigapipe.

agenta​

FieldTypeDescription
endpointstringAgenta's origin for a self-hosted stack, e.g. http://localhost:3060 (an origin, /api, /api/otlp or the full /api/otlp/v1/traces URL). Also via OTEL_AGENTA_ENDPOINT / AGENTA_HOST. Unset: Agenta Cloud for region
regionstringus (default) or eu: the cloud host when endpoint is unset
api_key / api_key_envstringRequired. A project API key → Authorization: ApiKey <key> (fallbacks OTEL_AGENTA_API_KEY, AGENTA_API_KEY); a missing key skips the entry. The dashboard adapter reads with the same key
metrics / logs / tracesboolPer-signal toggles; metrics and logs default off (Agenta mounts only the traces route)
ui_urlstringDashboard read path: the project's observability page for an "open in" link (the adapter cannot derive the workspace and project ids)
service_namestringDashboard read path: the service shown on cards and in the detail's resource (Agenta stores no resource attributes)

See Agenta.

tempo​

FieldTypeDescription
endpointstringRequired. Traces only (metrics/logs off); use type: lgtm for the all-in-one Grafana container
query_portintDashboard read path: Tempo's query API port (default 3200)
prometheus_url / loki_urlstringOptional. Naming them gives a Tempo entry the same dashboard metrics/logs as lgtm
search_fetchintDashboard read path: traces asked of Tempo per search page before the newest limit are kept (default 500; Tempo's own limit is not newest-first). Also on lgtm entries

otlp​

FieldTypeDescription
endpointstringRequired. OTLP traces endpoint
metricsboolDefault: true; set false for traces-only collectors
logsboolDefault: true; set false if the collector doesn't accept /v1/logs

Use headers: for auth (${VAR} interpolation supported).

lgtm​

Alias over otlp with a dedicated display name and all signals on by default. See Grafana LGTM.

FieldTypeDescription
endpointstringRequired. OTLP traces endpoint — http://localhost:4318/v1/traces for the bundled docker-compose/lgtm/docker-compose.yaml
metricsboolDefault: true
logsboolDefault: true
query_portintDashboard read path: Tempo's query API port (default 3200)
prometheus_urlstringDashboard metrics. Default: port 9090 on the Tempo host (the otel-lgtm layout); off disables
loki_urlstringDashboard logs. Default: port 3100 on the Tempo host; off disables (e.g. a Loki without OTLP)
metrics_matchstringOptional Prometheus series selector for the instrument list, e.g. {__name__=~"hermes_.*"} on a shared Prometheus
loki_selectorstringOptional LogQL stream selector the log filters are applied to (default {service_name=~".+"})

Use type: lgtm (not type: tempo) when pointing at the grafana/otel-lgtm container — tempo is traces-only and would disable the logs/metrics fan-out.

uptrace​

FieldTypeDescription
endpointstringRequired. OTLP traces endpoint (self-host: http://localhost:14318/v1/traces). Also via OTEL_UPTRACE_ENDPOINT
dsnstringUptrace DSN, sent as the uptrace-dsn header on every export (inline; discouraged)
dsn_envstringEnv var name holding the DSN (falls back to OTEL_UPTRACE_DSN / UPTRACE_DSN)
query_portintDashboard read path: the Uptrace UI/API port (default 14318; 443 behind an HTTPS ingress)
user_token / user_token_envstringDashboard read path: an Uptrace user token (Settings → API tokens); falls back to UPTRACE_USER_TOKEN. The DSN's project token only ingests
project_idintDashboard read path: the Uptrace project to query (default 1)

All three signals on by default. See Uptrace.

openobserve​

FieldTypeDescription
endpointstringRequired. http://<host>:5080/api/<org>/v1/traces, or the bare origin http://<host>:5080, which the plugin completes with org. Also via OTEL_OPENOBSERVE_ENDPOINT
user / user_envstringBasic-auth user (falls back to OTEL_OPENOBSERVE_USER / OPENOBSERVE_USER)
password / password_envstringBasic-auth password (falls back to OTEL_OPENOBSERVE_PASSWORD / OPENOBSERVE_PASSWORD)
stream_namestringOptional stream name (OTEL_OPENOBSERVE_STREAM)
orgstringOrg that completes a bare-origin endpoint (OTEL_OPENOBSERVE_ORG, default default); ignored when endpoint has a path. The dashboard also reads it

All three signals on by default. See OpenObserve.

parseable​

FieldTypeDescription
endpointstringRequired. Parseable ingestor OTLP traces endpoint, ending in /v1/traces
api_keystringParseable API key (inline; discouraged)
api_key_envstringEnv var holding the key (falls back to OTEL_PARSEABLE_API_KEY, then PARSEABLE_API_KEY). The key is required and is sent as X-API-Key
traces_datasetstringTraces dataset (default: hermes-traces)
metrics_datasetstringMetrics dataset (default: hermes-metrics)
logs_datasetstringLogs dataset (default: hermes-logs)

The plugin supplies signal-specific X-P-Stream and X-P-Log-Source headers automatically. See Parseable.

honeycomb​

FieldTypeDescription
api_keystringHoneycomb ingest key (inline; discouraged)
api_key_envstringEnv var name holding the key (falls back to OTEL_HONEYCOMB_API_KEY / HONEYCOMB_API_KEY)
regionstringus (default) or eu; selects the endpoint when none is given
datasetstringOptional x-honeycomb-dataset header. Only honored by Classic keys — modern Environments keys ignore it
endpointstringOverride; skips the region default. Also via OTEL_HONEYCOMB_ENDPOINT

The plugin sets x-honeycomb-team from the key automatically and enables all three signals. See Honeycomb for dataset routing details.

weave​

FieldTypeDescription
api_keystringW&B API key (inline; discouraged)
api_key_envstringEnv var name holding the key (falls back to OTEL_WEAVE_API_KEY / WANDB_API_KEY)
entitystringW&B entity/team; copied to Resource attribute wandb.entity
entity_envstringEnv var name holding the entity (falls back to WANDB_ENTITY / DEFAULT_WANDB_ENTITY)
projectstringW&B project; copied to Resource attribute wandb.project
project_envstringEnv var name holding the project (falls back to WANDB_PROJECT / DEFAULT_WANDB_PROJECT)
base_urlstringW&B base URL. Cloud default is https://trace.wandb.ai; Dedicated Cloud / Self-Managed hosts such as https://acme.wandb.io get /traces/otel/v1/traces appended
endpointstringOverride; skips base_url construction. Also via OTEL_WEAVE_ENDPOINT / WANDB_OTLP_ENDPOINT

The plugin sets the wandb-api-key header automatically. Weave is traces-only by default; set metrics: true / logs: true only if W&B documents ingest for those signals or you are pointing at a compatible collector. wandb.entity and wandb.project may also be supplied via top-level resource_attributes; conflicting values fail startup.

langsmith​

FieldTypeDescription
api_key / api_key_envstringRequired. LangSmith API key, sent as x-api-key (falls back to OTEL_LANGSMITH_API_KEY / LANGSMITH_API_KEY)
project / project_envstringOptional project, sent as the Langsmith-Project header (falls back to OTEL_LANGSMITH_PROJECT / LANGSMITH_PROJECT)
regionstringus (default) or eu; picks the host when endpoint is unset
endpointstringOverride. An API base gets /otel/v1/traces appended. Also via OTEL_LANGSMITH_ENDPOINT / LANGSMITH_ENDPOINT

Traces only. See LangSmith.

elastic​

FieldTypeDescription
endpointstringRequired. Elastic Cloud managed OTLP URL (https://<deployment>.ingest.<region>.<csp>.elastic.cloud) or a self-hosted EDOT Collector's OTLP/HTTP base. Also via OTEL_ELASTIC_ENDPOINT. A base URL gets /v1/traces appended; /v1/metrics and /v1/logs are derived from it
api_keystringElastic API key (inline; discouraged). Sent as Authorization: ApiKey <key>; the header is omitted entirely when no key resolves (a local collector)
api_key_envstringEnv var name holding the key (falls back to OTEL_ELASTIC_API_KEY / ELASTIC_API_KEY)
datasetstringOptional; copied to the data_stream.dataset Resource attribute. Lowercase letters, digits, _ and ., no -, at most 100 characters. The collector appends .otel
namespacestringOptional; copied to the data_stream.namespace Resource attribute, same character rules
metrics_temporalitystringPreset delta for this type (Elasticsearch does not take cumulative histograms); cumulative overrides

An invalid dataset / namespace skips the entry at startup with a warning rather than failing the agent. Both attributes are set on the shared Resource, so every configured backend receives them; two elastic entries with different values conflict at startup. See Elastic.

openlit​

FieldTypeDescription
endpointstringRequired. The OpenLIT OTLP/HTTP receiver base: http://localhost:4338 for the bundled stack, http://<host>:4318 upstream (the UI port does not proxy OTLP on the 2.1.0 image). Also via OTEL_OPENLIT_ENDPOINT. A base URL gets /v1/traces appended; /v1/metrics and /v1/logs are derived from it
api_keystringOpenLIT API key (inline; discouraged). Sent as Authorization: Bearer <key> to scope ingest to an organisation, project and environment; the header is omitted when no key resolves
api_key_envstringEnv var name holding the key (falls back to OTEL_OPENLIT_API_KEY / OPENLIT_API_KEY)
metrics / logs / tracesboolPer-signal toggles; all three default on

See OpenLIT.

mlflow​

FieldTypeDescription
endpointstringRequired. MLflow tracking server (http://localhost:5001 for the bundled stack, http://<host>:5000 upstream). Also via OTEL_MLFLOW_ENDPOINT. A base URL gets /v1/traces appended
experiment_idstringExperiment that receives the traces, sent as the mandatory x-mlflow-experiment-id header. Default 0 (the built-in Default experiment)
experiment_id_envstringEnv var name holding the experiment id (falls back to OTEL_MLFLOW_EXPERIMENT_ID / MLFLOW_EXPERIMENT_ID)
workspacestringOptional; sent as X-MLFLOW-WORKSPACE
api_key / api_key_envstringOptional tracking token, sent as Authorization: Bearer <token> (falls back to OTEL_MLFLOW_API_KEY / MLFLOW_TRACKING_TOKEN)
metrics / logsboolDefault off: the server has no /v1/metrics or /v1/logs route (404)

See MLflow.

opik​

FieldTypeDescription
endpointstringOpik base URL: http://localhost:5173 for the bundled stack, or a full …/api/v1/private/otel/v1/traces URL. Default https://www.comet.com/opik (Comet cloud). Also via OTEL_OPIK_ENDPOINT or the SDK's OPIK_URL_OVERRIDE
api_key / api_key_envstringComet API key, sent as a bare Authorization: <key> header (Opik's scheme; falls back to OTEL_OPIK_API_KEY / OPIK_API_KEY). Not needed on a self-hosted deployment
workspacestringComet workspace → Comet-Workspace header (cloud; falls back to OPIK_WORKSPACE)
project / project_envstringOpik project → projectName header (falls back to OPIK_PROJECT_NAME; Opik uses "Default Project" when absent)
metrics / logsboolDefault off: only /traces exists under the OTLP prefix

See Comet Opik.

laminar​

FieldTypeDescription
endpointstringLaminar app-server base: http://localhost:8100 for the bundled stack (upstream publishes 8000; the frontend port 5667 does not ingest). Default https://api.lmnr.ai (Laminar cloud). Also via OTEL_LAMINAR_ENDPOINT / LMNR_BASE_URL
api_key / api_key_envstringRequired. Project API key, sent as Authorization: Bearer <key> (falls back to OTEL_LAMINAR_API_KEY / LMNR_PROJECT_API_KEY). The key names the project
metricsboolDefault off: /v1/metrics answers 200 and stores nothing. true only with a collector in front
logsboolDefault on (log records are stored)

See Laminar.

langwatch​

FieldTypeDescription
endpointstringLangWatch base: http://localhost:5560 for the bundled stack, or the /api/otel prefix, or a full per-signal URL. Default https://app.langwatch.ai. Also via OTEL_LANGWATCH_ENDPOINT / LANGWATCH_ENDPOINT
api_key / api_key_envstringRequired. Project API key (sk-lw-…), sent as Authorization: Bearer <key> (falls back to OTEL_LANGWATCH_API_KEY / LANGWATCH_API_KEY)
project / project_envstringOptional project id → X-Project-Id, needed only with a service key (falls back to LANGWATCH_PROJECT_ID)
metrics / logs / tracesboolAll three default on; the plugin derives /api/otel/v1/metrics and /api/otel/v1/logs from the traces URL

See LangWatch.

latitude​

FieldTypeDescription
endpointstringLatitude ingest base: http://localhost:3002 for the bundled stack. Default https://ingest.latitude.so (Latitude cloud). Also via OTEL_LATITUDE_ENDPOINT / LATITUDE_INGEST_URL. A base URL gets /v1/traces appended
api_key / api_key_envstringRequired. API key, sent as Authorization: Bearer <key> (falls back to OTEL_LATITUDE_API_KEY / LATITUDE_API_KEY)
project / project_envstringRequired. Project slug for the mandatory X-Latitude-Project header (falls back to LATITUDE_PROJECT); spans without a project are rejected
metrics / logsboolDefault off: the ingest service has only /v1/traces

See Latitude.

Env var interpolation in headers:​

Inside any headers: value, and any other export field of a backends: entry such as api_key, dsn, password or endpoint, ${VAR_NAME} is replaced with the env var's value when the config is loaded:

headers:
Authorization: "Bearer ${OTEL_AUTH_TOKEN}"
x-honeycomb-team: ${HONEYCOMB_API_KEY}

A missing env var logs a startup warning and the literal ${VAR} is sent (which fails auth, but visibly so).

Header names are not expanded. The dashboard expands ${VAR} in each backend entry the same way before it queries the backend, so a credential written as ${VAR} works for both exporting and reading back.

Precedence​

For every field, precedence (highest → lowest) is:

  1. HERMES_OTEL_* env var (if applicable — see Env var reference)
  2. config.yaml value
  3. Built-in default

Validation​

On startup the plugin validates the config and:

  • Logs a warning naming the key and keeps the default for a value that cannot be parsed as the field's type (yaml or HERMES_OTEL_* env var)
  • Logs a single warning and uses an empty config if the YAML fails to parse
  • Logs a warning and ignores the file if it exists but pyyaml is not installed in the Hermes venv
  • Logs a warning and skips a backends: entry it cannot resolve (missing endpoint, unknown type)

The plugin never crashes Hermes because of config — at worst it disables itself with a clear log line.