Basic Usage

View as Markdown

The nemo-relay binary observes coding agents that do not expose every LLM call site directly. It combines agent-specific hook endpoints with a passthrough LLM gateway so NeMo Relay owns both the agent lifecycle and the model request lifecycle.

Use the gateway when you need one observability boundary for OpenAI Codex, Claude Code, and Hermes without replacing each agent’s canonical hook payload.

Hook Endpoints

Each hook endpoint accepts the agent’s native hook JSON directly. Do not wrap the payload in a shared gateway envelope.

  • POST /hooks/codex accepts Codex hook JSON and returns the Codex-compatible hook response object.
  • POST /hooks/claude-code accepts Claude Code hook JSON and returns Claude-compatible fields such as continue and permission decisions when the hook event supports them.
  • POST /hooks/hermes accepts Hermes shell hook JSON and returns the empty JSON object expected by Hermes hook commands.

The adapters preserve vendor fields such as session IDs, working directories, transcript paths, model names, tool payloads, shell payloads, MCP payloads, file payloads, user identity, and subagent metadata in NeMo Relay event metadata.

Gateway Routes

Route all coding-agent LLM traffic through the gateway when full LLM lifecycle observability is required.

  • POST /v1/responses
  • POST /v1/chat/completions
  • POST /v1/messages
  • POST /v1/messages/count_tokens
  • GET /v1/models

The gateway forwards raw provider JSON without rewriting OpenAI or Anthropic payload schemas. It removes only hop-by-hop transport headers, forwards streaming responses as streams, and emits NeMo Relay LLM start and end events under the active session scope.

Transparent Run

Use the agent shortcuts for no-install local observability. The wrapper starts a gateway on a dynamic 127.0.0.1 port, injects the resolved hook and gateway configuration into the launched coding agent, and stops the gateway when the agent exits.

$nemo-relay codex
$nemo-relay claude
$nemo-relay hermes

Use nemo-relay run -- <command> when you want to launch an explicit command instead of the built-in shortcut:

$nemo-relay run -- codex

If a launcher or wrapper hides the real agent name, set that wrapper as the configured command and pass --agent. The same pattern applies to Claude Code, Codex, and Hermes:

1[agents.codex]
2command = "my-codex-wrapper"
$nemo-relay run --agent codex

Hermes is different from the other transparent modes: run --agent hermes starts the gateway and exports the dynamic NEMO_RELAY_GATEWAY_URL, but Hermes shell hooks still need to be installed or otherwise approved in Hermes config.

Use --dry-run --print to inspect the generated hook config, gateway environment, gateway URL, and final command without launching the agent.

Persistent Host Plugins

Use persistent plugin installation when Claude Code or Codex should load NeMo Relay through the host’s plugin system instead of through a wrapper command:

$nemo-relay install claude-code
$nemo-relay install codex
$nemo-relay install all

Plugin installation writes a local marketplace, installs the generated nemo-relay-plugin, and configures the host-specific hook and provider routing needed for full observability. It still relies on the same local nemo-relay binary on PATH.

Use plugin doctor and uninstall for the installed host state:

$nemo-relay doctor --plugin codex
$nemo-relay uninstall codex

Refer to Plugin Installation for install directories, host-specific behavior, and Codex lazy sidecar constraints.

Shared Configuration

Shared TOML config is optional. The gateway loads defaults, then system config, then project config, then user config. User config takes priority over system and project config. CLI flags and environment variables override file config.

Interactive Setup

Run nemo-relay config to set up Relay interactively:

  1. Choose whether the base configuration should apply to the current project, your user account, or both.
  2. Select the coding agents that Relay should observe.
  3. Review and save the base config.toml.
  4. Choose whether to continue to the plugin editor.

The base config.toml stores the agent settings. Select Yes at the plugin prompt to configure optional Relay components and save them separately in plugins.toml. Project setup uses the project plugin configuration, global setup uses the user plugin configuration, and both continues with the project plugin configuration.

Select No to finish after saving config.toml. Canceling the prompt or leaving the plugin editor does not remove the saved base configuration. You can open the plugin editor again later with nemo-relay plugins edit, or use nemo-relay plugins edit --project for project configuration.

