Skip to content

feat(observability): propagate traceparent for LLM requests - #744

Merged
rapids-bot[bot] merged 10 commits into
NVIDIA:mainfrom
willkill07:feat/relay-186-traceparent
Aug 10, 2026
Merged

feat(observability): propagate traceparent for LLM requests#744
rapids-bot[bot] merged 10 commits into
NVIDIA:mainfrom
willkill07:feat/relay-186-traceparent

Conversation

@willkill07

@willkill07 willkill07 commented Aug 8, 2026

Copy link
Copy Markdown
Member

Overview

Add public traceparent capture/conversion APIs across Relay bindings and automatically propagate runtime-owned W3C traceparent headers on managed LLM requests.

  • 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

  • Add rooted PropagationContext to traceparent conversion and ambient capture APIs in Rust, FFI, Python, Node.js, and Go.
  • Inject exactly one runtime-owned traceparent header for buffered and streaming managed LLM execution, replacing case-insensitive user values.
  • Reserve the LLM UUID before request interception so the outbound parent ID matches the emitted LLM span.
  • Keep standalone request-intercept behavior outbound-only: inject when a real Relay context exists and omit without error otherwise.
  • Update propagation and LLM instrumentation documentation and add Rust regression coverage.

Validation completed: cargo clippy --workspace --all-targets -- -D warnings, cargo fmt --all, focused Rust traceparent/middleware tests, Rust/FFI/Python/Node cargo checks, Python native tests, and focused Go propagation tests.

Known environment limitations: the full Rust test suite has unrelated existing observability-config-v2/plugin-fixture failures; the full Go suite requires generated dynamic-plugin fixtures.

Where should the reviewer start?

Start with crates/core/src/api/runtime/scope_stack.rs for traceparent identity semantics, then crates/core/src/api/llm.rs and crates/core/src/api/shared.rs for managed and standalone injection ordering.

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

  • Relates to: RELAY-186

Summary by CodeRabbit

  • New Features

    • Added W3C traceparent propagation for managed LLM requests and request interception.
    • Conflicting trace headers are replaced with runtime-generated values.
    • Added APIs across Python, Go, Node.js, and FFI integrations to capture the current trace context or convert propagation contexts into traceparent strings.
    • LLM handles can accept caller-provided identifiers.
    • Request interception now returns complete interception outcomes.
  • Documentation

    • Added guidance for trace propagation and automatic LLM request instrumentation.

Signed-off-by: Will Killian <wkillian@nvidia.com>
@willkill07
willkill07 requested review from a team as code owners August 8, 2026 18:53
@github-actions github-actions Bot added size:M PR is medium Feature a new feature lang:go PR changes/introduces Go code lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code labels Aug 8, 2026
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The change adds W3C traceparent generation and propagation. Runtime contexts retain propagated roots, managed LLM requests inject runtime-owned headers, standalone interception returns complete outcomes, and FFI, Node, Go, and Python APIs expose traceparent conversion.

Changes

Traceparent propagation

Layer / File(s) Summary
Runtime trace context
crates/core/src/api/runtime/..., crates/core/src/observability/mod.rs, crates/core/tests/integration/context_isolation_tests.rs
Scope stacks preserve propagated root UUIDs. Rooted contexts produce W3C traceparent values. Runtime capture reports errors when no emitted scope exists.
LLM request injection
crates/core/src/api/llm.rs, crates/core/src/api/shared.rs, crates/core/src/api/runtime/state.rs, crates/core/tests/integration/*, crates/core/tests/unit/llm_api_tests.rs, crates/node/tests/*, python/tests/test_llm.py
Managed buffered and streaming calls reserve UUIDs before interception and inject runtime-owned headers. Standalone interception injects captured context when available. Existing traceparent headers are replaced case-insensitively.
Native and Go bindings
crates/ffi/..., go/nemo_relay/nemo_relay.go, go/nemo_relay/context_test.go
C FFI and Go APIs capture the current traceparent and convert rooted propagation contexts. Native allocations are released after conversion.
Node, Python, and documentation APIs
crates/node/src/api/mod.rs, crates/python/..., docs/...
Node and Python expose traceparent capture and propagation-context conversion. Documentation describes managed LLM injection and manual capture.

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

Sequence Diagram(s)

sequenceDiagram
  participant Application
  participant ScopeStack
  participant ManagedLLM
  participant LlmRequest
  participant Provider
  Application->>ManagedLLM: start buffered or streaming call
  ManagedLLM->>ScopeStack: reserve LLM UUID
  ManagedLLM->>LlmRequest: intercept request
  ScopeStack->>LlmRequest: generate and inject traceparent
  LlmRequest->>Provider: send request with runtime-owned header
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title uses valid Conventional Commits syntax, an allowed lowercase type and scope, an imperative summary, and remains under 72 characters.
Description check ✅ Passed The description includes all required sections, completed confirmations, implementation details, reviewer guidance, related issue information, and validation results.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@willkill07 willkill07 changed the title feat: propagate traceparent for LLM requests feat(observability): propagate traceparent for LLM requests Aug 8, 2026
@willkill07 willkill07 self-assigned this Aug 8, 2026
@willkill07 willkill07 added this to the 0.8 milestone Aug 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/core/tests/unit/llm_api_tests.rs`:
- Around line 398-406: Update the provider request assertions in the LLM API
test to capture every buffered and streaming LLM start event, then verify each
outbound traceparent’s final 16 hexadecimal characters equal the lower 64 bits
of the corresponding event UUID. Retain the existing content, request-ID, and
traceparent format checks while adding assertions for this identity contract.

In `@crates/node/src/api/mod.rs`:
- Around line 1726-1732: The Node capture_traceparent path must handle
callback_propagation_parent_uuid before with_effective_scope_stack, using it as
the fallback root and parent when no propagated root exists; update
python/nemo_relay/__init__.py’s _propagation_parent_var handling to create a
rooted PropagationContext or retain the propagated root, and add Node and Python
callback-context tests verifying successful matching traceparent values while
preserving binding API parity.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 871fb960-f54d-4c08-9cf9-911cc0f6d088

📥 Commits

Reviewing files that changed from the base of the PR and between 5570b5b and 92ba36f.

📒 Files selected for processing (20)
  • crates/core/src/api/llm.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/core/src/api/runtime/state.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/observability/mod.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • crates/ffi/nemo_relay.h
  • crates/ffi/src/api/scope_stack.rs
  • crates/node/src/api/mod.rs
  • crates/python/src/py_api/mod.rs
  • crates/python/src/py_types/core.rs
  • docs/about-nemo-relay/concepts/scopes.mdx
  • docs/instrument-applications/instrument-llm-call.mdx
  • go/nemo_relay/nemo_relay.go
  • python/nemo_relay/__init__.py
  • python/nemo_relay/__init__.pyi
  • python/nemo_relay/_native.pyi
📜 Review details
⏰ Context from checks skipped due to timeout. (18)
  • GitHub Check: Python / Package (windows-arm64)
  • GitHub Check: Python / Test (windows-amd64)
  • GitHub Check: Python / Package (macos-arm64)
  • GitHub Check: Python / Package (windows-amd64)
  • GitHub Check: Rust / Package (macos-arm64)
  • GitHub Check: Python / Package (linux-musl-amd64)
  • GitHub Check: Node.js / Package (linux-musl-amd64)
  • GitHub Check: Python / Test (macos-arm64)
  • GitHub Check: Node.js / Package (windows-arm64)
  • GitHub Check: Python / Package (linux-musl-arm64)
  • GitHub Check: Node.js / Package (linux-musl-arm64)
  • GitHub Check: Python / Test (windows-arm64)
  • GitHub Check: Node.js / Package (windows-amd64)
  • GitHub Check: Python / Test (linux-amd64)
  • GitHub Check: Go / Test (windows-arm64)
  • GitHub Check: Go / Test (windows-amd64)
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (52)
**/*.mdx

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

MDX top-of-file SPDX comments must use {/* ... */} delimiters instead of HTML comment delimiters (Must-Fix)

**/*.mdx: In MDX files, top-of-file comments must use JSX comment delimiters ({/* and */}); do not use HTML comments for MDX SPDX headers.
New or regenerated MDX files must use {/* ... */} for top-of-file SPDX comments.

Files:

  • docs/about-nemo-relay/concepts/scopes.mdx
  • docs/instrument-applications/instrument-llm-call.mdx
{docs,examples}/**/*

📄 CodeRabbit inference engine (.agents/skills/rename-surfaces/SKILL.md)

Update docs and examples.

Files:

  • docs/about-nemo-relay/concepts/scopes.mdx
  • docs/instrument-applications/instrument-llm-call.mdx
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, use maintain-dynamic-plugins and include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

**/*: Use release tags in raw Rust-compatible SemVer without a leading v; tags such as v0.1.0 are prohibited.
Use branch prefixes feat/, fix/, docs/, test/, or refactor/ according to the change purpose.
Every commit in a pull request must include a DCO Signed-off-by: sign-off.
Before submitting a pull request, ensure pre-commit hooks, relevant tests, target-specific builds, documentation updates, and a rebase on the latest main are complete.
Use commit messages in the form type: short description, with a valid type and a first line under 72 characters.

Run the prescribed plugin validation commands, including fixture building, focused Rust and Python package tests, integration tests, documentation checks, and the broader validate-change matrix for broad runtime or public API changes.

**/*: Keep observability changes scoped, surface assumptions, and define focused validation before editing.
Run affected Rust tests and just test-rust for event-field changes; run just test-python, just test-go, and just test-node when binding-native configuration or lifecycle changes; update docs and examples in the same branch.

