Skip to content

refactor(guardrails)!: remove built-in integration - #1172

Open
afourniernv wants to merge 1 commit into
NVIDIA:mainfrom
afourniernv:refactor/remove-deprecated-nemo-guardrails
Open

afourniernv wants to merge 1 commit into
NVIDIA:mainfrom
afourniernv:refactor/remove-deprecated-nemo-guardrails

Conversation

@afourniernv

@afourniernv afourniernv commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Warning

BREAKING CHANGE: NeMo Relay 0.10 no longer ships the built-in nemo_guardrails component, its local or remote backend, its public Rust configuration module, or the guardrails-remote Cargo feature. Legacy [[components]] entries must be removed before upgrading.

Overview

Removes the built-in NeMo Guardrails integration after its deprecation in #753. This is the independently reviewed removal tracked by RELAY-692; it does not bundle or claim release of the replacement dynamic worker.

  • I confirm this contribution is my own work, or I have the right to submit it under this project's license.
  • I searched existing issues and open pull requests, and this does not duplicate existing work.

Details

  • Deletes the built-in local and remote implementations, public Rust configuration types, registration path, editor support, feature wiring, and implementation-specific tests.
  • Rejects enabled and disabled legacy [[components]] kind = "nemo_guardrails" entries with a migration-specific diagnostic. Manifest-backed dynamic plugins remain unaffected, including a future plugin that uses a Guardrails-related ID.
  • Removes stale built-in references from the docs and onboarding skill, redirects deleted documentation routes, and records the breaking change in the 0.10 release notes.
  • Documents that legacy settings do not migrate automatically and that the removed remote full-generation backend has no direct worker equivalent.
  • Leaves Relay's generic guardrail middleware APIs and conditional guardrails unchanged.
  • Tracks the separately packaged replacement in feat: add NeMo Guardrails worker plugin NeMo-Relay-Plugins#6 without describing that draft plugin as released.

Validation completed successfully:

  • just test-rust (5,308 workspace tests plus native, gRPC worker, and language-binding plugin example suites)
  • just docs
  • just docs-linkcheck
  • uv run pre-commit run
  • cargo check -p nemo-relay --lib --all-features
  • Core, CLI, Python, and Node build checks

The Fern checks passed with the expected unauthenticated warning that server-side missing-redirect validation was skipped.

Where should the reviewer start?

Start with the removed-component diagnostic in crates/cli/src/server/mod.rs, its regression coverage in crates/cli/tests/coverage/shared/server_tests.rs, and the migration guidance in docs/reference/migration-guides.mdx.

Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)

Summary by CodeRabbit

  • Breaking Changes

    • The built-in NeMo Guardrails component and its local and remote backends are no longer available. Remove all legacy nemo_guardrails configuration entries, including disabled entries; Relay rejects them with migration guidance.
    • NeMo Guardrails is no longer supported in the CLI editor, and the guardrails-remote Cargo feature has been removed. Existing settings are not transferred automatically to another integration.
  • Documentation

    • Added NeMo Relay 0.10 migration guidance and redirected legacy NeMo Guardrails documentation links to it.

Signed-off-by: Alex Fournier <afournier@nvidia.com>
@afourniernv
afourniernv requested review from a team as code owners September 30, 2026 21:51
@github-actions github-actions Bot added size:XXL PR is very large Improvement improvement to existing functionality breaking PR introduces a breaking change lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code labels Sep 30, 2026
@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Repository guideline files applied to this review (7)
.agents/skills/contribute-docs/SKILL.md — configured
.agents/skills/review-doc-style/SKILL.md — configured
.agents/skills/prepare-code-freeze/SKILL.md — configured
.agents/skills/draft-release-notes/SKILL.md — configured
.agents/skills/update-project-version/SKILL.md — configured
.agents/skills/maintain-packaging/SKILL.md — configured
.agents/skills/README.md — configured

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: NVIDIA/NeMo-Relay/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: e1174539-b02d-418f-9df8-f64084611b24

📥 Commits

Reviewing files that changed from the base of the PR and between 872972c and 8051eb9.

📒 Files selected for processing (39)
  • crates/cli/Cargo.toml
  • crates/cli/src/plugins/editor_model.rs
  • crates/cli/src/plugins/prompt.rs
  • crates/cli/src/server/mod.rs
  • crates/cli/tests/coverage/shared/plugins_tests.rs
  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/core/Cargo.toml
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/mod.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/local.rs
  • crates/core/src/plugins/nemo_guardrails/local_worker.py
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugins/nemo_guardrails/python.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/local_python_tests.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/remote_coverage_tests.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/remote_tests.rs
  • crates/node/Cargo.toml
  • crates/python/Cargo.toml
  • crates/python/src/lib.rs
  • crates/python/tests/coverage/nemo_guardrails_coverage_tests.rs
  • docs/about-nemo-relay/concepts/plugins.mdx
  • docs/about-nemo-relay/release-notes/index.mdx
  • docs/configure-plugins/about.mdx
  • docs/configure-plugins/nemo-guardrails/about.mdx
  • docs/configure-plugins/nemo-guardrails/configuration.mdx
  • docs/configure-plugins/plugin-configuration-files.mdx
  • docs/getting-started/configuration.mdx
  • docs/index.yml
  • docs/reference/migration-guides.mdx
  • docs/resources/glossary.mdx
  • fern/docs.yml
  • skills/nemo-relay-get-started/SKILL.md
  • skills/nemo-relay-get-started/evals/evals.json
  • skills/nemo-relay-get-started/references/built-in-integrations-try-now.md
  • skills/nemo-relay-get-started/references/cli-try-now.md
  • skills/nemo-relay-get-started/references/manual-language-try-now.md
💤 Files with no reviewable changes (24)
  • crates/cli/src/plugins/prompt.rs
  • docs/index.yml
  • docs/resources/glossary.mdx
  • crates/core/src/plugins/mod.rs
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/Cargo.toml
  • docs/configure-plugins/nemo-guardrails/about.mdx
  • crates/core/tests/unit/plugins/nemo_guardrails/local_python_tests.rs
  • docs/configure-plugins/nemo-guardrails/configuration.mdx
  • crates/core/src/plugin.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/remote_coverage_tests.rs
  • docs/getting-started/configuration.mdx
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/python/src/lib.rs
  • skills/nemo-relay-get-started/SKILL.md
  • crates/core/src/plugins/nemo_guardrails/python.rs
  • crates/core/src/plugins/nemo_guardrails/local.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/remote_tests.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
  • crates/core/src/plugins/nemo_guardrails/local_worker.py
  • crates/python/tests/coverage/nemo_guardrails_coverage_tests.rs
  • docs/configure-plugins/about.mdx
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/cli/src/plugins/editor_model.rs

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.

📜 Recent review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Preview docs
  • GitHub Check: Changes / Detect
🧰 Additional context used
📓 Path-based instructions (11)
Review documentation for technical accuracy against the current API, command correctness, and consistency across language bindings.

⚙️ CodeRabbit configuration file

Files:

  • docs/about-nemo-relay/concepts/plugins.mdx
  • docs/about-nemo-relay/release-notes/index.mdx
  • docs/reference/migration-guides.mdx
  • docs/configure-plugins/plugin-configuration-files.mdx
Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.

⚙️ CodeRabbit configuration file

Files:

  • crates/cli/tests/coverage/shared/server_tests.rs
  • crates/cli/tests/coverage/shared/plugins_tests.rs
Treat binding changes as public API changes.

⚙️ CodeRabbit configuration file

Files:

  • crates/node/Cargo.toml
  • crates/python/Cargo.toml
Source excerpt: In MDX files, top-of-file comments must use JSX comment delimiters: `{/*` to open and `*/}` to close.

📄 CodeRabbit inference engine (.agents/skills/contribute-docs/SKILL.md)

Files:

  • docs/about-nemo-relay/concepts/plugins.mdx
  • docs/about-nemo-relay/release-notes/index.mdx
  • docs/reference/migration-guides.mdx
  • docs/configure-plugins/plugin-configuration-files.mdx
Source excerpt: Verify MDX files use JSX delimiters for top-of-file SPDX comments.

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)

Files:

  • docs/about-nemo-relay/concepts/plugins.mdx
  • docs/about-nemo-relay/release-notes/index.mdx
  • docs/reference/migration-guides.mdx
  • docs/configure-plugins/plugin-configuration-files.mdx
Source excerpt: Search documentation source for references to the old version and update current-version install commands, package examples, and configuration examples to `` where appropriate: Review matches before changing th...

📄 CodeRabbit inference engine (.agents/skills/prepare-code-freeze/SKILL.md)

Files:

  • docs/about-nemo-relay/concepts/plugins.mdx
  • docs/about-nemo-relay/release-notes/index.mdx
  • docs/reference/migration-guides.mdx
  • docs/configure-plugins/plugin-configuration-files.mdx
Source excerpt: Update `docs/about-nemo-relay/release-notes/index.mdx` unless the release changes its route or navigation entry.

📄 CodeRabbit inference engine (.agents/skills/draft-release-notes/SKILL.md)

Files:

  • docs/about-nemo-relay/release-notes/index.mdx
Source excerpt: Python surfaces use PEP 440 translations where required; Cargo, npm, and plugin manifests use the repository SemVer form.

📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)

Files:

  • crates/cli/Cargo.toml
  • crates/node/Cargo.toml
  • crates/python/Cargo.toml
Source excerpt: Rust `Cargo.toml` package names and workspace metadata

📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)

Files:

  • crates/cli/Cargo.toml
  • crates/node/Cargo.toml
  • crates/python/Cargo.toml
Source excerpt: Preserve MDX front matter and the JSX SPDX comment.

📄 CodeRabbit inference engine (.agents/skills/draft-release-notes/SKILL.md)

Files:

  • docs/about-nemo-relay/concepts/plugins.mdx
  • docs/about-nemo-relay/release-notes/index.mdx
  • docs/reference/migration-guides.mdx
  • docs/configure-plugins/plugin-configuration-files.mdx
Source excerpt: Consumer-facing NeMo Relay usage skills live in top-level `skills/` and are maintained independently for integrators and end users.

📄 CodeRabbit inference engine (.agents/skills/README.md)

Files:

  • skills/nemo-relay-get-started/references/built-in-integrations-try-now.md
  • skills/nemo-relay-get-started/references/cli-try-now.md
  • skills/nemo-relay-get-started/references/manual-language-try-now.md
  • skills/nemo-relay-get-started/evals/evals.json
🔇 Additional comments (15)
crates/cli/Cargo.toml (1)

31-31: LGTM!

crates/node/Cargo.toml (1)

24-24: LGTM!

crates/python/Cargo.toml (1)

24-24: LGTM!

crates/cli/src/server/mod.rs (1)

1002-1002: LGTM!

Also applies to: 1016-1016, 1025-1025, 1035-1035, 1053-1053, 1076-1082

crates/cli/tests/coverage/shared/plugins_tests.rs (1)

2219-2219: LGTM!

crates/cli/tests/coverage/shared/server_tests.rs (1)

2583-2603: LGTM!

Also applies to: 2636-2644, 2694-2706

docs/about-nemo-relay/concepts/plugins.mdx (1)

188-189: LGTM!

docs/about-nemo-relay/release-notes/index.mdx (1)

36-51: LGTM!

docs/configure-plugins/plugin-configuration-files.mdx (1)

248-249: LGTM!

Also applies to: 444-445

docs/reference/migration-guides.mdx (1)

14-44: LGTM!

fern/docs.yml (1)

103-103: LGTM!

Also applies to: 105-109, 117-117

skills/nemo-relay-get-started/evals/evals.json (1)

185-185: LGTM!

skills/nemo-relay-get-started/references/built-in-integrations-try-now.md (1)

77-78: LGTM!

skills/nemo-relay-get-started/references/cli-try-now.md (1)

235-238: LGTM!

skills/nemo-relay-get-started/references/manual-language-try-now.md (1)

65-67: LGTM!


Walkthrough

The built-in NeMo Guardrails component, its local and remote backends, public configuration types, CLI editor support, and Cargo feature are removed. Static legacy entries now produce a migration diagnostic. Documentation and plugin recommendations are updated.

Changes

NeMo Guardrails removal

Layer / File(s) Summary
Core runtime and backend removal
crates/core/Cargo.toml, crates/core/src/plugin.rs, crates/core/src/plugins/*, crates/core/tests/unit/plugins/nemo_guardrails/*, crates/cli/Cargo.toml, crates/node/Cargo.toml, crates/python/Cargo.toml, crates/python/src/lib.rs, crates/python/tests/coverage/*
Core registration, the component and its local and remote backends, and the guardrails-remote feature are removed. Related Rust and Python test coverage is deleted.
CLI editor removal and legacy-entry validation
crates/cli/src/plugins/editor_model.rs, crates/cli/src/plugins/prompt.rs, crates/cli/src/server/mod.rs, crates/cli/tests/coverage/shared/*
The CLI no longer edits NeMo Guardrails configuration. Static nemo_guardrails entries are rejected whether enabled or disabled, with a removal diagnostic and migration-guide link. A dynamic entry without manifest_ref reaches dynamic activation and reports the missing field.
Migration guidance and references
docs/about-nemo-relay/concepts/plugins.mdx, docs/about-nemo-relay/release-notes/index.mdx, docs/configure-plugins/*, docs/getting-started/configuration.mdx, docs/index.yml, docs/reference/migration-guides.mdx, docs/resources/glossary.mdx, fern/docs.yml, skills/nemo-relay-get-started/*
Release notes and migration guidance describe the removal and handling of legacy entries. Plugin documentation and recommendations no longer list NeMo Guardrails. Legacy documentation routes redirect to the migration guides.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Other

Merge Risk: ⚪ Minimal · up to 8051e

The removal is accompanied by migration diagnostics and documentation. No concrete merge-blocking issue is established; merge after normal checks, with users required to remove legacy configuration entries.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 69.23% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 26 functions across 3 files. (12 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows Conventional Commits format, uses the required breaking-change marker, clearly describes the removal, and is 50 characters long without a trailing period.
Description check ✅ Passed The description includes the required Overview, Details, reviewer guidance, and Related Issues sections. It documents the breaking change, scope, migration behavior, validation, and related work.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 69.23% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 26 functions across 3 files. (12 skipped: 12 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

License Diff

Compared against origin/main.

Lockfile license changes

Lockfile License Changes

Rust

Added

  • None

Removed

  • None

Updated/Changed

  • None

Node

Added

  • None

Removed

  • None

Updated/Changed

  • None

Python

Added

  • None

Removed

  • None

Updated/Changed

  • None
Status output
[license-diff] selected languages: rust, node, python
[license-diff] generating current inventory
[license-diff] current: generating Rust inventory
[license-diff] current: Rust inventory complete (469 packages)
[license-diff] current: generating Node inventory
[license-diff] current: Node inventory complete (424 packages)
[license-diff] current: generating Python inventory
[license-diff] current: Python inventory complete (115 packages)
[license-diff] current inventory complete
[license-diff] checking out base ref origin/main into a temporary worktree
[license-diff] base: generating Rust inventory
[license-diff] base: Rust inventory complete (469 packages)
[license-diff] base: generating Node inventory
[license-diff] base: Node inventory complete (424 packages)
[license-diff] base: generating Python inventory
[license-diff] base: Python inventory complete (115 packages)
[license-diff] base inventory complete
[license-diff] removing temporary base worktree
[license-diff] comparing inventories
[license-diff] rendering Markdown output
[license-diff] done

@github-actions

Copy link
Copy Markdown

@afourniernv afourniernv added the DO NOT MERGE PR should not be merged; see PR for details label Sep 30, 2026
willkill07 added a commit that referenced this pull request Oct 1, 2026
#### Overview

Passes invocation-scoped codec context to every non-streaming and
streaming LLM execution interceptor across Relay core, language
bindings, native plugins, and gRPC workers.

Relay remains the codec owner. An interceptor can identify and use the
request codec selected for the invocation, safely decode and re-encode
the request, and—on non-streaming calls—decode the completed downstream
response. Streaming receives request codec access only because Relay
does not yet have a complete-response contract for provider chunks.

- [x] I confirm this contribution is my own work, or I have the right to
submit it under this project's license.
- [x] I searched existing issues and open pull requests, and this does
not duplicate existing work.

#### Details

- Adds one execution context argument across the existing
execution-interceptor surfaces; it does not add another middleware stage
or change ordering.
- Carries host-owned codec operations through in-process callbacks, the
native plugin ABI, language bindings, and gRPC workers.
- Preserves the current request-interceptor contract and keeps
complete-response decoding unavailable for streaming calls.

#### Why

Execution interceptors wrap the provider call but currently receive only
provider JSON. A consumer that needs structured request or response data
must maintain provider-specific adapters, guess the wire format, or
depend on Relay's full runtime package. Those approaches duplicate host
logic, can drift from Relay, and cannot cover host-owned runtime or
opaque codecs.

This change exposes the codec already selected by Relay through the
existing execution interceptor. It does not add another middleware stage
or change ordering. The NeMo Guardrails worker is the first consumer
([NVIDIA/NeMo-Relay-Plugins#6](NVIDIA/NeMo-Relay-Plugins#6)),
but the API is generic.

#### API contract

`LlmExecutionContext` is passed immediately before `next`:

| Surface | Callback shape |
|---|---|
| Rust core and Rust language binding | `(name, request, context, next)`
|
| Python language binding | `(name, request, context, next)` |
| Node.js language binding | `(request, context, next)` |
| Go language binding | `(request, context, next)` |
| Public C API | `(user_data, name, request, context, next, next_ctx)` |
| Native Rust plugin SDK | `(name, request, context, next)` for
typed/async wrappers; equivalent context in raw callbacks |
| Rust and Python worker SDKs | `(name, request, context, next)` |

The context is directional:

- `request_codec`: `LlmSanitizeRequestContext`, with identity plus
decode and encode operations whenever Relay resolved a codec;
- `response_codec`: optional `LlmSanitizeResponseContext`, with identity
plus decode for non-streaming execution;
- streaming `response_codec`: unavailable rather than offering
best-effort chunk decoding.

Execution intercepts reuse the existing `LlmSanitizeRequestContext` and
`LlmSanitizeResponseContext` types; no parallel generic aliases are
added. The native plugin SDK keeps distinct execution codec contexts
because its borrowed ABI capabilities have different ownership and
lifetime rules. The shared codec capability exposes identity and
operations; using it does not run sanitizer middleware.

Identity distinguishes absent, built-in, runtime, and opaque codecs. An
opaque codec still exposes operations when Relay has the resolved codec
object.

Request intercepts are unchanged; `annotated_request` remains their
normalized input.

#### Compatibility

This is an intentional source and binary break for consumers that
register execution-interceptor callbacks.

- Native execution callbacks move to internal ABI v7. ABI v6 remains the
frozen operational-logging layout.
- Native manifests continue to use `compat.native_api = "1"`.
- Worker manifests continue to use `compat.worker_protocol = "grpc-v1"`;
`LlmInvocation` gains an additive execution-context field.
- Native plugins must rebuild against the v7 layout and set a Relay
lower bound of `>=0.10.0` or another range that excludes 0.9.
- Workers that register LLM execution intercepts must regenerate or
upgrade their SDK, adopt the context argument, and use the same Relay
compatibility floor.
- Rust, Python, Node.js, Go, and C consumers using these callbacks must
update to the new argument order when they adopt this Relay release.

The host rejects native ABI v2-v6 layouts before callback registration.
This keeps early 0.10-alpha v6 artifacts, whose callback layout lacks
execution context, distinguishable from the current ABI instead of
invoking them through an incompatible function signature.

Keeping `native_api = "1"` and `grpc-v1` is deliberate: those labels
identify the authored plugin and protocol families, while the Relay
version range communicates the release-level callback break.

#### Notes for reviewers

- The changes under `crates/core/src/plugins/nemo_guardrails` only keep
the deprecated built-in integration compiling with the new callback
signature. They are not a redesign of that plugin and should disappear
when removal PR [#1172](#1172)
lands. Replacement source is tracked separately in
[NVIDIA/NeMo-Relay-Plugins#6](NVIDIA/NeMo-Relay-Plugins#6).
- Please review the native ABI path particularly closely:
`crates/core/src/plugin/dynamic/native.rs`, `crates/plugin/src/lib.rs`,
`crates/plugin/src/async_sdk.rs`, `crates/ffi/nemo_relay.h`, and the
native fixture/tests. The important questions are table layout and
versioning, rejection of stale binaries, handle ownership,
retain/release balance, cancellation, and capability expiry.

#### Lifetime and ownership

- Core and in-process binding contexts receive revocable codec facades.
Each interceptor gets an independent lease: a non-streaming lease
expires when its callback settles, while a streaming request lease moves
into the returned stream and expires on completion, error, close, drop,
or cancellation. Retaining a facade after expiry does not keep the
backing codec alive.
- Worker SDKs receive proxies, never capability IDs. The host authorizes
each operation against the activation and invocation that created it and
revokes capabilities when non-streaming execution settles or the
returned stream closes.
- Safe native async wrappers retain an owning completion or stream
lease. Calls after settlement fail instead of dereferencing a stale
codec handle.
- Streaming keeps the request capability alive through lazy polling and
close, but never exposes a response decoder.
- A worker stream error is terminal on both sides of the gRPC bridge.
Relay closes the forwarded stream and releases continuations, scope
state, active-invocation state, and codec capabilities even if the
consumer retains its stream object.

#### Non-goals

- No response encoding API.
- No generic response mutation contract beyond returning the execution
interceptor's existing JSON result.
- No buffering or output-guarded streaming.
- No change to request intercepts, conditional middleware, cache
ordering, or execution ordering.
- No claim that Relay's normalized response exposes every provider
candidate, tool payload, or reasoning field.

#### Validation

The branch covers:

- request decode/encode and non-streaming response decode;
- built-in, runtime, opaque, and absent codec identities;
- non-streaming and lazy streaming lifetime/expiry behavior;
- global and scope-local registration and callback argument order;
- Rust, Python, Node.js, Go, C/FFI, native plugin, Rust worker, and
Python worker surfaces;
- frozen ABI-v6 logging layout, current ABI-v7 layout, and v2-v6
rejection while keeping `native_api = "1"`;
- worker capability authorization, ownership, cancellation,
terminal-error cleanup, and expiry while keeping `grpc-v1`.

The repository CI matrix must run on the pushed head. This PR remains
draft until the design is approved and that matrix is green.

#### Where should the reviewer start?

1. `crates/core/src/api/runtime/llm_execution_context.rs` and
`crates/core/src/api/runtime/callbacks.rs` — callback and directional
context contract.
2. `crates/core/src/api/llm.rs` and the execution registry — context
construction and unchanged ordering.
3. **Native ABI focus:** `crates/core/src/plugin/dynamic/native.rs`,
`crates/plugin/src/lib.rs`, `crates/plugin/src/async_sdk.rs`,
`crates/ffi/nemo_relay.h`, and the native fixture/tests — table layout,
versioning, ownership, and stale-binary rejection.
4. `crates/worker-proto`, `crates/core/src/plugin/dynamic/worker.rs`,
`crates/worker`, and `python/plugin` — invocation-scoped worker
capabilities.
5. Language bindings and their global/scope-local tests.

#### Related Issues: (use one of the action keywords Closes / Fixes /
Resolves / Relates to)

- Relates to
[RELAY-681](https://linear.app/nvidia/issue/RELAY-681/ship-an-input-only-nemo-guardrails-dynamic-python-worker)
- Relates to #1172
- Consumer:
[NVIDIA/NeMo-Relay-Plugins#6](NVIDIA/NeMo-Relay-Plugins#6)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* LLM execution interceptors can access the selected request codec to
decode and encode requests. Non-streaming interceptors can also access
the codec for completed responses; streaming interceptors do not receive
response codec access.
* Codec access is limited to the callback or returned stream’s lifetime.
* **Compatibility**
* Plugins and workers using LLM execution interceptors must update
callback signatures and rebuild for Relay 0.10. Native plugins must use
ABI v7; affected compatibility ranges must start at 0.10.
* **Documentation**
  * Added codec-context guidance and Relay 0.10 migration instructions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Alex Fournier <afournier@nvidia.com>
Co-authored-by: Will Killian <wkillian@nvidia.com>

This branch was successfully deployed

1 active deployment
fern — 8051eb9e Deployed Sep 30, 2026 by copy-pr-bot[bot] via Preview docs #5189
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking PR introduces a breaking change DO NOT MERGE PR should not be merged; see PR for details Improvement improvement to existing functionality lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code size:XXL PR is very large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant