> This page is for NeMo Relay, version v0.9.4.
> For other versions, use one of these documentation indexes:
> - Latest (v0.10.0) (default): https://docs.nvidia.com/nemo/relay/latest/llms.txt
> - dev: https://docs.nvidia.com/nemo/relay/dev/llms.txt
> - v0.10.0: https://docs.nvidia.com/nemo/relay/v0.10.0/llms.txt
> - v0.9.4: https://docs.nvidia.com/nemo/relay/v0.9.4/llms.txt
> - v0.8.4: https://docs.nvidia.com/nemo/relay/v0.8.4/llms.txt
> - v0.7.3: https://docs.nvidia.com/nemo/relay/v0.7.3/llms.txt
> - v0.6.0: https://docs.nvidia.com/nemo/relay/v0.6.0/llms.txt
> - v0.5.0: https://docs.nvidia.com/nemo/relay/v0.5.0/llms.txt

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo/relay/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo/relay/_mcp/server.

# Release Notes for NVIDIA NeMo Relay

> Review highlights, compatibility updates, fixed known issues, and current known issues for NVIDIA NeMo Relay 0.9.

This page contains the release notes for [NVIDIA NeMo Relay](/about-nemo-relay/overview).

For the full release history, including individual pull requests, refer to
[GitHub Releases](https://github.com/NVIDIA/NeMo-Relay/releases).

## Release 0.9.3

### Shared Python Worker Plugins

* System-installed Python worker plugins can now validate across daemon users.
  Newly provisioned managed environments hold the attestation key; legacy
  environments may remain valid without an environment-local key. Startup
  checks shared lifecycle state without rewriting it. Administrators must make
  the system configuration, manifest, lifecycle state, and managed environment
  readable by each daemon user. For setup and permissions, refer to
  [Discoverable Plugins](/configure-plugins/discoverable-plugins).

### Coding-Agent and Observability Updates

* Authenticated Claude Code and Codex permission decisions now carry the
  matched `gen_ai.tool.call.id` and tool parent. When a guardrail rejects an
  active tool, Relay closes its span as denied with
  `error.type = "guardrail_rejected"`. For lifecycle details, refer to
  [Basic Usage](/nemo-relay-cli/basic-usage#runtime-mapping).
* Claude Code and Codex hooks for qualified `mcp__<server>__<tool>` calls now
  add `mcp.method.name = "tools/call"` event metadata. Existing method metadata
  takes precedence; the new value identifies the requested operation and does
  not establish that the MCP server received or completed it. For export
  behavior, refer to [OpenTelemetry](/configure-plugins/observability/opentelemetry).

### Dependency Update

* The optional LangChain NVIDIA integration now requires
  `langchain-nvidia-ai-endpoints>=1.4.2,<2.0.0`.

## Release 0.9.2

### Managed Daemon Operations

* The daemon now provides `GET /healthz` to report process health and global
  deployment mode. Separate read-only worker routes list assigned worker IDs
  and their last-known broker status. A healthy daemon can still have no
  assigned workers, so use the worker routes and lifecycle events when checking
  a managed deployment. For response fields and access guidance, refer to the
  [Daemon Reference](/daemon/reference#probe-daemon-health).

### Coding-Agent and Observability Fixes

* Codex permission checks now ignore the approval description that Codex adds
  to built-in tool requests when matching them to recorded tool calls. Denials
  use Codex's expected hook response format instead of producing an invalid
  permission-request output error. For Codex hook setup, refer to
  [Codex](/nemo-relay-cli/codex).
* OpenTelemetry log exporters now account for pending records separately for
  each resource-specific provider. Successful delivery no longer causes a
  false `otel.logs_dropped` error during shutdown when resource metadata
  creates multiple log providers.

## Release 0.9.1

NeMo Relay 0.9.1 improves OpenTelemetry coverage and managed Codex routing,
and fixes response-cache behavior for Anthropic compaction.

### Highlights

* The `gen_ai` OpenTelemetry projection adds authoritative request, response,
  usage, reasoning, embedding, and tool attributes. Managed streaming requests
  now report time to first chunk through the trace attribute
  `gen_ai.response.time_to_first_chunk` and the matching metric histogram.
  Relay also records the version of a wrapped Claude Code or Codex executable
  in matching observability metadata.
* OpenTelemetry log and metric endpoints can now promote selected root-scope
  metadata into their resource attributes with
  `promote_resource_metadata_prefixes`. Derived log and metric endpoints
  inherit the trace endpoint setting. Use only controlled, low-cardinality
  metadata values; Relay falls back to the configured base resource when its
  fixed resource-lineage or resource-pipeline limits are reached.
* GenAI tool spans now include the resolved conversation ID and preserve every
  non-null sanitized JSON tool argument and successful result.
* Managed Codex deployments now route ChatGPT OAuth requests to the native
  ChatGPT Codex backend when no administrator OpenAI credential is configured.
  When an administrator credential is configured, Relay replaces the inbound
  OAuth credential before forwarding to that upstream.

### Compatibility and Migration

> **Upgrade Action Required for Daemon Operators**
>
> The primary `nemo-relay daemon` process now reads TOML logging settings only
> from `[daemon.logging]`. It no longer falls back to `[logging]`.

Move logging settings for the primary daemon service to `[daemon.logging]`.
Other Relay processes continue to use `[logging]`; CLI and environment logging
overrides retain their existing precedence. For the required configuration and
Rust struct-literal updates, and telemetry attribute rename, refer to the
[Migration Guides](/reference/migration-guides).

### Fixes and Other Changes

* Anthropic Messages requests that use server-side compaction, continue from a
  compaction block, or send a compaction beta header now bypass the response
  cache. The live provider response preserves compaction lifecycle and streaming
  behavior; the bypass mark reports `anthropic_compaction`.
* Codex permission requests without a tool-call ID are accepted when exactly
  one active tool in the same session matches the request's name and arguments.
* OpenTelemetry logs and traces now use the same observed-event root when a
  scope's local parent was not exported. Relay also avoids adding a unique
  session UUID metric dimension so equivalent measurements can aggregate.
* Python development dependency constraints now require patched releases of
  `anyio` and `soupsieve`.

## Known Issues in 0.9.1

Response-cache replay does not support Anthropic server-side compaction. Relay
therefore sends affected requests to the live provider instead of caching them.
For affected request shapes, refer to
[Response Cache](/configure-plugins/adaptive/response-cache#llm-eligibility-and-limits).

## Release 0.9.0

### Highlights

This release adds the following features and changes:

* A shared daemon routes coding-agent requests to separate workers. Each user
  on each computer gets a worker with its own plugins and runtime state.
* The CLI adds Pi support. You can install its extension, record session
  activity, check tool calls against policy, and route supported model requests.
* All language bindings use the same plugin host to start, check, and stop
  plugins. Reports show the combined settings from files and application code.
* Related work stays in the same trace by default. OpenTelemetry tool spans
  include more details about tool execution and sanitized tool content.

> **Breaking Changes**
>
> Update plugin-host calls and tool execution intercepts before upgrading.
> Review trace boundaries and policies for removing personally identifiable
> information (PII). Change remote plaintext trace endpoints to HTTPS.
> OTLP/HTTP trace exporters no longer follow redirects. For required steps,
> refer to the [Migration Guides](/reference/migration-guides).

### Managed Daemon Deployments

Daemon mode supports the following shared-service features:

* `nemo-relay daemon` routes requests from authenticated Model Context Protocol
  (MCP) clients to workers. It supports coding-agent bundles that administrators
  manage for Codex, Claude Code, and Pi. Workers load system settings.
* MCP clients and workers keep WebSocket control connections open. These
  connections carry route updates, readiness checks, shutdown requests, and
  recovery messages. Model and hook traffic uses separate HTTP connections.
  Responses stream back as data arrives.
* Local deployments support Windows, macOS, and Linux. Remote deployments use
  HTTPS. Clients must reach the daemon, and the daemon must reach each client
  worker. Proxies must support WebSocket upgrades, keep those connections open,
  and forward frames in both directions. For setup, service management,
  upgrades, and troubleshooting, refer to
  [Daemon](/daemon/about).
* A managed gateway has up to 20 seconds after Relay starts it to resolve its
  persistent configuration, bind its listener, and report readiness. This gives
  slow configuration discovery time to finish.

### Coding-Agent and Framework Support

The following updates extend support for coding agents and frameworks:

* Use `nemo-relay install pi`, `nemo-relay pi`, and `nemo-relay doctor pi` to
  install, launch, and check the Pi extension. This proof of concept is tested
  with Pi 0.84.x. It records sessions, turns, tools, and shell commands entered
  in Pi. It checks policy through supported hooks.
* When Relay launches Pi, model requests can select named upstreams
  automatically. Relay skips models that use unsupported APIs. It also skips
  providers whose models have incompatible endpoint settings. For routing
  details, refer to [Pi](/nemo-relay-cli/pi).
* Use `create_tool_node` to run standalone LangGraph `ToolNode` calls through
  Relay's tool pipeline. LangGraph still supplies state, store, and runtime
  arguments. Add `NemoRelayCallbackHandler` to record graph lifecycle scopes.
  For details, refer to [Managed ToolNode Calls](/supported-integrations/langgraph#managed-toolnode-calls).
* The OpenClaw plugin now targets OpenClaw 2026.9.3. Its minimum gateway version
  is also 2026.9.3. For details, refer to
  [OpenClaw Plugin](/supported-integrations/openclaw-plugin).

### Plugin Configuration and Caching

Plugin settings and response caching include the following updates:

* `initialize` and `validate` use the same plugin settings, version checks,
  and trust policy. Exact validation checks only the static document you pass
  in. Initialization returns a `PluginHostActivation` handle that controls
  plugin lifetime. For details, refer to
  [Configure and Initialize Plugins](/configure-plugins/initialize-plugins).
* Host reports include `config_paths` and `resolved_config`. These fields show
  which files contributed settings and how Relay combined them with application
  settings. Reports redact literal credentials and values in dynamic-plugin
  settings whose meaning Relay does not know.
* Dynamic plugin declarations now layer by manifest plugin ID. When a
  higher-precedence file declares the same ID, its complete record replaces the
  lower-precedence record instead of blocking startup with a duplicate-ID
  error. For details, refer to [Plugin Configuration Files](/configure-plugins/plugin-configuration-files).
* Response caching adds `key_strategy = "logical"`. It ignores changes to tool
  descriptions and tool order. Other tool-definition changes still affect the
  key. `exact_request` remains the default. Each strategy has its own set of
  cache keys. For details, refer to
  [Key Strategies](/configure-plugins/adaptive/response-cache#key-strategies).

### Observability and Redaction

Trace exports and PII redaction include the following changes:

* Forking a scope stack or capturing propagation context keeps the Relay root
  when one is available. This root links related work to the same OpenTelemetry
  trace, even across processes. You can still capture a rootless context to
  start a separate trace.
* ATIF uses the propagated root as the exported `session_id` when one is
  present. The `trajectory_id`, filenames, storage keys, and remote session
  headers still use the individual trajectory scope UUID.
* Claude Code, Codex, and Pi provide consistent tool types and executing-agent
  names, including known subagent names. The `gen_ai` output format now includes
  sanitized tool arguments and successful results when they are JSON objects.
  It also includes tool-definition identities. The `full` and `openinference`
  formats receive the added tool metadata. For details, refer to
  [OpenTelemetry](/configure-plugins/observability/opentelemetry).
* Direct trace, log, and metric subscribers can read exporter headers from
  environment variables. Use `header_env`, or `headerEnv` in Node.js. Relay reads
  the values when it creates the subscriber. Missing or invalid values prevent
  creation without exposing the secret.
* Observability exporters can also read a header from a local file with
  `header_file`. This supports credentials that another process rotates. Relay
  reads the file for each HTTP delivery. An ATOF WebSocket reads it when it
  connects or reconnects, and an NDJSON sink reads it when it starts. Relay does
  not write the header value to diagnostics.
* OpenTelemetry trace, log, and metric exports add their standard SDK resource
  fields automatically. Do not set the reserved `telemetry.sdk.*` fields
  yourself.
* The PII `trajectory_context` preset removes unknown fields and opaque
  payloads, whose structure Relay cannot safely interpret. It keeps approved
  analytics fields and trace links. Typed metric attributes must match allowed
  string names and values. The preset drops numeric, boolean, and unlisted
  attributes. Python, Node.js, and Go configuration helpers expose the preset
  and its typed settings. For details, refer to
  [PII Redaction Configuration](/configure-plugins/pii-redaction/configuration).

### Operational Diagnostics

The CLI and daemon now provide more privacy-safe operational logs:

* Daemon logs show worker, route, MCP session, and upstream lifecycle events.
  CLI logs also show hook delivery and upstream request events, including slow
  or stalled streams. These records use random operation IDs and do not include
  prompts, tool data, model names, URLs, headers, or credentials.
* Failure records use short, fixed reason codes. These codes help operators
  identify a failed MCP session, gateway recovery, or worker startup without
  placing private error text in structured logs.
* `nemo-relay doctor` now includes the redacted plugin-host preflight. It shows
  static settings and dynamic-plugin trust or configuration problems without
  starting plugins.

For the event names, fields, and logging setup, refer to
[Operational Logging](/reference/operational-logging).

### Support Matrix and Compatibility Updates

For supported platforms, architectures, worker runtimes, coding agents, and
integrations, refer to the [Support Matrix](/reference/support-matrix).
Go and the raw C FFI remain experimental, with source-first support.

For steps to upgrade from 0.8.x to 0.9, refer to the
[Migration Guides](/reference/migration-guides).

### Breaking Changes

Review each of the following changes before upgrading.

#### Tool Execution Intercepts

> **Breaking Change**
>
> Tool execution intercepts now receive `(ToolExecutionContext, next)` because
> Relay needs to pass the provider tool-call ID with the name and arguments.
> Update every callback and plugin SDK that you use. Native plugins use ABI v5,
> and native or worker plugins that register this callback cannot support Relay
> 0.8. Follow the [Migration Guides](/reference/migration-guides) before you
> upgrade.

#### Plugin Host Lifecycle and Trust

> **Breaking Change**
>
> Global plugin clear and report functions and explicit dynamic activation-spec
> APIs are removed because one activation handle now owns the plugin host. Keep
> the handle, read its report, and close it during shutdown. The host also checks
> dynamic-plugin trust through every embedding API, so an unsigned plugin that
> previously started can now fail. Follow the
> [Migration Guides](/reference/migration-guides) before you upgrade.

#### Layered Dynamic Plugin Records

> **Breaking Change**
>
> A higher-precedence `[[plugins.dynamic]]` record with the same manifest ID now
> replaces the full lower-precedence record. This avoids duplicate-ID failures,
> but it also means that the lower record's `config` is not kept. Copy all needed
> settings to the higher-precedence record. Follow the
> [Migration Guides](/reference/migration-guides) before you upgrade.

#### Python Plugin Errors

> **Breaking Change**
>
> Python plugin initialization and activation now raise `ValueError` for invalid
> static settings and `FileNotFoundError` for unavailable files or resources.
> These errors replace `RuntimeError` for those cases, so existing exception
> handlers can miss them. Follow the [Migration Guides](/reference/migration-guides)
> before you upgrade.

#### Trace Boundaries

> **Breaking Change**
>
> Default propagation can now join traces that were separate. In ATIF,
> `session_id` identifies a run and `trajectory_id` identifies one trajectory in
> that run. This preserves the parent trace across related work. Follow the
> [Migration Guides](/reference/migration-guides) before you upgrade.

#### GenAI Tool Content

> **Breaking Change**
>
> GenAI exports now include sanitized tool content by default. Review redaction
> and data-access rules because your collector can receive content that it did
> not receive before. Follow the [Migration Guides](/reference/migration-guides)
> before you upgrade.

#### Secure Trace Transport

> **Breaking Change**
>
> Remote trace collectors must use HTTPS. Plain HTTP is limited to localhost and
> loopback IP addresses, and OTLP/HTTP trace exporters reject redirects. This
> prevents trace data from being sent to an unexpected or insecure destination.
> Follow the [Migration Guides](/reference/migration-guides) before you upgrade.

#### File-Based Exporter Headers

> **Breaking Change**
>
> Rust observability struct literals must set the new `header_file` field, and Go
> code that uses unkeyed composite literals must switch to keyed fields. Also,
> when any exporter header source is set, remote ATOF, ATIF, log, and metric
> destinations require secure HTTPS or WSS transport. These rules protect rotated
> credentials. Follow the [Migration Guides](/reference/migration-guides) before
> you upgrade.

#### PII Redaction

> **Breaking Change**
>
> The stricter `trajectory_context` preset removes opaque fields and metric
> attributes that it previously kept, so analytics that use them need updates.
> Follow the [Migration Guides](/reference/migration-guides) before you upgrade.

#### Rust Response Cache API

> **Breaking Change**
>
> Rust `ResponseCacheConfig.key_strategy` now uses
> `ResponseCacheKeyStrategy` instead of `String`, and
> `KEY_STRATEGY_EXACT_REQUEST` is removed. Update source code that configures a
> response cache. Follow the
> [Migration Guides](/reference/migration-guides) before you upgrade.

### Fixed Known Issues in 0.9

This release fixes the following issues that also affect earlier releases:

* Coding-agent LLM events keep the provider's conversation ID when one is
  given. Otherwise, they use the coding agent's session ID to link events.
* LangChain keeps message boundaries, tool-call IDs, and provider-specific
  content blocks when middleware processes messages. Relay omits its headers
  for models whose SDK rejects `extra_headers`, so those calls can proceed.
* Anthropic token usage is kept when a stream reports it across several events.
  Gateway routing handles upstream URLs that already end in `/v1`.
  Collected streams also keep content and encrypted content from Anthropic
  `compaction_delta` events.
* Anthropic Messages requests that enable server-side compaction or continue
  from a compaction block bypass the optional response cache, avoiding replay
  that cannot preserve the native compaction lifecycle.
* OpenAI Responses decoding keeps Codex automation tool outputs. Codex routing
  overrides also stay in the launched command's execution scope.
* Codex installation handles marketplace entries that point to missing files.
  Use `nemo-relay install codex --force` to repair stale entries owned by Relay.
* Generated Codex and Claude Code hook commands use private files.
* PII URL masking no longer keeps credentials. Overlapping PII path selectors
  no longer remove unrelated request content.
* Gateway streams can run for more than five minutes when data keeps arriving.
  Relay still stops a stream that stays idle for five minutes.
* `nemo-relay doctor` gives a slow coding-agent CLI up to 10 seconds to report
  its version. Network health checks keep their shorter timeout.
* `nemo-relay gateway stop` recognizes the published pinned CLI process and
  can stop the Relay-owned gateway it started.
* OpenTelemetry flush and shutdown drain accepted trace, log, and metric data
  more reliably before they finish.

### Other Improvements

This release also includes the following updates:

* Unix and PowerShell uninstall scripts remove a CLI installed by a script.
  They keep settings and integrations. They check active processes and refuse
  removal while managed daemon processes use the binary. For details, refer to
  [Remove a Script-Installed CLI](/getting-started/installation#remove-a-script-installed-cli).
* ATIF documentation explains how metadata placeholders become safe path
  components. Slashes in metadata values do not create nested directories.
  For details, refer to [Metadata-Based Paths](/configure-plugins/observability/atif#metadata-based-paths).

## Known Issues in 0.9

The following limitations still apply in this release:

* OTLP collectors can return a successful response while rejecting individual
  spans, log records, or metric data points. Relay does not report these partial
  successes in runtime diagnostics, and flush or shutdown can still succeed.
  Monitor collector-side rejection metrics and logs. Refer to
  [OpenTelemetry](/configure-plugins/observability/opentelemetry#trace-batch-processor-configuration).
* Go and the raw C FFI remain experimental and source-first. Generated API
  pages focus on Rust, Python, and Node.js.
* Local coding-agent observability depends on host hooks and provider traffic
  reaching the local gateway. Relay cannot fully capture remote or cloud
  execution that bypasses the local host.
* Persistent Codex and Claude Code integrations use user-scoped
  configuration and a shared loopback gateway. Use `nemo-relay run` when a
  launch must retain project-specific configuration.
* On Windows, a restrictive host Job Object can limit gateway reuse or prevent
  persistent bootstrap. Codex can also make a cold-start `/models` request
  before required MCP servers start; Relay retries the request.
* Codex 0.143 does not expose `SessionEnd`, and Codex multi-agent v2 encrypts
  delegated-task payloads that Relay cannot decrypt or reliably link.
* Pi support is a proof of concept tested with 0.84.x. By default, its personal
  extension lets work continue if the gateway is unavailable. Later extensions
  can change arguments after Relay checks them. Unsupported provider routes
  produce no LLM spans. This includes Google's native Gemini and Vertex APIs.
  To route Gemini model traffic through Relay, use a provider or proxy that
  accepts an OpenAI- or Anthropic-compatible API. Nested Pi processes appear as
  separate sessions. SIGINT in headless mode can stop Pi before queued events
  are sent. For details, refer to [Pi Limitations](/nemo-relay-cli/pi#limitations).
* If a managed daemon worker fails to start, its authenticated route can enter
  pass-through mode. This mode forwards model requests without worker plugins
  until all MCP clients leave the route. MCP readiness alone does not prove
  that policy checks or exporters are active. For details, refer to
  [Daemon Operations](/daemon/operations).
* Remote daemons and client workers must be able to reach each other.
  Proxies must support WebSockets. Loopback control connections do not send
  periodic pings. An idle hung process can go undetected until an operation
  times out.
* The Node.js binding and package workflows require Node.js 24 or later.
* OpenClaw has public hook-backed telemetry. Its security and optimization
  coverage is partial because it does not own a managed execution path.
* The built-in `nemo_guardrails` plugin is deprecated and scheduled for removal
  in NeMo Relay 0.9. No replacement is included. Until removal, the remote
  backend inherits its configured service's availability, latency, and policy
  behavior, and the local backend requires Python 3.11 or later and
  `nemoguardrails==0.22.0`. Removal will include the built-in component kind,
  the public `nemo_relay::plugins::nemo_guardrails` Rust module, its CLI editor
  entry, and the `guardrails-remote` Cargo feature.
* The PII redaction plugin currently supports its deterministic local backend;
  local-model backend configuration is reserved for future work.
* Pricing and optimization estimates depend on model names, token data, pricing
  sources, and freshness evidence. Missing or inconsistent evidence produces
  partial or absent cost fields rather than zero values.
* ATOF stream sinks and remote ATIF storage require reachable, correctly
  configured destinations. A failed stream sink does not stop file output or
  other active sinks.
* ATIF omits point-in-time marks. Use ATOF for the canonical mark stream;
  the `gen_ai` OpenTelemetry projection also omits marks. The `full` and
  `openinference` projections retain their fixed native mark handling.
* Native dynamic plugins run in the Relay process and are not sandboxed. A
  `grpc-v1` worker runs in a separate process, but that process is not a
  security sandbox.
* Treat Python `LLMRequest` objects as immutable. Request middleware that
  changes content must return a new request object.
* Native subscriber callbacks arrive asynchronously. Flush subscribers before
  depending on their side effects, captured events, files, or exporter output.
* OpenTelemetry endpoints use finite batch queues. A burst that fills an
  endpoint queue drops completed spans without applying backpressure and can
  leave an incomplete trace, including a missing root span. The SDK warns on
  the first drop and reports the exact dropped-span count during graceful
  shutdown. Configure `max_queue_size`, `max_export_batch_size`, and
  `scheduled_delay_millis` independently on each endpoint, or use the standard
  `OTEL_BSP_*` environment variables as process-wide fallbacks. A larger finite
  queue does not guarantee lossless telemetry.
* Operational logging covers Relay-managed hooks, gateway requests, the daemon,
  and workers. It does not yet cover every CLI command.

## Previous Releases

For previous release notes, release artifacts, and the complete PR-by-PR
history, refer to [GitHub Releases](https://github.com/NVIDIA/NeMo-Relay/releases).

## Related Topics

For more information, refer to the following pages:

* [Support Matrix](/reference/support-matrix)
* [Migration Guides](/reference/migration-guides)
* [Installation](/getting-started/installation)
* [NVIDIA NeMo Relay CLI](/nemo-relay-cli/about)
* [Known Issues and Troubleshooting](/resources/support-and-faqs)