Files:

  • docs/about-nemo-relay/concepts/scopes.mdx
  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • python/nemo_relay/__init__.py
  • crates/python/src/py_api/mod.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/ffi/nemo_relay.h
  • crates/python/src/py_types/core.rs
  • docs/instrument-applications/instrument-llm-call.mdx
  • python/nemo_relay/__init__.pyi
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • python/nemo_relay/_native.pyi
  • go/nemo_relay/nemo_relay.go
  • crates/ffi/src/api/scope_stack.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/node/src/api/mod.rs
docs/**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If documentation examples or commands under docs/ change, run the targeted docs checks appropriate to the change.

Files:

  • docs/about-nemo-relay/concepts/scopes.mdx
  • docs/instrument-applications/instrument-llm-call.mdx
**/*.{md,mdx}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If links in documentation change, run just docs-linkcheck.

Use documented public APIs and stable wrapper commands in examples and user-facing documentation; do not rely on internal helpers.

**/*.{md,mdx}: Prefer the documented public API over internal shortcuts in documentation and examples.
Keep package names, repository references, and build commands current.
Contribution workflow documentation must require an issue before external contribution pull requests and note that NVIDIA contributors may use a GitHub or Linear issue.
Update entry-point documentation when examples or reading paths change.
Keep release-process and release-notes guidance in maintainer documentation such as RELEASING.md, rather than user-facing documentation pages or CHANGELOG.md.
Use stable user-facing wrappers at the scripts/ root in documentation and examples; reference namespaced helper paths only for internal maintenance documentation.
When detailed dynamic plugin guides exist, keep Rust native plugin examples, Python worker plugin examples, and grpc-v1 protocol details on separate pages.
Dynamic plugin manifests in documentation and examples should use compat.relay = ">=0.5,<1.0" unless deliberately narrower.
Render images, diagrams, tables, and other visual content at representative page widths, ensuring legibility and complete access without clipping; use responsive scaling, reflow, or overflow as appropriate and scope visual styling narrowly.
Dynamic plugin entry pages should link to native, worker, Rust example, Python example, and protocol pages when those pages exist.
Images, diagrams, tables, and custom visual content must remain legible and fully accessible at representative desktop and narrow page widths.
Release-policy documentation must point to GitHub Releases as the only release-history source of truth.
Run just docs when the documentation site changes; retain ./scripts/build-docs.sh html as the compatibility wrapper.

Files:

  • docs/about-nemo-relay/concepts/scopes.mdx
  • docs/instrument-applications/instrument-llm-call.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update relevant reference documentation when public behavior or APIs change.

Files:

  • docs/about-nemo-relay/concepts/scopes.mdx
  • docs/instrument-applications/instrument-llm-call.mdx
**/*.{rs,py,go,js,jsx,ts,tsx,c,h,html,md,mdx,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include the appropriate SPDX copyright and Apache-2.0 license header in every source file.

Files:

  • docs/about-nemo-relay/concepts/scopes.mdx
  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • python/nemo_relay/__init__.py
  • crates/python/src/py_api/mod.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/ffi/nemo_relay.h
  • crates/python/src/py_types/core.rs
  • docs/instrument-applications/instrument-llm-call.mdx
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • go/nemo_relay/nemo_relay.go
  • crates/ffi/src/api/scope_stack.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/node/src/api/mod.rs
**/*.{md,mdx,rst}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/assets/nvidia-style-technical-docs.md)

**/*.{md,mdx,rst}: Use title case consistently for technical documentation headings and table headers; avoid quotation marks, ampersands, and exclamation marks in headings, while preserving official product, event, research, and whitepaper title case.
Format code elements, commands, parameters, package names, expressions, directories, file names, and paths in monospace; represent path placeholders with angle brackets inside monospace.
Format UI buttons, menus, fields, and labels in bold, and separate consecutive UI navigation labels with >.
Use quotation marks for error messages and strings when appropriate, italics for newly introduced terms and publication titles, and plain text for keyboard shortcuts.
Represent GitHub repositories with owner/repository link text, such as [NVIDIA/NeMo](link), rather than generic repository wording.
Introduce every code block with a complete sentence; do not let a code block complete or interrupt the grammar of surrounding prose; use syntax highlighting when supported.
Keep inline method, function, and class references consistent with nearby documentation; omit empty parentheses in prose when no call is shown.
Use descriptive link text matching the destination title when possible; avoid raw URLs, generic anchors, long-sentence links, and unnecessary links that distract from procedures.
Ensure lists have a complete lead-in sentence, more than one item, no more than two levels, parallel construction, one idea or action per item, and appropriate punctuation; use bullets for unordered items and numbers for ordered tasks.
Format definition lists with a bold term followed by a complete, parallel, punctuated definition.
Use tables for reference information, decision support, compatibility matrices, and comparable choices; flag one-row tables, missing captions or lead-ins, sentence-case headers where title case is expected, unexplained empty cells, and code or links that would be clearer as prose.
Write procedure steps as imperative ...

Files:

  • docs/about-nemo-relay/concepts/scopes.mdx
  • docs/instrument-applications/instrument-llm-call.mdx
docs/**/*.mdx

📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)

For documentation-only changes, prefer contribute-docs plus targeted command checks.

Files:

  • docs/about-nemo-relay/concepts/scopes.mdx
  • docs/instrument-applications/instrument-llm-call.mdx
{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}

⚙️ CodeRabbit configuration file

