Skip to main content

latitude-telemetry-hermes

Stream Hermes Agent (Nous Research's open-source agent harness) sessions to Latitude as OTLP traces — user prompts, model turns, tool calls and results, the tools the agent was offered, memory reads and writes, delegated subagents, token usage, cost and timing, and the real system prompt — so you get full-fidelity observability of your agent runs in Latitude.

This is the Hermes counterpart to the other harness integrations (@latitude-data/claude-code-telemetry, @latitude-data/pi-telemetry, @latitude-data/openclaw-telemetry). Hermes is a Python harness and loads plugins from Python, so this connector ships as a pip package rather than npm.

Install

pip install latitude-telemetry-hermes

Then enable the plugin by adding latitude to ~/.hermes/config.yaml, plus Hermes's reasoning-delta forwarding so time-to-first-token is measurable:

plugins:
  enabled:
    - latitude
  stream_reasoning_deltas: true

stream_reasoning_deltas: true is required for TTFT. It is Hermes's own setting, off by default. Hermes streams a turn's visible text through a path that does not notify plugins when the turn ends in a tool call — most turns, for a coding agent — so reasoning deltas are the only ones a plugin reliably sees, and they are not forwarded until this is on. With it on, TTFT landed on 51 of 53 model calls in our dogfood session.

Hermes discovers the plugin through the hermes_agent.plugins entry point — there are no files to copy.

Enable via config.yaml, not hermes plugins enable latitude. Hermes's runtime loads pip/entry-point plugins, but its hermes plugins list/enable/disable commands scan only bundled and ~/.hermes/plugins/ directory plugins — so they report a pip-installed plugin as "not installed or bundled" even though it loads fine (hermes-agent#23802). The config.yaml entry above is the reliable way to turn it on.

Plugin not loading at all? It must be installed into the same Python that runs Hermes. The official installer puts Hermes in its own venv (~/.hermes/hermes-agent/venv) that ignores your shell's Python — so a plain pip install from another interpreter (system, pyenv, mise, …) won't be discovered. Install into Hermes's venv instead:

~/.hermes/bin/uv pip install --python ~/.hermes/hermes-agent/venv/bin/python latitude-telemetry-hermes

Set your credentials in the environment (or in ~/.hermes/.env, which Hermes loads at startup):

export LATITUDE_API_KEY=lat_xxx
export LATITUDE_PROJECT=my-project

That's it — every session is now streamed to Latitude as OTLP traces. To export structure and timing without prompt/response/tool content, set LATITUDE_NO_CONTENT=true. Secret redaction is on by default: content passes through Hermes's own redactor on the way out, so a token echoed by a terminal tool is masked before it leaves the machine.

Self-hosted / local Latitude? The plugin defaults to Latitude Cloud (https://ingest.latitude.so). Point it at your own ingest by setting LATITUDE_BASE_URL to the ingest origin only — e.g. http://localhost:3002 for a local dev stack — without the /v1/traces suffix (the plugin appends it). Your LATITUDE_API_KEY and LATITUDE_PROJECT must come from that same instance.

How it works

Hermes loads pip-installed plugins via the hermes_agent.plugins entry point and calls the module's register(ctx) function, which subscribes to the lifecycle hooks — pre_api_request / post_api_request / api_request_error, pre_llm_call / post_llm_call, pre_tool_call / post_tool_call, on_stream_start / on_stream_delta / on_stream_end, on_session_start / on_session_end / on_session_reset / on_session_finalize, and subagent_start / subagent_stop. The *_api_request family is the LLM-call span boundary; the *_llm_call pair frames the turn; the stream hooks supply time-to-first-token; the session hooks bound the memory read and flush the exporter so short / one-shot runs (hermes -z "…") ship before the process exits.

The plugin owns the OTLP mapping for that hook stream. It assembles one trace per turn:

interaction (one user turn)
├── search_memory  (what the agent remembered coming in, once per session)
├── llm_request    (one per model call: model, tokens, cost, TTFT, system prompt, tool definitions)
├── tool_call:*    (one per tool call: arguments, result, success, duration)
│   └── upsert_memory  (a memory write, under the call that made it)
└── tool_call:delegate
    └── interaction    (a delegated subagent, nested under the call that spawned it)

Spans follow Latitude's GenAI semantic conventions (gen_ai.*), so they render natively in the Latitude trace viewer. Content-bearing attributes are tagged :gated and dropped before export when content capture is disabled. Spans are shipped as they finish, coalesced into batches under a size ceiling, and retried on transient ingest errors. The plugin is fail-open — a telemetry error never affects the agent — and depends only on the Python standard library (plus certifi, which Hermes already ships, for TLS verification).

Hermes internals are imported only for what no hook exposes (memory paths, the tool snapshot, the secret redactor, cost status), always guarded and always with a working fallback, so a Hermes upgrade degrades one attribute rather than the plugin.

Design notes, hook payload traps, the usage reconciliation and the full attribute tables live in dev-docs/hermes-telemetry.md.

Configuration

Every setting is readable from two places, the environment winning: the env var below, or plugins.entries.latitude.settings.<key> in the active profile's config.yaml. Both config.yaml and .env are profile-scoped, so one profile per agent gives each agent its own credentials, tags and metadata. The ~/.hermes/… paths here are the default profile's; a named profile keeps its own pair under ~/.hermes/profiles/<name>/.

# ~/.hermes/config.yaml
plugins:
  enabled: [latitude]
  entries:
    latitude:
      settings:
        api_key: lat_xxx
        project: my-project
        agent: { name: alescript, version: 2.1.0 }
        tags: [prod, eu-west]
        metadata: { deployment: staging }
Env config.yaml key Default Description
LATITUDE_API_KEY api_key API key (required)
LATITUDE_PROJECT / LATITUDE_PROJECT_SLUG project Project slug (required)
LATITUDE_BASE_URL base_url https://ingest.latitude.so Ingest origin (no path; the plugin appends /v1/traces)
LATITUDE_HERMES_TELEMETRY_ENABLED / LATITUDE_TELEMETRY_ENABLED enabled true Master switch
LATITUDE_DEBUG debug false Verbose logging, including each export's HTTP status
LATITUDE_HERMES_NO_CONTENT / LATITUDE_NO_CONTENT no_content false Structure and timing only
LATITUDE_HERMES_MAX_CONTENT_CHARS max_content_chars 262144 Per-attribute content budget; larger values are truncated from the middle
LATITUDE_HERMES_REDACT_SECRETS redact_secrets true Run exported content through Hermes's secret redactor
LATITUDE_HERMES_REDACT_ATTRIBUTES redact_attributes Attributes whose value never leaves the machine; the key is still sent, masked. Exact key or /regex/flags
LATITUDE_HERMES_REDACT_MASK redact_mask ****** Replacement for a redacted attribute value
LATITUDE_HERMES_MEMORY memory true Emit memory spans for the built-in stores
LATITUDE_HERMES_MEMORY_CONTENT memory_content true Include memory record bodies
LATITUDE_HERMES_TOOL_DEFINITIONS tool_definitions true Emit the tool definitions the agent was offered
LATITUDE_HERMES_STREAM_TTFT stream_ttft true Subscribe to stream deltas to measure TTFT
LATITUDE_HERMES_AUX_USAGE aux_usage true Recover the usage of Hermes's auxiliary model calls
LATITUDE_HERMES_AGENT_NAME agent.name profile name unless default Names the agent: a tag plus gen_ai.agent.name
LATITUDE_HERMES_AGENT_VERSION agent.version Adds the version as its own tag, plus version metadata
LATITUDE_HERMES_SERVICE_NAME service_name hermes-agent OTLP service.name — the Service breakdown/filter axis
LATITUDE_HERMES_TAGS / LATITUDE_TAGS tags Extra tags, comma-separated or a JSON array; appended to the derived ones
LATITUDE_HERMES_METADATA / LATITUDE_METADATA metadata Extra metadata, a JSON object or key=value pairs

Telemetry stays off until both an API key and a project are set.

Derived tags (hermes, the platform, the agent name, the agent version, cron:<job>, subagent:<role>) make several agents in one project distinguishable, and make comparing two versions of one agent a single analytics breakdown or a two-variant experiment. See the public docs for the recipe.

Development

uv sync
uv run pytest

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

latitude_telemetry_hermes-0.2.0.tar.gz (66.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

latitude_telemetry_hermes-0.2.0-py3-none-any.whl (43.2 kB view details)

Uploaded Python 3

File details

Details for the file latitude_telemetry_hermes-0.2.0.tar.gz.

File metadata

  • Download URL: latitude_telemetry_hermes-0.2.0.tar.gz
  • Upload date:
  • Size: 66.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for latitude_telemetry_hermes-0.2.0.tar.gz
Algorithm Hash digest
SHA256 4fdfb69e6bddd78e2bdf14575d1ac7771a84d398996f13f43029644b21e205c2
MD5 12eb06890f017cc7aeebfa9f434878fa
BLAKE2b-256 85284d967d450d2b82e2f5653963673dc92b3ee7d6caee4007cc631d7990f9f6

See more details on using hashes here.

File details

Details for the file latitude_telemetry_hermes-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: latitude_telemetry_hermes-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 43.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for latitude_telemetry_hermes-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6217ecda18067d73dcd6bf89385d5fa28ceb0de535996cecbd1e3aaf620e5f90
MD5 83215ea052e6f37cd92afdcb548f6a5b
BLAKE2b-256 2db0794f2acb0956096c3f00839c00fcf16b0500d130b853c545893e96e7ceaf

See more details on using hashes here.

Release history Release notifications | RSS feed

0.3.0

2 files

This release

0.2.0 This release

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page