Add Model Pricing for Cost Estimates

Model pricing is configured with the same plugins.toml discovery path as Observability. The configured sources apply to transparent agent runs, standalone gateway runs, and evals or custom agents that initialize the same gateway plugin config. Framework integrations, harnesses, and custom hosts do not need their own model pricing logic when they emit managed LLM calls with response codecs: Relay attaches cost to the annotated response when the provider reports cost or when a configured model pricing source matches the response model and token usage.

Create a Relay model pricing catalog JSON file:

1{
2 "version": 1,
3 "entries": [
4 {
5 "provider": "openai",
6 "model_id": "gpt-4o-mini",
7 "aliases": ["openai/openai/gpt-4o-mini"],
8 "currency": "USD",
9 "unit": "per_token",
10 "rates": {
11 "input_per_million": 0.15,
12 "output_per_million": 0.6,
13 "cache_read_per_million": 0.075
14 },
15 "prompt_cache": {
16 "read_accounting": "included_in_prompt_tokens"
17 },
18 "pricing_as_of": "2026-06-06",
19 "pricing_source": "internal-pricing-snapshot"
20 }
21 ]
22}

Validate and add the file-backed source:

$nemo-relay model-pricing validate /path/to/pricing.json
$nemo-relay model-pricing init --project
$nemo-relay model-pricing add-source /path/to/pricing.json --project

Use --user instead of --project for a device-wide user config, or --global for /etc/nemo-relay/plugins.toml. model-pricing add-source prepends the source by default, so the new file becomes the highest-priority source for that scope. Use --append to add it as a lower-priority fallback.

Resolve a model before running an agent:

$nemo-relay model-pricing resolve gpt-4o-mini \
> --provider openai \
> --prompt-tokens 1000 \
> --completion-tokens 500

model-pricing resolve prints the source that won, the matched provider/model, and an estimated total when token counts are supplied. Use it to debug overlapping fleet, project, and user model pricing files.

Run doctor to validate the active model pricing sources alongside exporter checks:

$nemo-relay doctor codex

Doctor fails when an enabled model pricing source is unreadable or contains an invalid catalog, and it reports passing sources as Model pricing source.

Relay does not ship a canonical price catalog. Unknown models and missing token fields leave cost absent instead of defaulting to zero. For the catalog schema, provider-aware lookup behavior, threshold-based model pricing, and custom PricingSource integrations, refer to Provider Response Codecs and Model Pricing.

Transparent runs always bind the managed gateway to 127.0.0.1:0. The selected port is discovered by the wrapper and exposed to hooks through NEMO_RELAY_GATEWAY_URL.

Common environment variables for direct gateway server use are:

  • NEMO_RELAY_GATEWAY_BIND
  • NEMO_RELAY_OPENAI_BASE_URL
  • NEMO_RELAY_ANTHROPIC_BASE_URL
  • NEMO_RELAY_MAX_HOOK_PAYLOAD_BYTES
  • NEMO_RELAY_MAX_PASSTHROUGH_BODY_BYTES

The default hook payload limit is 20MiB. The default provider passthrough body limit is 100MiB. Set both values in bytes.

Plugin configuration controls process-level Observability exporters. Per-session configuration controls structured metadata on the top-level agent begin event and the plugin configuration metadata associated with the session.

hook-forward can also pass per-session configuration through headers:

  • x-nemo-relay-config-profile
  • x-nemo-relay-session-metadata
  • x-nemo-relay-plugin-config
  • x-nemo-relay-gateway-mode

The accepted gateway mode values are hook-only, passthrough, and required. The gateway records this value as session metadata so downstream exporters and review tooling can distinguish hook-only traces from sessions where provider traffic was expected to pass through the gateway.

Runtime Mapping

The gateway normalizes vendor hook payloads into private internal events before calling NeMo Relay APIs.

  • Agent start opens a top-level ScopeType::Agent scope on a dedicated ScopeStackHandle.
  • Subagent start opens a child ScopeType::Agent scope. Subagent stop closes that scope when it is still active.
  • Tool pre-use starts a NeMo Relay tool span. Tool post-use, denial, or failure closes it.
  • Prompt, response, agent-thought, and legacy Hermes pre_llm_call / post_llm_call hooks are retained as private correlation hints. They are not emitted as NeMo Relay events.
  • Compaction, notification, and unknown hook events become mark events under the active session scope.
  • Gateway requests emit NeMo Relay LLM start and end events under the active session scope. Before each LLM start, the gateway uses explicit subagent headers, pending hints, shared conversation/generation/request identifiers, and the previous correlated owner to choose the parent scope.
  • LLM responses that contain future tool-use suggestions are retained as private tool-call hints. The next matching tool hook can then inherit the subagent scope that owned the LLM response, even when the hook payload does not include a subagent id.

Gateway requests can provide explicit correlation identifiers with these headers:

  • x-nemo-relay-session-id
  • x-nemo-relay-subagent-id
  • x-nemo-relay-conversation-id
  • x-nemo-relay-generation-id
  • x-nemo-relay-request-id

When those headers are absent, the gateway also looks for conversation_id/conversationId/conversation.id, generation_id/generationId/generation.id, and request_id/requestId/request.id fields in the provider request body. Correlation hints expire after five minutes. If the gateway cannot select one unambiguous hint, it falls back to the previous LLM owner, then to the only active subagent, then to the top-level agent scope.

Every gateway LLM event includes llm_correlation_status metadata. Possible values are explicit, single_hint, matched_hint, sticky_last_owner, active_subagent, agent_fallback, and ambiguous_fallback. Matched hints can also add llm_correlation_source, llm_correlation_subagent_id, llm_correlation_conversation_id, llm_correlation_generation_id, llm_correlation_request_id, and llm_correlation_agent_type.

Generated hook bundles subscribe to the events needed for that mapping:

AgentLLM lifecycle and correlation hooksScope, tool, and mark hooks
Claude CodeUserPromptSubmit, AfterAgentResponse, AfterAgentThought, StopSessionStart, SessionEnd, SubagentStart, SubagentStop, PreToolUse, PostToolUse, PostToolUseFailure, Notification, PreCompact
CodexUserPromptSubmit, AfterAgentResponse, AfterAgentThought, StopSessionStart, SessionEnd, SubagentStart, SubagentStop, PreToolUse, PostToolUse, PostToolUseFailure, Notification, PreCompact
Hermespre_api_request, post_api_request, api_request_error, pre_llm_call, post_llm_callon_session_start, on_session_end, on_session_finalize, on_session_reset, subagent_start, subagent_stop, pre_tool_call, post_tool_call

Hermes pre_api_request, post_api_request, and api_request_error hooks map to NeMo Relay LLM start/end events when present. Hermes pre_llm_call and post_llm_call remain private correlation hints.

Hook Forwarding

Hooks generated by the wrapper (Claude/Codex ephemeral, Hermes via setup) invoke nemo-relay hook-forward <agent> from stdin. Inside the wrapper the gateway URL comes from NEMO_RELAY_GATEWAY_URL injected on every run; outside the wrapper (Hermes standalone, IDE-launched Claude/Codex) the hook command falls back to its embedded --gateway-url.

Hooks installed by Claude Code and Codex plugins use the plugin shim path managed by nemo-relay install. That path starts or reuses the local plugin sidecar before forwarding the hook payload.

hook-forward reads the canonical hook payload from standard input, sends it to the matching endpoint, and prints the endpoint response. It fails open by default so observability outages do not block the coding agent. Add --fail-closed only when policy requires hook delivery to block the agent.

Optional flags map to gateway headers:

  • --session-metadata sets x-nemo-relay-session-metadata.
  • --profile sets x-nemo-relay-config-profile.
  • --gateway-mode sets x-nemo-relay-gateway-mode.

Agent Guides

Use the per-agent guide for end-to-end setup, smoke tests, and GUI or application-mode caveats.

Each guide covers transparent run setup, gateway routing, hook smoke tests, Agent Trajectory Interchange Format (ATIF) export verification on session end, and troubleshooting missing LLM lifecycle data.