{docs/**,README.md,CONTRIBUTING.md,RELEASING.md,SECURITY.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency across language bindings.
Flag stale examples, missing SPDX headers where required, and instructions that no longer match CI or pre-commit behavior.

Files:

  • docs/about-nemo-relay/concepts/scopes.mdx
  • docs/instrument-applications/instrument-llm-call.mdx
**/*.rs

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

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

**/*.rs: If any Rust code changed, always run just test-rust.
If any Rust code changed, also run cargo fmt --all.
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

**/*.rs: Format Rust code with rustfmt defaults using cargo fmt.
Run cargo clippy -- -D warnings; all Rust warnings must be treated as errors.
Use Rust snake_case naming conventions.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • crates/python/src/py_api/mod.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/python/src/py_types/core.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • crates/ffi/src/api/scope_stack.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/node/src/api/mod.rs
{crates/core,crates/adaptive}/**/*

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

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

Use Result<T> with FlowError in core runtime paths, keeping wrapper-layer errors explicit and binding-appropriate.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
crates/{core,adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full validation matrix across Rust, Python, Go, and Node.js.

For shared-semantics or broad runtime changes in the core or adaptive crates, run just ci=true test-rust.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
**/*.{rs,py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change.

**/*.{rs,py,go,js,ts}: Keep FFI and Python, Go, and Node.js binding configuration objects and subscriber/exporter methods aligned with the core observability configuration and lifecycle semantics.
Preserve complete sanitized LLM request input and annotations when enable_full_payloads is enabled, while retaining credential removal and sanitizers.
Use each exporter's documented flush and deregister order before shutdown in observability examples and implementations.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • python/nemo_relay/__init__.py
  • crates/python/src/py_api/mod.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/python/src/py_types/core.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • go/nemo_relay/nemo_relay.go
  • crates/ffi/src/api/scope_stack.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/node/src/api/mod.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • python/nemo_relay/__init__.py
  • crates/python/src/py_api/mod.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/python/src/py_types/core.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • go/nemo_relay/nemo_relay.go
  • crates/ffi/src/api/scope_stack.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/node/src/api/mod.rs
**/*.{rs,py,js,jsx,ts,tsx,go,c,h,cc,cpp,md,toml,yml,yaml,sh}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, documentation, scripts, and configuration files; the project is Apache-2.0.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • python/nemo_relay/__init__.py
  • crates/python/src/py_api/mod.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/ffi/nemo_relay.h
  • crates/python/src/py_types/core.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • go/nemo_relay/nemo_relay.go
  • crates/ffi/src/api/scope_stack.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/node/src/api/mod.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Use snake_case naming in Rust and Python.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • python/nemo_relay/__init__.py
  • crates/python/src/py_api/mod.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/python/src/py_types/core.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • crates/ffi/src/api/scope_stack.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/node/src/api/mod.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Use Json = serde_json::Value in Rust-facing runtime APIs where existing code expects JSON payloads.
Treat Rust as the source of truth for runtime behavior; binding APIs should mirror Rust semantics unless a language-specific wrapper intentionally improves ergonomics.

crates/**/*.rs: Runtime helpers must cover marks, scopes, continuations, and isolated scope stacks.
plugins list, plugins inspect, and plugins validate must report lifecycle and compatibility status without leaking secret configuration.
Top-level doctor must report resolved dynamic-plugin and host-configuration status.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • crates/python/src/py_api/mod.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/python/src/py_types/core.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • crates/ffi/src/api/scope_stack.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/node/src/api/mod.rs
**/*.{rs,py,js,mjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Preserve the existing Tokio-based asynchronous model and callback/future lifetimes; do not unexpectedly block or hide async work in bindings.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • python/nemo_relay/__init__.py
  • crates/python/src/py_api/mod.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/python/src/py_types/core.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • crates/ffi/src/api/scope_stack.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/node/src/api/mod.rs
**/*.{rs,py,go,js,jsx,ts,tsx,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{rs,py,go,js,jsx,ts,tsx,c,h}: Run tests for every language affected by a change; changes to the core Rust crate require tests across all bindings.
Use SONAR_IGNORE_START / SONAR_IGNORE_END only for documented false positives, keep ignored blocks minimal, explain them with a comment, and obtain reviewer sign-off.
Preserve the layered architecture in which Rust provides the core runtime and C FFI, PyO3, and NAPI provide bindings that mirror the full API surface.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • python/nemo_relay/__init__.py
  • crates/python/src/py_api/mod.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/ffi/nemo_relay.h
  • crates/python/src/py_types/core.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • go/nemo_relay/nemo_relay.go
  • crates/ffi/src/api/scope_stack.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/node/src/api/mod.rs
**/{test,tests}/**/*

📄 CodeRabbit inference engine (CONTRIBUTING.md)

When adding functionality, include tests in the appropriate test files for each affected language binding.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • crates/core/tests/integration/context_isolation_tests.rs
**/*.{toml,md,rs,py}

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

Treat plugin Relay compatibility as normal SemVer; use >=0.5,<1.0 in examples unless a plugin intentionally declares a narrower range.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • python/nemo_relay/__init__.py
  • crates/python/src/py_api/mod.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/python/src/py_types/core.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • crates/ffi/src/api/scope_stack.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/node/src/api/mod.rs
crates/{core,adaptive,plugin,worker,worker-proto,types}/**/*.{rs,toml}

📄 CodeRabbit inference engine (.agents/skills/test-rust-core/SKILL.md)

For changes in the Rust core, adaptive, dynamic plugin, worker, worker-proto, or types crates, run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings as the default validation sequence.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
crates/{core,adaptive,plugin,worker,worker-proto,types}/**/*

📄 CodeRabbit inference engine (.agents/skills/test-rust-core/SKILL.md)

crates/{core,adaptive,plugin,worker,worker-proto,types}/**/*: For changes affecting crates/core, crates/adaptive, or shared Rust runtime semantics, expand validation to the full binding matrix with validate-change.
Use narrower crate-specific tests only as a local debug loop, not as the final validation for a Rust change.
If a public API, event shape, middleware behavior, plugin semantics, or crates/core/crates/adaptive behavior changes, also run validate-change.
If the change is isolated to one binding wrapper while Rust semantics remain unchanged, prefer that binding's build/test skill instead.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • crates/core/tests/integration/context_isolation_tests.rs
{crates/python/src/py_api/mod.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go,crates/node/src/api/**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update the language-native bindings for every exposed surface in Python, Go, and Node.js.

Files:

  • python/nemo_relay/__init__.py
  • crates/python/src/py_api/mod.rs
  • python/nemo_relay/__init__.pyi
  • python/nemo_relay/_native.pyi
  • go/nemo_relay/nemo_relay.go
  • crates/node/src/api/mod.rs
{python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go}

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update language wrapper helpers such as Python wrapper modules, Python type stubs, and Go shorthand packages when the new behavior belongs in those helper layers.

Files:

  • python/nemo_relay/__init__.py
  • python/nemo_relay/__init__.pyi
  • python/nemo_relay/_native.pyi
  • go/nemo_relay/nemo_relay.go
python/nemo_relay/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Keep Python wrapper modules under python/nemo_relay/; the native extension is built from crates/python with maturin.

Files:

  • python/nemo_relay/__init__.py
**/*.py

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.py: Lint Python with Ruff using rule sets E, F, W, and I.
Format Python with the Ruff formatter, using a 120-character line length and double quotes.
Run ty for Python type checking.
Use Python snake_case naming conventions.

Files:

  • python/nemo_relay/__init__.py
python/**/*.py

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

Python SDK tests belong under python/tests, not under source directories.

python/**/*.py: Format changed Python wrapper and test files with uv run ruff format python python/plugin.
Run uv run ruff format python python/plugin after changing Python wrapper or test files.

Files:

  • python/nemo_relay/__init__.py
python/nemo_relay/**/*

⚙️ CodeRabbit configuration file

python/nemo_relay/**/*: Review Python wrapper changes for typed API consistency, contextvars-based scope isolation, async behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.

Files:

  • python/nemo_relay/__init__.py
  • python/nemo_relay/__init__.pyi
  • python/nemo_relay/_native.pyi
crates/**/src/**/*.rs

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

Do not add tests under src; Rust tests belong in crate tests/ trees.

Files:

  • crates/python/src/py_api/mod.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/python/src/py_types/core.rs
  • crates/core/src/observability/mod.rs
  • crates/ffi/src/api/scope_stack.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/node/src/api/mod.rs
crates/python/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)

crates/python/**/*.rs: When Rust files change as part of Python work, run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings.
When the native Rust bridge changes, add and run the Rust crate tests for nemo-relay-python, including cargo test -p nemo-relay-python.

Files:

  • crates/python/src/py_api/mod.rs
  • crates/python/src/py_types/core.rs
crates/{python,ffi,node}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.

Files:

  • crates/python/src/py_api/mod.rs
  • crates/ffi/nemo_relay.h
  • crates/python/src/py_types/core.rs
  • crates/ffi/src/api/scope_stack.rs
  • crates/node/src/api/mod.rs
crates/core/src/{api/**/*.rs,api/runtime/**/*.rs,codec/**/*.rs,json.rs}

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Implement the new or changed public runtime behavior first in the Rust core, especially under crates/core/src/api/ and related core modules such as crates/core/src/api/runtime/, crates/core/src/codec/, and crates/core/src/json.rs.

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
crates/core/src/api/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

Preserve the documented pipeline order: conditional guardrails, request intercepts, request sanitization, execution intercepts, and response sanitization for tool and LLM execution; specialized sanitization, event creation, and dispatch for mark and scope events.

Files:

  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
crates/core/src/api/runtime/state.rs

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

crates/core/src/api/runtime/state.rs: Add a SortedRegistry<GuardrailEntry<...>> or SortedRegistry<Intercept<...>> field to NemoRelayContextState for the new middleware type.
Add chain-execution helpers to NemoRelayContextState, following existing helpers such as tool_sanitize_request_chain or tool_request_intercepts_chain.

Files:

  • crates/core/src/api/runtime/state.rs
crates/ffi/**

📄 CodeRabbit inference engine (.agents/skills/test-ffi-surface/SKILL.md)

Rebuild the FFI crate in release mode so the shared library and header stay in sync when making changes to crates/ffi

Files:

  • crates/ffi/nemo_relay.h
  • crates/ffi/src/api/scope_stack.rs
crates/ffi/nemo_relay.h

📄 CodeRabbit inference engine (.agents/skills/test-ffi-surface/SKILL.md)

Check the generated header diff when any exported symbol or type changed in the FFI surface

Update generated or generated-from-build surfaces such as crates/ffi/nemo_relay.h through the proper build step.

Files:

  • crates/ffi/nemo_relay.h
{crates/ffi/src/api/*.rs,crates/ffi/nemo_relay.h}

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Add or update the shared C/FFI surface in the relevant crates/ffi/src/api/*.rs module, re-export it through crates/ffi/src/api/mod.rs, and keep the generated crates/ffi/nemo_relay.h header correct.

Files:

  • crates/ffi/nemo_relay.h
  • crates/ffi/src/api/scope_stack.rs
**/*.{c,h,cc,cpp}

📄 CodeRabbit inference engine (AGENTS.md)

Prefix C FFI exports with nemo_relay_.

Files:

  • crates/ffi/nemo_relay.h
**/*.{c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Prefix C FFI exports with nemo_relay_.

Files:

  • crates/ffi/nemo_relay.h
crates/core/src/observability/*.rs

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

crates/core/src/observability/*.rs: Ensure OpenTelemetry endpoints have a type and nonblank destination; resolve header_env values at activation and reject missing, blank, or duplicate headers.
Concatenate layered ATOF sink, ATIF storage, and OpenTelemetry endpoint lists with higher-precedence entries first.
For the gen_ai projection, avoid nemo_relay.* attributes, map sanitized LLM instructions and messages to standard content attributes, and emit minimal spans for scopes without GenAI semantics to preserve parentage.
Correctly handle mark events, start and end events, orphan cases, and derive span or trajectory fields from the intended event data.
For observability configuration version 3, use one opentelemetry section containing typed endpoints, with no standalone public OpenInference surface.

Files:

  • crates/core/src/observability/mod.rs
go/nemo_relay/**/*.go

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

go/nemo_relay/**/*.go: Format changed Go packages with cd go/nemo_relay && go fmt ./...
Run Go tests with just test-go to build and test the NeMo Relay Go binding
Use just build-go when you want an explicit build-only pass or need the artifact for other work
Use just ci=true test-go when you need the CI-style coverage and JUnit path
On macOS, set DYLD_LIBRARY_PATH to the ../../target/release directory before running the raw go test command directly

Files:

  • go/nemo_relay/nemo_relay.go
go/nemo_relay/**

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

Keep shared plugin helpers in go/nemo_relay aligned with plugin registration, composition, and lifecycle behavior.

Files:

  • go/nemo_relay/nemo_relay.go
go/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Use PascalCase for public Go APIs.

Files:

  • go/nemo_relay/nemo_relay.go
**/*.go

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.go: Format Go code with gofmt.
Run go vet ./... for Go static analysis.
Use Go PascalCase naming conventions.

Files:

  • go/nemo_relay/nemo_relay.go
go/nemo_relay/**/*

⚙️ CodeRabbit configuration file

go/nemo_relay/**/*: Review Go binding changes for cgo memory ownership, race safety, callback cleanup, idiomatic exported APIs, and parity with Rust/FFI behavior.
Any API change should include focused Go tests and consider race-test behavior.

Files:

  • go/nemo_relay/nemo_relay.go
crates/ffi/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/ffi, also use test-ffi-surface for validation

Files:

  • crates/ffi/src/api/scope_stack.rs
crates/core/src/api/{tool,llm,shared,scope}.rs

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

Wire the new middleware chain into the appropriate lifecycle owner and pipeline stage: tool and LLM execution paths use tool.rs or llm.rs; shared mark and scope event sanitization uses shared.rs and is called from scope.rs.

Files:

  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
🧠 Learnings (4)
📚 Learning: 2026-08-03T19:55:03.931Z
Learnt from: afourniernv
Repo: NVIDIA/NeMo-Relay PR: 558
File: crates/pii-redaction/src/rampart/mod.rs:265-274
Timestamp: 2026-08-03T19:55:03.931Z
Learning: In NeMo Relay first-party plugin registration helpers, treat the documented duplicate-registration `PluginError::RegistrationFailed` result from `register_plugin` as success when registration is intended to be idempotent. Do not locally reclassify this as `PluginError::Conflict`; changing the classification requires a core-wide review of the public API and FFI behavior.

Applied to files:

  • crates/core/tests/unit/llm_api_tests.rs
  • crates/core/tests/integration/middleware_tests.rs
  • crates/python/src/py_api/mod.rs
  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/python/src/py_types/core.rs
  • crates/core/tests/integration/context_isolation_tests.rs
  • crates/core/src/observability/mod.rs
  • crates/ffi/src/api/scope_stack.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
  • crates/node/src/api/mod.rs
📚 Learning: 2026-07-28T20:07:29.880Z
Learnt from: willkill07
Repo: NVIDIA/NeMo-Relay PR: 571
File: crates/core/src/api/runtime/state.rs:996-1020
Timestamp: 2026-07-28T20:07:29.880Z
Learning: In NeMo Relay (RELAY-509), sanitizer callback failures must be treated as intentional fail-open behavior. When an event/tool (request/response) or LLM (request/response) sanitizer callback fails, the sanitizer chain should retain and publish the last valid event/payload snapshot (rather than dropping/invalidating the data) and log the failure including callback context (e.g., which sanitizer/callback failed and relevant identifiers). Apply this consistently across all sanitizer chains mentioned in the RELAY-509 documentation/migration guide.

Applied to files:

  • crates/core/src/api/runtime.rs
  • crates/core/src/api/runtime/state.rs
  • crates/core/src/observability/mod.rs
  • crates/core/src/api/llm.rs
  • crates/core/src/api/shared.rs
  • crates/core/src/api/runtime/scope_stack.rs
📚 Learning: 2026-07-28T03:31:05.964Z
Learnt from: willkill07
Repo: NVIDIA/NeMo-Relay PR: 564
File: crates/core/src/api/runtime/subscriber_dispatcher.rs:297-314
Timestamp: 2026-07-28T03:31:05.964Z
Learning: In this codebase’s runtime API, do not implement incremental native LLM stream forwarding via the native ABI v3 asynchronous middleware protocol (it can only settle a single JSON value via a one-shot completion handle and cannot forward stream chunks incrementally). If a latency-sensitive plugin needs streaming behavior, review for use of synchronous native stream intercepts or worker plugins instead of trying to chunk-deliver or incrementally forward over the ABI v3 async path.

Applied to files:

  • crates/core/src/api/runtime/state.rs
  • crates/core/src/api/runtime/scope_stack.rs
📚 Learning: 2026-07-28T23:57:11.641Z
Learnt from: willkill07
Repo: NVIDIA/NeMo-Relay PR: 570
File: crates/node/src/api/mod.rs:3265-3282
Timestamp: 2026-07-28T23:57:11.641Z
Learning: In the Node.js binding, `flushSubscribers()` is Promise-based/async and must be awaited. Any session-close or teardown path (e.g., the OpenClaw live smoke session-close flow) must await `flushSubscribers()` before continuing to live ATIF export assertions and before teardown, so queued subscriber delivery fully completes and tests/assertions observe the final state.

Applied to files:

  • crates/node/src/api/mod.rs
🔇 Additional comments (19)
crates/ffi/nemo_relay.h (1)

2344-2363: LGTM!

crates/ffi/src/api/scope_stack.rs (1)

9-12: LGTM!

Also applies to: 126-182

go/nemo_relay/nemo_relay.go (1)

237-238: LGTM!

Also applies to: 1616-1630, 1679-1687

crates/node/src/api/mod.rs (1)

44-44: LGTM!

Also applies to: 1742-1749

crates/python/src/py_api/mod.rs (1)

29-29: LGTM!

Also applies to: 389-393, 2111-2111

crates/python/src/py_types/core.rs (1)

261-266: LGTM!

python/nemo_relay/__init__.py (1)

132-132: LGTM!

Also applies to: 591-591

python/nemo_relay/__init__.pyi (1)

399-399: LGTM!

python/nemo_relay/_native.pyi (1)

1296-1306: LGTM!

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

288-294: LGTM!

docs/instrument-applications/instrument-llm-call.mdx (1)

42-47: LGTM!

crates/core/src/api/runtime/scope_stack.rs (1)

37-37: LGTM!

Also applies to: 70-83, 124-124, 144-144, 186-186, 513-550

crates/core/src/observability/mod.rs (1)

100-113: LGTM!

crates/core/src/api/runtime.rs (1)

29-32: LGTM!

crates/core/tests/integration/context_isolation_tests.rs (1)

9-9: LGTM!

Also applies to: 148-175

crates/core/src/api/llm.rs (1)

33-40: LGTM!

Also applies to: 145-148, 1449-1488, 1661-1700, 1811-1813

crates/core/src/api/runtime/state.rs (1)

611-621: LGTM!

crates/core/src/api/shared.rs (1)

12-12: LGTM!

Also applies to: 29-30, 188-202

crates/core/tests/integration/middleware_tests.rs (1)

3552-3589: LGTM!

Comment thread crates/core/tests/unit/llm_api_tests.rs Outdated
Comment thread crates/node/src/api/mod.rs
@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

Signed-off-by: Will Killian <wkillian@nvidia.com>
@github-actions github-actions Bot added the lang:js PR changes/introduces Javascript/Typescript code label Aug 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/core/tests/integration/pipeline_tests.rs`:
- Around line 502-511: Normalize only the runtime-owned traceparent header while
retaining complete equality checks: in
crates/core/tests/integration/pipeline_tests.rs:502-511, compare the normalized
LlmRequest with original rather than only unchanged.content; in
crates/node/tests/callback_error_tests.mjs:54-55 and
crates/node/tests/llm_tests.mjs:830-831, remove or destructure
result.headers.traceparent, deep-compare the remaining result with the expected
value, then validate the extracted traceparent separately.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: eff5cc36-70b0-4a86-96c9-23563d11cd88

📥 Commits

Reviewing files that changed from the base of the PR and between 92ba36f and 4e523c9.

📒 Files selected for processing (3)
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/node/tests/callback_error_tests.mjs
  • crates/node/tests/llm_tests.mjs
📜 Review details
⏰ Context from checks skipped due to timeout. (44)
  • GitHub Check: Rust / Test (linux-amd64)
  • GitHub Check: Rust / Package (windows-amd64)
  • GitHub Check: Rust / Package (macos-arm64)
  • GitHub Check: Rust / Package (linux-musl-amd64)
  • GitHub Check: Node.js / Package (linux-musl-amd64)
  • GitHub Check: Python / Package (windows-arm64)
  • GitHub Check: Rust / Package (windows-arm64)
  • GitHub Check: Node.js / Package (linux-arm64)
  • GitHub Check: Python / Package (linux-musl-arm64)
  • GitHub Check: Python / Package (linux-arm64)
  • GitHub Check: Node.js / Package (linux-musl-arm64)
  • GitHub Check: Python / Package (linux-musl-amd64)
  • GitHub Check: Node.js / Package (windows-arm64)
  • GitHub Check: Rust / Package (linux-musl-arm64)
  • GitHub Check: Python / Package (windows-amd64)
  • GitHub Check: Rust / Package (linux-amd64)
  • GitHub Check: Rust / Package (linux-arm64)
  • GitHub Check: Python / Package (linux-amd64)
  • GitHub Check: Python / Test (windows-arm64)
  • GitHub Check: Node.js / Package (windows-amd64)
  • GitHub Check: Python / Package (macos-arm64)
  • GitHub Check: Node.js / Package (macos-arm64)
  • GitHub Check: Rust / Test (windows-amd64)
  • GitHub Check: Python / Test (linux-amd64)
  • GitHub Check: Rust / Test (windows-arm64)
  • GitHub Check: Go / Test (macos-arm64)
  • GitHub Check: Python / Test (windows-amd64)
  • GitHub Check: Rust / Test (macos-arm64)
  • GitHub Check: Python / Test (linux-arm64)
  • GitHub Check: Python / Test (macos-arm64)
  • GitHub Check: Rust / Test (linux-arm64)
  • GitHub Check: Node.js / Package (linux-amd64)
  • GitHub Check: Node.js / Test (windows-arm64)
  • GitHub Check: Node.js / Test (macos-arm64)
  • GitHub Check: Go / Test (linux-amd64)
  • GitHub Check: Check / Run
  • GitHub Check: Go / Test (windows-arm64)
  • GitHub Check: Node.js / Test (linux-arm64)
  • GitHub Check: Go / Test (linux-arm64)
  • GitHub Check: Go / Test (windows-amd64)
  • GitHub Check: Node.js / Test (windows-amd64)
  • GitHub Check: Node.js / Test (linux-amd64)
  • GitHub Check: Node.js / Package OpenClaw plugin
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (21)
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, use maintain-dynamic-plugins and include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

**/*: Use release tags in raw Rust-compatible SemVer without a leading v; tags such as v0.1.0 are prohibited.
Use branch prefixes feat/, fix/, docs/, test/, or refactor/ according to the change purpose.
Every commit in a pull request must include a DCO Signed-off-by: sign-off.
Before submitting a pull request, ensure pre-commit hooks, relevant tests, target-specific builds, documentation updates, and a rebase on the latest main are complete.
Use commit messages in the form type: short description, with a valid type and a first line under 72 characters.

Run the prescribed plugin validation commands, including fixture building, focused Rust and Python package tests, integration tests, documentation checks, and the broader validate-change matrix for broad runtime or public API changes.

**/*: Keep observability changes scoped, surface assumptions, and define focused validation before editing.
Run affected Rust tests and just test-rust for event-field changes; run just test-python, just test-go, and just test-node when binding-native configuration or lifecycle changes; update docs and examples in the same branch.

Files:

  • crates/node/tests/callback_error_tests.mjs
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/node/tests/llm_tests.mjs
crates/node/**/*.{js,mjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use camelCase naming for Node.js APIs.

Files:

  • crates/node/tests/callback_error_tests.mjs
  • crates/node/tests/llm_tests.mjs
**/*.{rs,py,js,mjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Preserve the existing Tokio-based asynchronous model and callback/future lifetimes; do not unexpectedly block or hide async work in bindings.

Files:

  • crates/node/tests/callback_error_tests.mjs
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/node/tests/llm_tests.mjs
**/{test,tests}/**/*

📄 CodeRabbit inference engine (CONTRIBUTING.md)

When adding functionality, include tests in the appropriate test files for each affected language binding.

Files:

  • crates/node/tests/callback_error_tests.mjs
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/node/tests/llm_tests.mjs
crates/{python,ffi,node}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.

Files:

  • crates/node/tests/callback_error_tests.mjs
  • crates/node/tests/llm_tests.mjs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/node/tests/callback_error_tests.mjs
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/node/tests/llm_tests.mjs
**/*.rs

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

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

**/*.rs: If any Rust code changed, always run just test-rust.
If any Rust code changed, also run cargo fmt --all.
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

**/*.rs: Format Rust code with rustfmt defaults using cargo fmt.
Run cargo clippy -- -D warnings; all Rust warnings must be treated as errors.
Use Rust snake_case naming conventions.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
{crates/core,crates/adaptive}/**/*

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

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/tests/integration/pipeline_tests.rs
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

Use Result<T> with FlowError in core runtime paths, keeping wrapper-layer errors explicit and binding-appropriate.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
crates/{core,adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full validation matrix across Rust, Python, Go, and Node.js.

For shared-semantics or broad runtime changes in the core or adaptive crates, run just ci=true test-rust.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
**/*.{rs,py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change.

**/*.{rs,py,go,js,ts}: Keep FFI and Python, Go, and Node.js binding configuration objects and subscriber/exporter methods aligned with the core observability configuration and lifecycle semantics.
Preserve complete sanitized LLM request input and annotations when enable_full_payloads is enabled, while retaining credential removal and sanitizers.
Use each exporter's documented flush and deregister order before shutdown in observability examples and implementations.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
**/*.{rs,py,js,jsx,ts,tsx,go,c,h,cc,cpp,md,toml,yml,yaml,sh}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, documentation, scripts, and configuration files; the project is Apache-2.0.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Use snake_case naming in Rust and Python.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Use Json = serde_json::Value in Rust-facing runtime APIs where existing code expects JSON payloads.
Treat Rust as the source of truth for runtime behavior; binding APIs should mirror Rust semantics unless a language-specific wrapper intentionally improves ergonomics.

crates/**/*.rs: Runtime helpers must cover marks, scopes, continuations, and isolated scope stacks.
plugins list, plugins inspect, and plugins validate must report lifecycle and compatibility status without leaking secret configuration.
Top-level doctor must report resolved dynamic-plugin and host-configuration status.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
**/*.{rs,py,go,js,jsx,ts,tsx,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{rs,py,go,js,jsx,ts,tsx,c,h}: Run tests for every language affected by a change; changes to the core Rust crate require tests across all bindings.
Use SONAR_IGNORE_START / SONAR_IGNORE_END only for documented false positives, keep ignored blocks minimal, explain them with a comment, and obtain reviewer sign-off.
Preserve the layered architecture in which Rust provides the core runtime and C FFI, PyO3, and NAPI provide bindings that mirror the full API surface.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
**/*.{rs,py,go,js,jsx,ts,tsx,c,h,html,md,mdx,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include the appropriate SPDX copyright and Apache-2.0 license header in every source file.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
**/*.{toml,md,rs,py}

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

Treat plugin Relay compatibility as normal SemVer; use >=0.5,<1.0 in examples unless a plugin intentionally declares a narrower range.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
crates/{core,adaptive,plugin,worker,worker-proto,types}/**/*.{rs,toml}

📄 CodeRabbit inference engine (.agents/skills/test-rust-core/SKILL.md)

For changes in the Rust core, adaptive, dynamic plugin, worker, worker-proto, or types crates, run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings as the default validation sequence.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
crates/{core,adaptive,plugin,worker,worker-proto,types}/**/*

📄 CodeRabbit inference engine (.agents/skills/test-rust-core/SKILL.md)

crates/{core,adaptive,plugin,worker,worker-proto,types}/**/*: For changes affecting crates/core, crates/adaptive, or shared Rust runtime semantics, expand validation to the full binding matrix with validate-change.
Use narrower crate-specific tests only as a local debug loop, not as the final validation for a Rust change.
If a public API, event shape, middleware behavior, plugin semantics, or crates/core/crates/adaptive behavior changes, also run validate-change.
If the change is isolated to one binding wrapper while Rust semantics remain unchanged, prefer that binding's build/test skill instead.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
🧠 Learnings (1)
📚 Learning: 2026-08-03T19:55:03.931Z
Learnt from: afourniernv
Repo: NVIDIA/NeMo-Relay PR: 558
File: crates/pii-redaction/src/rampart/mod.rs:265-274
Timestamp: 2026-08-03T19:55:03.931Z
Learning: In NeMo Relay first-party plugin registration helpers, treat the documented duplicate-registration `PluginError::RegistrationFailed` result from `register_plugin` as success when registration is intended to be idempotent. Do not locally reclassify this as `PluginError::Conflict`; changing the classification requires a core-wide review of the public API and FFI behavior.

Applied to files:

  • crates/core/tests/integration/pipeline_tests.rs
🔇 Additional comments (1)
crates/core/tests/integration/pipeline_tests.rs (1)

555-563: LGTM!

Comment thread crates/core/tests/integration/pipeline_tests.rs Outdated
Signed-off-by: Will Killian <wkillian@nvidia.com>
@github-actions github-actions Bot added size:L PR is large and removed size:M PR is medium labels Aug 10, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/core/tests/unit/llm_api_tests.rs`:
- Around line 397-425: Extend the LLM API test fixture to include a
user-supplied mixed-case TraceParent header, then update both provider-path
assertions around provider_requests to count header names case-insensitively and
require exactly one traceparent key. Validate the surviving header’s injected
value and retain the existing event-payload and traceparent correlation checks
for both providers.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: f150db4c-f31c-446e-b76c-a89af6dc4c18

📥 Commits

Reviewing files that changed from the base of the PR and between 4e523c9 and a4a4557.

📒 Files selected for processing (8)
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • crates/node/src/api/mod.rs
  • crates/node/tests/callback_error_tests.mjs
  • crates/node/tests/llm_tests.mjs
  • go/nemo_relay/context_test.go
  • python/nemo_relay/__init__.py
  • python/tests/test_llm.py
📜 Review details
⏰ Context from checks skipped due to timeout. (28)
  • GitHub Check: Rust / Package (windows-amd64)
  • GitHub Check: Rust / Package (macos-arm64)
  • GitHub Check: Rust / Package (windows-arm64)
  • GitHub Check: Node.js / Package (windows-amd64)
  • GitHub Check: Python / Package (linux-musl-amd64)
  • GitHub Check: Node.js / Package (linux-musl-arm64)
  • GitHub Check: Rust / Package (linux-amd64)
  • GitHub Check: Node.js / Package (macos-arm64)
  • GitHub Check: Python / Package (windows-arm64)
  • GitHub Check: Node.js / Package (windows-arm64)
  • GitHub Check: Node.js / Package (linux-musl-amd64)
  • GitHub Check: Go / Test (windows-amd64)
  • GitHub Check: Go / Test (windows-arm64)
  • GitHub Check: Python / Package (linux-musl-arm64)
  • GitHub Check: Python / Package (windows-amd64)
  • GitHub Check: Rust / Test (windows-amd64)
  • GitHub Check: Python / Package (linux-amd64)
  • GitHub Check: Python / Test (linux-amd64)
  • GitHub Check: Python / Test (macos-arm64)
  • GitHub Check: Rust / Test (windows-arm64)
  • GitHub Check: Rust / Test (macos-arm64)
  • GitHub Check: Node.js / Test (windows-arm64)
  • GitHub Check: Python / Test (windows-amd64)
  • GitHub Check: Python / Test (windows-arm64)
  • GitHub Check: Node.js / Test (windows-amd64)
  • GitHub Check: Rust / Test (linux-amd64)
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (34)
{crates/python/src/py_api/mod.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go,crates/node/src/api/**/*.rs}

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update the language-native bindings for every exposed surface in Python, Go, and Node.js.

Files:

  • python/nemo_relay/__init__.py
  • go/nemo_relay/context_test.go
  • crates/node/src/api/mod.rs
{python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go}

📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)

Update language wrapper helpers such as Python wrapper modules, Python type stubs, and Go shorthand packages when the new behavior belongs in those helper layers.

Files:

  • python/nemo_relay/__init__.py
  • go/nemo_relay/context_test.go
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, use maintain-dynamic-plugins and include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

**/*: Use release tags in raw Rust-compatible SemVer without a leading v; tags such as v0.1.0 are prohibited.
Use branch prefixes feat/, fix/, docs/, test/, or refactor/ according to the change purpose.
Every commit in a pull request must include a DCO Signed-off-by: sign-off.
Before submitting a pull request, ensure pre-commit hooks, relevant tests, target-specific builds, documentation updates, and a rebase on the latest main are complete.
Use commit messages in the form type: short description, with a valid type and a first line under 72 characters.

Run the prescribed plugin validation commands, including fixture building, focused Rust and Python package tests, integration tests, documentation checks, and the broader validate-change matrix for broad runtime or public API changes.

**/*: Keep observability changes scoped, surface assumptions, and define focused validation before editing.
Run affected Rust tests and just test-rust for event-field changes; run just test-python, just test-go, and just test-node when binding-native configuration or lifecycle changes; update docs and examples in the same branch.

Files:

  • python/nemo_relay/__init__.py
  • crates/node/tests/callback_error_tests.mjs
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • python/tests/test_llm.py
  • go/nemo_relay/context_test.go
  • crates/node/tests/llm_tests.mjs
  • crates/node/src/api/mod.rs
**/*.{rs,py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change.

**/*.{rs,py,go,js,ts}: Keep FFI and Python, Go, and Node.js binding configuration objects and subscriber/exporter methods aligned with the core observability configuration and lifecycle semantics.
Preserve complete sanitized LLM request input and annotations when enable_full_payloads is enabled, while retaining credential removal and sanitizers.
Use each exporter's documented flush and deregister order before shutdown in observability examples and implementations.

Files:

  • python/nemo_relay/__init__.py
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • python/tests/test_llm.py
  • go/nemo_relay/context_test.go
  • crates/node/src/api/mod.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.

Files:

  • python/nemo_relay/__init__.py
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • python/tests/test_llm.py
  • go/nemo_relay/context_test.go
  • crates/node/src/api/mod.rs
**/*.{rs,py,js,jsx,ts,tsx,go,c,h,cc,cpp,md,toml,yml,yaml,sh}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, documentation, scripts, and configuration files; the project is Apache-2.0.

Files:

  • python/nemo_relay/__init__.py
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • python/tests/test_llm.py
  • go/nemo_relay/context_test.go
  • crates/node/src/api/mod.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Use snake_case naming in Rust and Python.

Files:

  • python/nemo_relay/__init__.py
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • python/tests/test_llm.py
  • crates/node/src/api/mod.rs
**/*.{rs,py,js,mjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Preserve the existing Tokio-based asynchronous model and callback/future lifetimes; do not unexpectedly block or hide async work in bindings.

Files:

  • python/nemo_relay/__init__.py
  • crates/node/tests/callback_error_tests.mjs
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • python/tests/test_llm.py
  • crates/node/tests/llm_tests.mjs
  • crates/node/src/api/mod.rs
python/nemo_relay/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Keep Python wrapper modules under python/nemo_relay/; the native extension is built from crates/python with maturin.

Files:

  • python/nemo_relay/__init__.py
**/*.py

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.py: Lint Python with Ruff using rule sets E, F, W, and I.
Format Python with the Ruff formatter, using a 120-character line length and double quotes.
Run ty for Python type checking.
Use Python snake_case naming conventions.

Files:

  • python/nemo_relay/__init__.py
  • python/tests/test_llm.py
**/*.{rs,py,go,js,jsx,ts,tsx,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{rs,py,go,js,jsx,ts,tsx,c,h}: Run tests for every language affected by a change; changes to the core Rust crate require tests across all bindings.
Use SONAR_IGNORE_START / SONAR_IGNORE_END only for documented false positives, keep ignored blocks minimal, explain them with a comment, and obtain reviewer sign-off.
Preserve the layered architecture in which Rust provides the core runtime and C FFI, PyO3, and NAPI provide bindings that mirror the full API surface.

Files:

  • python/nemo_relay/__init__.py
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • python/tests/test_llm.py
  • go/nemo_relay/context_test.go
  • crates/node/src/api/mod.rs
**/*.{rs,py,go,js,jsx,ts,tsx,c,h,html,md,mdx,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include the appropriate SPDX copyright and Apache-2.0 license header in every source file.

Files:

  • python/nemo_relay/__init__.py
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • python/tests/test_llm.py
  • go/nemo_relay/context_test.go
  • crates/node/src/api/mod.rs
**/*.{toml,md,rs,py}

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

Treat plugin Relay compatibility as normal SemVer; use >=0.5,<1.0 in examples unless a plugin intentionally declares a narrower range.

Files:

  • python/nemo_relay/__init__.py
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • python/tests/test_llm.py
  • crates/node/src/api/mod.rs
python/**/*.py

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

Python SDK tests belong under python/tests, not under source directories.

python/**/*.py: Format changed Python wrapper and test files with uv run ruff format python python/plugin.
Run uv run ruff format python python/plugin after changing Python wrapper or test files.

Files:

  • python/nemo_relay/__init__.py
  • python/tests/test_llm.py
python/nemo_relay/**/*

⚙️ CodeRabbit configuration file

python/nemo_relay/**/*: Review Python wrapper changes for typed API consistency, contextvars-based scope isolation, async behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.

Files:

  • python/nemo_relay/__init__.py
crates/node/**/*.{js,mjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use camelCase naming for Node.js APIs.

Files:

  • crates/node/tests/callback_error_tests.mjs
  • crates/node/tests/llm_tests.mjs
**/{test,tests}/**/*

📄 CodeRabbit inference engine (CONTRIBUTING.md)

When adding functionality, include tests in the appropriate test files for each affected language binding.

Files:

  • crates/node/tests/callback_error_tests.mjs
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • python/tests/test_llm.py
  • crates/node/tests/llm_tests.mjs
crates/{python,ffi,node}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.

Files:

  • crates/node/tests/callback_error_tests.mjs
  • crates/node/tests/llm_tests.mjs
  • crates/node/src/api/mod.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/node/tests/callback_error_tests.mjs
  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • python/tests/test_llm.py
  • go/nemo_relay/context_test.go
  • crates/node/tests/llm_tests.mjs
**/*.rs

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

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

**/*.rs: If any Rust code changed, always run just test-rust.
If any Rust code changed, also run cargo fmt --all.
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

**/*.rs: Format Rust code with rustfmt defaults using cargo fmt.
Run cargo clippy -- -D warnings; all Rust warnings must be treated as errors.
Use Rust snake_case naming conventions.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • crates/node/src/api/mod.rs
{crates/core,crates/adaptive}/**/*

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

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

Use Result<T> with FlowError in core runtime paths, keeping wrapper-layer errors explicit and binding-appropriate.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
crates/{core,adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full validation matrix across Rust, Python, Go, and Node.js.

For shared-semantics or broad runtime changes in the core or adaptive crates, run just ci=true test-rust.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Use Json = serde_json::Value in Rust-facing runtime APIs where existing code expects JSON payloads.
Treat Rust as the source of truth for runtime behavior; binding APIs should mirror Rust semantics unless a language-specific wrapper intentionally improves ergonomics.

crates/**/*.rs: Runtime helpers must cover marks, scopes, continuations, and isolated scope stacks.
plugins list, plugins inspect, and plugins validate must report lifecycle and compatibility status without leaking secret configuration.
Top-level doctor must report resolved dynamic-plugin and host-configuration status.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • crates/node/src/api/mod.rs
crates/{core,adaptive,plugin,worker,worker-proto,types}/**/*.{rs,toml}

📄 CodeRabbit inference engine (.agents/skills/test-rust-core/SKILL.md)

For changes in the Rust core, adaptive, dynamic plugin, worker, worker-proto, or types crates, run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings as the default validation sequence.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
crates/{core,adaptive,plugin,worker,worker-proto,types}/**/*

📄 CodeRabbit inference engine (.agents/skills/test-rust-core/SKILL.md)

crates/{core,adaptive,plugin,worker,worker-proto,types}/**/*: For changes affecting crates/core, crates/adaptive, or shared Rust runtime semantics, expand validation to the full binding matrix with validate-change.
Use narrower crate-specific tests only as a local debug loop, not as the final validation for a Rust change.
If a public API, event shape, middleware behavior, plugin semantics, or crates/core/crates/adaptive behavior changes, also run validate-change.
If the change is isolated to one binding wrapper while Rust semantics remain unchanged, prefer that binding's build/test skill instead.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
python/tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Maintain test coverage for Python binding and wrapper changes with the Python test suite.

python/tests/**/*.py: Use pytest to run Python tests.
Do not add @pytest.mark.asyncio to tests; async tests are automatically detected by the async runner.
Do not add a -> None return type annotation to test functions.
When mocking a class, use unittest.mock.MagicMock or unittest.mock.AsyncMock, using spec when necessary, rather than defining a new class.
Prefix mocked class names with mock, not fake.
Prefer pytest fixtures over helper methods.
If a fixture is needed in multiple test files, define it in a conftest.py file instead of repeating it.
Define fixtures using @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) and a <fixture_name>_fixture function; specify scope only when it is not function.
Prefer pytest.mark.parametrize over separate tests for different input types.
Run focused pytest tests first when the affected area is known, and run the full suite with just test-python before review.

Files:

  • python/tests/test_llm.py
go/nemo_relay/**/*.go

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

go/nemo_relay/**/*.go: Format changed Go packages with cd go/nemo_relay && go fmt ./...
Run Go tests with just test-go to build and test the NeMo Relay Go binding
Use just build-go when you want an explicit build-only pass or need the artifact for other work
Use just ci=true test-go when you need the CI-style coverage and JUnit path
On macOS, set DYLD_LIBRARY_PATH to the ../../target/release directory before running the raw go test command directly

Files:

  • go/nemo_relay/context_test.go
go/nemo_relay/**

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

Keep shared plugin helpers in go/nemo_relay aligned with plugin registration, composition, and lifecycle behavior.

Files:

  • go/nemo_relay/context_test.go
go/**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

Use PascalCase for public Go APIs.

Files:

  • go/nemo_relay/context_test.go
**/*.go

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.go: Format Go code with gofmt.
Run go vet ./... for Go static analysis.
Use Go PascalCase naming conventions.

Files:

  • go/nemo_relay/context_test.go
go/nemo_relay/**/*

⚙️ CodeRabbit configuration file

go/nemo_relay/**/*: Review Go binding changes for cgo memory ownership, race safety, callback cleanup, idiomatic exported APIs, and parity with Rust/FFI behavior.
Any API change should include focused Go tests and consider race-test behavior.

Files:

  • go/nemo_relay/context_test.go
crates/**/src/**/*.rs

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

Do not add tests under src; Rust tests belong in crate tests/ trees.

Files:

  • crates/node/src/api/mod.rs
🧠 Learnings (3)
📚 Learning: 2026-08-03T19:55:03.931Z
Learnt from: afourniernv
Repo: NVIDIA/NeMo-Relay PR: 558
File: crates/pii-redaction/src/rampart/mod.rs:265-274
Timestamp: 2026-08-03T19:55:03.931Z
Learning: In NeMo Relay first-party plugin registration helpers, treat the documented duplicate-registration `PluginError::RegistrationFailed` result from `register_plugin` as success when registration is intended to be idempotent. Do not locally reclassify this as `PluginError::Conflict`; changing the classification requires a core-wide review of the public API and FFI behavior.

Applied to files:

  • crates/core/tests/integration/pipeline_tests.rs
  • crates/core/tests/unit/llm_api_tests.rs
  • crates/node/src/api/mod.rs
📚 Learning: 2026-07-28T20:33:25.156Z
Learnt from: willkill07
Repo: NVIDIA/NeMo-Relay PR: 572
File: go/nemo_relay/adaptive_runtime_test.go:214-238
Timestamp: 2026-07-28T20:33:25.156Z
Learning: When adding/adjusting Go unit tests for `BuildCacheRequestFacts` (request-ID validation and related request parsing), set `CacheRequestFactsInput.Provider` to a valid provider in all tests that are intended to isolate request-ID behavior—because `BuildCacheRequestFacts` does not validate `Provider`. Then add separate test coverage for malformed `AnnotatedRequest` JSON so JSON parsing failures are not conflated with `Provider`-related inputs.

Applied to files:

  • go/nemo_relay/context_test.go
📚 Learning: 2026-07-28T23:57:11.641Z
Learnt from: willkill07
Repo: NVIDIA/NeMo-Relay PR: 570
File: crates/node/src/api/mod.rs:3265-3282
Timestamp: 2026-07-28T23:57:11.641Z
Learning: In the Node.js binding, `flushSubscribers()` is Promise-based/async and must be awaited. Any session-close or teardown path (e.g., the OpenClaw live smoke session-close flow) must await `flushSubscribers()` before continuing to live ATIF export assertions and before teardown, so queued subscriber delivery fully completes and tests/assertions observe the final state.

Applied to files:

  • crates/node/src/api/mod.rs
🪛 Ruff (0.16.1)
python/tests/test_llm.py

[warning] 615-615: Missing return type annotation for private function execution_intercept

(ANN202)


[warning] 619-619: Missing return type annotation for private function provider

(ANN202)

🔇 Additional comments (10)
go/nemo_relay/context_test.go (2)

10-10: LGTM!


306-330: LGTM!

crates/node/src/api/mod.rs (1)

1729-1739: LGTM!

python/nemo_relay/__init__.py (1)

445-451: LGTM!

crates/node/tests/callback_error_tests.mjs (1)

54-56: LGTM!

python/tests/test_llm.py (2)

24-24: LGTM!


610-633: LGTM!

crates/core/tests/integration/pipeline_tests.rs (1)

502-511: LGTM!

Also applies to: 555-563

crates/core/tests/unit/llm_api_tests.rs (1)

325-325: LGTM!

Also applies to: 334-337, 351-354

crates/node/tests/llm_tests.mjs (1)

830-832: LGTM!

Also applies to: 1091-1103, 1119-1124

Comment thread crates/core/tests/unit/llm_api_tests.rs
Signed-off-by: Will Killian <wkillian@nvidia.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/core/tests/unit/llm_api_tests.rs`:
- Line 77: Update the traceparent test fixture and its expected sanitized header
to use the same valid, distinct W3C traceparent value instead of
"user-provided-traceparent". Apply this consistently to the related assertions
around the traceparent header so the test verifies preservation of valid
user-provided values.
- Around line 415-425: Extend the provider-request assertions around the
traceparent checks to validate the final credential-header set: ensure the
header map contains only x-request-id and the managed traceparent, or explicitly
assert that Authorization and all other credential headers are absent. Preserve
the existing traceparent content validation.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: d8b2a0d7-72e7-4855-8612-cbd24f2b04da

📥 Commits

Reviewing files that changed from the base of the PR and between a4a4557 and bf1b199.

📒 Files selected for processing (1)
  • crates/core/tests/unit/llm_api_tests.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (44)
  • GitHub Check: Python / Package (windows-amd64)
  • GitHub Check: Python / Package (macos-arm64)
  • GitHub Check: Python / Package (linux-musl-amd64)
  • GitHub Check: Node.js / Package (windows-arm64)
  • GitHub Check: Python / Package (linux-musl-arm64)
  • GitHub Check: Python / Package (windows-arm64)
  • GitHub Check: Python / Package (linux-arm64)
  • GitHub Check: Node.js / Package (linux-musl-arm64)
  • GitHub Check: Python / Test (windows-arm64)
  • GitHub Check: Python / Test (linux-arm64)
  • GitHub Check: Python / Test (macos-arm64)
  • GitHub Check: Node.js / Package (linux-arm64)
  • GitHub Check: Python / Test (linux-amd64)
  • GitHub Check: Node.js / Package (linux-amd64)
  • GitHub Check: Python / Package (linux-amd64)
  • GitHub Check: Python / Test (windows-amd64)
  • GitHub Check: Node.js / Package (linux-musl-amd64)
  • GitHub Check: Rust / Package (windows-arm64)
  • GitHub Check: Node.js / Package (macos-arm64)
  • GitHub Check: Rust / Package (linux-musl-amd64)
  • GitHub Check: Rust / Package (linux-amd64)
  • GitHub Check: Node.js / Package (windows-amd64)
  • GitHub Check: Rust / Package (macos-arm64)
  • GitHub Check: Node.js / Test (windows-arm64)
  • GitHub Check: Node.js / Test (linux-arm64)
  • GitHub Check: Rust / Package (windows-amd64)
  • GitHub Check: Rust / Package (linux-musl-arm64)
  • GitHub Check: Rust / Package (linux-arm64)
  • GitHub Check: Node.js / Test (linux-amd64)
  • GitHub Check: Go / Test (macos-arm64)
  • GitHub Check: Go / Test (linux-amd64)
  • GitHub Check: Rust / Test (macos-arm64)
  • GitHub Check: Rust / Test (linux-arm64)
  • GitHub Check: Node.js / Test (windows-amd64)
  • GitHub Check: Rust / Test (windows-arm64)
  • GitHub Check: Go / Test (windows-arm64)
  • GitHub Check: Rust / Test (windows-amd64)
  • GitHub Check: Rust / Test (linux-amd64)
  • GitHub Check: Node.js / Test (macos-arm64)
  • GitHub Check: Go / Test (linux-arm64)
  • GitHub Check: Go / Test (windows-amd64)
  • GitHub Check: Node.js / Package OpenClaw plugin
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (19)
**/*.rs

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

**/*.rs: Any Rust change must run just test-rust
Any Rust change must run cargo fmt --all
Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all for all FFI work since it is Rust work
Run just test-rust to validate FFI changes
Run cargo clippy --workspace --all-targets -- -D warnings to enforce strict linting on FFI work

When Rust files changed as part of Go work, also run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Run cargo fmt --all when Rust files are changed as part of Node work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files are changed as part of Node work
Run just test-rust when Rust files are changed as part of Node work

**/*.rs: If any Rust code changed, always run just test-rust.
If any Rust code changed, also run cargo fmt --all.
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings.
For Rust changes headed for review, run cargo fmt --all and cargo clippy --workspace --all-targets -- -D warnings even if relying on pre-commit.

**/*.rs: Format Rust code with rustfmt defaults using cargo fmt.
Run cargo clippy -- -D warnings; all Rust warnings must be treated as errors.
Use Rust snake_case naming conventions.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
{crates/core,crates/adaptive}/**/*

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

Changes to crates/core or crates/adaptive must run the full language matrix

Files:

  • crates/core/tests/unit/llm_api_tests.rs
crates/core/**/*.rs

📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)

If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation

Use Result<T> with FlowError in core runtime paths, keeping wrapper-layer errors explicit and binding-appropriate.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, use maintain-dynamic-plugins and include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, prefer uv run pre-commit run --files <changed files...>.
Before review or handoff, run uv run pre-commit run --all-files.

**/*: Use release tags in raw Rust-compatible SemVer without a leading v; tags such as v0.1.0 are prohibited.
Use branch prefixes feat/, fix/, docs/, test/, or refactor/ according to the change purpose.
Every commit in a pull request must include a DCO Signed-off-by: sign-off.
Before submitting a pull request, ensure pre-commit hooks, relevant tests, target-specific builds, documentation updates, and a rebase on the latest main are complete.
Use commit messages in the form type: short description, with a valid type and a first line under 72 characters.

Run the prescribed plugin validation commands, including fixture building, focused Rust and Python package tests, integration tests, documentation checks, and the broader validate-change matrix for broad runtime or public API changes.

**/*: Keep observability changes scoped, surface assumptions, and define focused validation before editing.
Run affected Rust tests and just test-rust for event-field changes; run just test-python, just test-go, and just test-node when binding-native configuration or lifecycle changes; update docs and examples in the same branch.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
crates/{core,adaptive}/**/*

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If crates/core or crates/adaptive changed, run the full validation matrix across Rust, Python, Go, and Node.js.

For shared-semantics or broad runtime changes in the core or adaptive crates, run just ci=true test-rust.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
**/*.{rs,py,go,js,ts}

📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)

If a language surface changed, always run that language's test target even when Rust core did not change.

**/*.{rs,py,go,js,ts}: Keep FFI and Python, Go, and Node.js binding configuration objects and subscriber/exporter methods aligned with the core observability configuration and lifecycle semantics.
Preserve complete sanitized LLM request input and annotations when enable_full_payloads is enabled, while retaining credential removal and sanitizers.
Use each exporter's documented flush and deregister order before shutdown in observability examples and implementations.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}

📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)

Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
**/*.{rs,py,js,jsx,ts,tsx,go,c,h,cc,cpp,md,toml,yml,yaml,sh}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, documentation, scripts, and configuration files; the project is Apache-2.0.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
**/*.{rs,py}

📄 CodeRabbit inference engine (AGENTS.md)

Use snake_case naming in Rust and Python.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Use Json = serde_json::Value in Rust-facing runtime APIs where existing code expects JSON payloads.
Treat Rust as the source of truth for runtime behavior; binding APIs should mirror Rust semantics unless a language-specific wrapper intentionally improves ergonomics.

crates/**/*.rs: Runtime helpers must cover marks, scopes, continuations, and isolated scope stacks.
plugins list, plugins inspect, and plugins validate must report lifecycle and compatibility status without leaking secret configuration.
Top-level doctor must report resolved dynamic-plugin and host-configuration status.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
**/*.{rs,py,js,mjs,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Preserve the existing Tokio-based asynchronous model and callback/future lifetimes; do not unexpectedly block or hide async work in bindings.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
**/*.{rs,py,go,js,jsx,ts,tsx,c,h}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{rs,py,go,js,jsx,ts,tsx,c,h}: Run tests for every language affected by a change; changes to the core Rust crate require tests across all bindings.
Use SONAR_IGNORE_START / SONAR_IGNORE_END only for documented false positives, keep ignored blocks minimal, explain them with a comment, and obtain reviewer sign-off.
Preserve the layered architecture in which Rust provides the core runtime and C FFI, PyO3, and NAPI provide bindings that mirror the full API surface.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
**/{test,tests}/**/*

📄 CodeRabbit inference engine (CONTRIBUTING.md)

When adding functionality, include tests in the appropriate test files for each affected language binding.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
**/*.{rs,py,go,js,jsx,ts,tsx,c,h,html,md,mdx,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include the appropriate SPDX copyright and Apache-2.0 license header in every source file.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
**/*.{toml,md,rs,py}

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

Treat plugin Relay compatibility as normal SemVer; use >=0.5,<1.0 in examples unless a plugin intentionally declares a narrower range.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
crates/{core,adaptive,plugin,worker,worker-proto,types}/**/*.{rs,toml}

📄 CodeRabbit inference engine (.agents/skills/test-rust-core/SKILL.md)

For changes in the Rust core, adaptive, dynamic plugin, worker, worker-proto, or types crates, run cargo fmt --all, just test-rust, and cargo clippy --workspace --all-targets -- -D warnings as the default validation sequence.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
crates/{core,adaptive,plugin,worker,worker-proto,types}/**/*

📄 CodeRabbit inference engine (.agents/skills/test-rust-core/SKILL.md)

crates/{core,adaptive,plugin,worker,worker-proto,types}/**/*: For changes affecting crates/core, crates/adaptive, or shared Rust runtime semantics, expand validation to the full binding matrix with validate-change.
Use narrower crate-specific tests only as a local debug loop, not as the final validation for a Rust change.
If a public API, event shape, middleware behavior, plugin semantics, or crates/core/crates/adaptive behavior changes, also run validate-change.
If the change is isolated to one binding wrapper while Rust semantics remain unchanged, prefer that binding's build/test skill instead.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

crates/{core,adaptive}/**/*.rs: Review the Rust runtime for async correctness, scope isolation, middleware ordering, and event lifecycle regressions.
Pay close attention to task-local/thread-local scope propagation, callback lifetimes, stream finalization, and root_uuid isolation.
Public API changes should preserve existing behavior unless tests and docs show the intended migration path.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}

⚙️ CodeRabbit configuration file

{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.

Files:

  • crates/core/tests/unit/llm_api_tests.rs
🧠 Learnings (1)
📚 Learning: 2026-08-03T19:55:03.931Z
Learnt from: afourniernv
Repo: NVIDIA/NeMo-Relay PR: 558
File: crates/pii-redaction/src/rampart/mod.rs:265-274
Timestamp: 2026-08-03T19:55:03.931Z
Learning: In NeMo Relay first-party plugin registration helpers, treat the documented duplicate-registration `PluginError::RegistrationFailed` result from `register_plugin` as success when registration is intended to be idempotent. Do not locally reclassify this as `PluginError::Conflict`; changing the classification requires a core-wide review of the public API and FFI behavior.

Applied to files:

  • crates/core/tests/unit/llm_api_tests.rs
🔇 Additional comments (1)
crates/core/tests/unit/llm_api_tests.rs (1)

330-342: LGTM!

Also applies to: 356-359

Comment thread crates/core/tests/unit/llm_api_tests.rs
Comment thread crates/core/tests/unit/llm_api_tests.rs
Signed-off-by: Will Killian <wkillian@nvidia.com>
Comment thread crates/node/src/api/mod.rs
Comment thread python/nemo_relay/__init__.py Outdated

@mnajafian-nv mnajafian-nv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything else looks good to me. The only issue I found is that capture_traceparent() drops the imported trace root in the Node and Python callback fast paths under rooted propagation. Details inline.

Signed-off-by: Will Killian <wkillian@nvidia.com>
Signed-off-by: Will Killian <wkillian@nvidia.com>
@mnajafian-nv

Copy link
Copy Markdown
Contributor

/merge

@rapids-bot
rapids-bot Bot merged commit cbe4aec into NVIDIA:main Aug 10, 2026
93 checks passed
@willkill07
willkill07 deleted the feat/relay-186-traceparent branch August 10, 2026 18:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature a new feature lang:go PR changes/introduces Go code lang:js PR changes/introduces Javascript/Typescript code lang:python PR changes/introduces Python code lang:rust PR changes/introduces Rust code size:L PR is large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants