Skip to content

feat: add ATIF HTTP storage export#231

Merged
rapids-bot[bot] merged 1 commit into
NVIDIA:mainfrom
willkill07:wkk_feat/atif-http-storage
Jun 5, 2026
Merged

feat: add ATIF HTTP storage export#231
rapids-bot[bot] merged 1 commit into
NVIDIA:mainfrom
willkill07:wkk_feat/atif-http-storage

Conversation

@willkill07
Copy link
Copy Markdown
Member

@willkill07 willkill07 commented Jun 5, 2026

Overview

Add HTTP endpoint storage as a first-class ATIF remote export backend, alongside existing S3-compatible storage.

  • 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

  • Added type = "http" ATIF storage configuration with endpoint, headers, header_env, and timeout_millis.
  • Implemented POST-based ATIF JSON upload with runtime filename/session headers and non-2xx unhealthy-sink handling.
  • Updated Python, Node.js, and WASM wrapper config types/helpers for mixed S3 and HTTP storage entries.
  • Documented HTTP remote storage and added Rust, Python, and Node.js tests.

Validation:

  • cargo test -p nemo-relay atif_storage
  • uv run pytest python/tests/test_observability_plugin.py
  • cd crates/node && node --test tests/observability_plugin_tests.mjs
  • just test-python
  • just test-node
  • Commit hooks passed: cargo fmt, cargo clippy, cargo check, cargo deny, Ruff, ty, docs linkcheck, Node prettier.
  • just test-rust was attempted, but existing CLI server/session tests hung after several minutes with no progress; the run was terminated.

Where should the reviewer start?

Start with crates/core/src/observability/plugin_component.rs for the new HTTP storage config, validation, and upload path. The local HTTP integration coverage is in crates/core/tests/integration/atif_storage_tests.rs.

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

  • Closes RELAY-257

Summary by CodeRabbit

  • New Features

    • Added HTTP endpoint support for ATIF remote storage configuration as an alternative to S3, including configurable headers, timeouts, and session ID tracking.
  • Documentation

    • Updated ATIF observability documentation with HTTP endpoint storage configuration examples and guidance.

@willkill07 willkill07 requested a review from a team as a code owner June 5, 2026 16:34
@github-actions github-actions Bot added size:L PR is large Feature a new feature lang:js PR changes/introduces Javascript/Typescript code lang:python PR changes/introduces Python code labels Jun 5, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 5, 2026

Review Change Stack

Walkthrough

This PR adds HTTP endpoint support for ATIF remote trajectory uploads alongside S3, extending the observability plugin with a new HttpStorageConfig type, validation, async HTTP client threading, and cross-language type definitions.

Changes

HTTP Storage Backend Integration

Layer / File(s) Summary
Cargo feature and cfg gating
crates/core/Cargo.toml, crates/core/src/observability/plugin_component.rs
Enable reqwest and rustls dependencies for guardrails-remote and require object-store for remote-storage code compilation.
HTTP storage configuration schema and validation
crates/core/src/observability/plugin_component.rs
Add Http(HttpStorageConfig) variant to AtifStorageConfig and new struct with endpoint, headers, header_env, and timeout_millis; validation helpers enforce URL format, header correctness, positive timeout, and env-var presence.
Session ID threading and teardown behavior
crates/core/src/observability/plugin_component.rs
Thread per-trajectory session_id from agent UUID through PendingAtifWrite, file preparation, and remote put() calls; simplify dispatcher teardown to report only fatal errors rather than aggregating per-sink upload failures.
HTTP remote upload client implementation
crates/core/src/observability/plugin_component.rs
Extend AtifUploadRequest with session_id, introduce HttpUploadConfig to resolve endpoint/headers/timeout, build_http spawns OS thread with single-threaded Tokio and reqwest client, put() enqueues requests, and post_atif_http performs JSON POST with x-nemo-relay-atif-filename and session-id headers.
Integration tests for HTTP storage endpoints
crates/core/tests/integration/atif_storage_tests.rs
Add local TCP test harness capturing requests, global PLUGIN_TEST_LOCK for test serialization, and tests validating multi-endpoint POSTs with ATIF headers/session-id and unhealthy-sink behavior on non-2xx responses.
Unit tests for HTTP storage configuration
crates/core/tests/unit/observability/plugin_component_tests.rs
Parsing and validation tests for AtifStorageConfig::Http, array-of-tables, endpoint format, timeout positivity, header names/values, and header_env env-var presence with success/error cases.
Type definitions and language bindings
crates/node/observability.d.ts, crates/node/tests/observability_plugin_tests.mjs, python/nemo_relay/observability.py, python/nemo_relay/observability.pyi, python/tests/test_observability_plugin.py
Add HttpStorageConfig across TypeScript, Python dataclasses, and stubs; update AtifConfig.storage to accept heterogeneous S3/HTTP arrays; include pass-through and serialization tests.
User documentation and examples
docs/observability-plugin/atif.mdx
Clarify type discriminator requirement, add "HTTP endpoint storage" section describing POST delivery semantics and unhealthy-endpoint behavior, update multiple-destination example to mix S3 and HTTP backends.

🎯 4 (Complex) | ⏱️ ~45 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title follows Conventional Commits format with type 'feat', concise imperative summary, no scope, no breaking change marker, and is 34 characters—well under 72.
Description check ✅ Passed Description includes all required template sections: Overview with checkboxes confirmed, Details with comprehensive change summary, reviewer start point, and related issue closure reference.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@github-actions github-actions Bot added the lang:rust PR changes/introduces Rust code label Jun 5, 2026
@willkill07 willkill07 added this to the 0.4 milestone Jun 5, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 5, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/core/src/observability/plugin_component.rs (1)

994-1008: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't turn quarantined sink failures into teardown failures.

complete_scope_write() already marks a bad remote sink unhealthy and sink_targets() stops using it on later trajectories. Folding sink_errors back into last_error_result() means one 5xx response still makes clear_plugin_configuration() fail during shutdown, which breaks the advertised “skip unhealthy sink and continue” behavior.

🤖 Prompt for 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.

In `@crates/core/src/observability/plugin_component.rs` around lines 994 - 1008,
last_error_result() is turning quarantined sink failures in self.sink_errors
into an overall IO error during shutdown; remove the sink_errors folding so
isolated remote sink 5xxs don't make clear_plugin_configuration() fail. Change
last_error_result (the method) to only consider self.fatal_error for producing
an Err and ignore/omit self.sink_errors aggregation, leaving quarantining/health
logic to complete_scope_write() and sink_targets() as-is.
🤖 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/src/observability/plugin_component.rs`:
- Around line 1556-1581: In the AtifStorageConfig::Http branch inside
validate(), add validation for the literal HTTP headers so invalid entries fail
early: iterate over http.headers and call the same validation used in
HttpUploadConfig::resolve() (or create/use a helper like
validate_atif_header_name/validate_http_header) for each header name, pushing a
diagnostic via push_policy_diag if a header is invalid; repeat the same change
in the other validate() occurrence noted (around the second block at lines
~2120-2140) so both config-validation paths reject bad headers instead of
deferring failure to initialize_plugins()/HttpUploadConfig::resolve().

In `@crates/core/tests/integration/atif_storage_tests.rs`:
- Around line 32-37: The tests currently ignore the HTTP verb; update the
CapturedHttpRequest struct to include a method field (e.g., method: String) and
modify the request-capturing code that builds CapturedHttpRequest to parse the
request line (take the first token of the start-line) and set that method. Then
add assertions in the HTTP storage tests (where CapturedHttpRequest instances
are inspected) to assert eq!("POST", captured.method) so the tests fail if the
uploader stops using POST; reference CapturedHttpRequest and the test(s) that
inspect its fields when making these changes.

---

Outside diff comments:
In `@crates/core/src/observability/plugin_component.rs`:
- Around line 994-1008: last_error_result() is turning quarantined sink failures
in self.sink_errors into an overall IO error during shutdown; remove the
sink_errors folding so isolated remote sink 5xxs don't make
clear_plugin_configuration() fail. Change last_error_result (the method) to only
consider self.fatal_error for producing an Err and ignore/omit self.sink_errors
aggregation, leaving quarantining/health logic to complete_scope_write() and
sink_targets() as-is.
🪄 Autofix (Beta)

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: f9add61d-35a8-4c42-bb68-f9140f4befa3

📥 Commits

Reviewing files that changed from the base of the PR and between 559cce7 and c1138b4.

📒 Files selected for processing (11)
  • crates/core/Cargo.toml
  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/node/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
  • crates/wasm/wrappers/esm/observability.d.ts
  • docs/observability-plugin/atif.mdx
  • python/nemo_relay/observability.py
  • python/nemo_relay/observability.pyi
  • python/tests/test_observability_plugin.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Check / Run
  • GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (46)
**/test_*.{py,py}

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

Relevant integration tests or smoke coverage must exist for the integration path

Files:

  • python/tests/test_observability_plugin.py
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

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

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • python/tests/test_observability_plugin.py
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
{pyproject.toml,**/*.py}

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

Maintain consistency between Python package names in pyproject.toml and import paths used throughout the codebase

Files:

  • python/tests/test_observability_plugin.py
  • python/nemo_relay/observability.py
**/*.{py,txt,toml,cfg,yaml,yml}

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

Update Python package names and top-level module imports during coordinated rename operations

Files:

  • python/tests/test_observability_plugin.py
  • crates/core/Cargo.toml
  • python/nemo_relay/observability.py
python/**/*test*.py

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

python/**/*test*.py: Do not add @pytest.mark.asyncio to any test in Python test files
Do not add a -> None return type annotation to test functions
When mocking a class, use unittest.mock.MagicMock or unittest.mock.AsyncMock with the spec constructor argument when necessary, rather than defining a new class
Prefix mocked class names with mock, not fake
Prefer pytest fixtures over helper methods in Python tests
Prefer pytest.mark.parametrize over creating individual tests for different input types

Files:

  • python/tests/test_observability_plugin.py
python/**/{conftest.py,*test*.py}

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

When creating a fixture follow the pattern: @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) def <fixture_name>_fixture() -> <return_type>: and only specify the scope argument when the value is something other than "function"

Files:

  • python/tests/test_observability_plugin.py
**/*.py

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

**/*.py: Run Python formatting with uv run ruff format python
Run Python testing with uv run pytest -k "<pattern>"

**/*.py: Use Ruff with rule sets E, F, W, I for Python linting
Use Ruff formatter with line length 120 and double quotes for Python code formatting
Run ty for Python type checking
Use Python snake_case naming convention for Python identifiers
Include SPDX license header in all Python source files using hash comment syntax
Validate Python code with uv run pre-commit run --all-files to enforce Ruff linting and formatting, and ty type checking

Files:

  • python/tests/test_observability_plugin.py
  • python/nemo_relay/observability.py
**/*.{md,mdx,py,sh,yaml,yml,toml,json}

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

Keep package names, repo references, and build commands current

Files:

  • python/tests/test_observability_plugin.py
  • crates/core/Cargo.toml
  • docs/observability-plugin/atif.mdx
  • python/nemo_relay/observability.py
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.

Files:

  • python/tests/test_observability_plugin.py
  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/core/Cargo.toml
  • python/nemo_relay/observability.py
  • crates/node/observability.d.ts
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions: Rust and Python use snake_case, C FFI exports prefixed nemo_relay_, Go uses PascalCase for public APIs, Node.js uses camelCase.

Files:

  • python/tests/test_observability_plugin.py
  • crates/wasm/wrappers/esm/observability.d.ts
  • python/nemo_relay/observability.py
  • crates/node/observability.d.ts
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.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:

  • python/tests/test_observability_plugin.py
  • crates/node/tests/observability_plugin_tests.mjs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
**

⚙️ CodeRabbit configuration file

**:

AGENTS.md

This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.

Project Overview

NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go, WebAssembly, and the raw C FFI are experimental and source-first.

The shared runtime model is:

  1. Scope stacks decide where work belongs and which scope-local behavior is visible.
  2. Middleware registries decide what guardrails and intercepts run around managed calls.
  3. Plugins install reusable runtime behavior from configuration.
  4. Events record runtime behavior in ATOF form.
  5. Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.

Repository Structure

The repository layout separates the Rust runtime, language bindings, documentation,
integration patches, and agent-facing skills.

crates/
  core/       # Rust core runtime crate, published as nemo-relay
  adaptive/   # Adaptive runtime primitives and plugin components
  python/     # PyO3 native extension for the Python package
  ffi/        # Raw C ABI layer used by downstream bindings such as Go
  node/       # NAPI Node.js binding and JavaScript/TypeScript entry points
  wasm/       # wasm-bindgen WebAssembly binding and JS wrappers
python/
  nemo_relay/  # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers
  tests/      # Python tests
go/
  nemo_relay/  # Experimental Go CGo binding and tests
fern/         # Fern documentation site
scripts/      # Stable wrappers and helper scripts; build/test/docs entry points live in justfile
third_party/  # P...

Files:

  • python/tests/test_observability_plugin.py
  • python/nemo_relay/observability.pyi
  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/core/Cargo.toml
  • docs/observability-plugin/atif.mdx
  • python/nemo_relay/observability.py
  • crates/node/tests/observability_plugin_tests.mjs
  • crates/node/observability.d.ts
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
{crates/python/src/py_api/**/*.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi}

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

Update Python native binding in crates/python/src/py_api/mod.rs with Python wrapper docstring in python/nemo_relay/<module>.py and type stubs in python/nemo_relay/*.pyi modules

Files:

  • python/nemo_relay/observability.pyi
  • python/nemo_relay/observability.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/observability.pyi
  • python/nemo_relay/observability.py
{crates/adaptive/**,python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,go/nemo_relay/!(adaptive)/**,**/node/**,**/wasm/**}

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

Keep adaptive surface in sync across crates/adaptive, shared plugin behavior in core and bindings, Python adaptive/plugin wrappers in python/nemo_relay/adaptive.py and python/nemo_relay/plugin.py, Go adaptive helpers under go/nemo_relay/adaptive plus shared plugin helpers in go/nemo_relay, and Node/WebAssembly adaptive helpers and plugin wrappers

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
  • crates/node/observability.d.ts
{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}

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

{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}: Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)
Keep plugin context surfaces aligned across all language implementations

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
  • crates/node/observability.d.ts
**/*.{wasm,js,ts}{,x}

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

Ensure WebAssembly package naming conventions are consistent with generated package expectations and downstream consumption

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/observability.d.ts
crates/wasm/{wrappers,tests-js,scripts}/**/*.{js,ts,jsx,tsx}

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

Format changed WebAssembly JS/TS wrapper files with npm run precommit:format --workspace=nemo-relay-node -- crates/wasm/wrappers crates/wasm/tests-js crates/wasm/scripts

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
**/*.{js,ts,jsx,tsx}

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

Run Node.js formatting with npm run format --workspace=nemo-relay-node

Include SPDX license header in all JavaScript and TypeScript source files using double-slash comment syntax

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/observability.d.ts
crates/wasm/**/*.{js,ts,jsx,tsx}

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

Run WebAssembly formatting with npm run precommit:format --workspace=nemo-relay-node -- crates/wasm/wrappers crates/wasm/tests-js crates/wasm/scripts

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
crates/{python,ffi,node,wasm}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node,wasm}/**/*: 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/wasm/wrappers/esm/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
  • crates/node/observability.d.ts
**/{Cargo.toml,**/*.rs}

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

Maintain consistency between Rust package names in Cargo.toml and their actual usage across the codebase

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.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/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/*.{rs,toml}

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

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/Cargo.toml

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

Update WebAssembly crate names and generated package names during coordinated rename operations

Confirm or infer the target release version from upstream/main:Cargo.toml. Derive the release branch as release/<major>.<minor>.

Files:

  • crates/core/Cargo.toml
crates/{core,adaptive}/**

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

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

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

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

Ensure renamed public surfaces are reflected consistently in manifests and docs for large or public-facing changes

Files:

  • crates/core/Cargo.toml
  • docs/observability-plugin/atif.mdx
**/*.toml

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in TOML configuration files using hash comment syntax

Files:

  • crates/core/Cargo.toml
{docs/**,README.md,CONTRIBUTING.md}

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

{docs/**,README.md,CONTRIBUTING.md}: For docs-only changes, run targeted checks only if commands, package names, or examples changed. Use just docs for docs-site builds and just docs-linkcheck when links changed
Run docs site build with just docs

Files:

  • docs/observability-plugin/atif.mdx
{docs/**,README.md,CONTRIBUTING.md,**/*.md}

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

Run docs link validation with just docs-linkcheck when links change

Files:

  • docs/observability-plugin/atif.mdx
{docs/**,README.md}

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

Verify README and docs entry points still match current package names and paths for large or public-facing changes

Files:

  • docs/observability-plugin/atif.mdx
{docs/**,examples/**,README.md}

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

Verify examples still run with documented commands for large or public-facing changes

Files:

  • docs/observability-plugin/atif.mdx
**/*.mdx

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

In MDX files, top-of-file comments must use JSX comment delimiters: {/* to open and */} to close. Do not use HTML comments for MDX SPDX headers.

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

Files:

  • docs/observability-plugin/atif.mdx
**/*.{html,md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in HTML and Markdown files using HTML comment syntax

Files:

  • docs/observability-plugin/atif.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update embedded documentation snippets, patch docs, and binding-support notes if examples or supported bindings changed

Files:

  • docs/observability-plugin/atif.mdx
docs/**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run just docs or ./scripts/build-docs.sh html to regenerate ignored Fern API reference pages before validation for documentation site changes

Files:

  • docs/observability-plugin/atif.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/observability-plugin/atif.mdx
python/nemo_relay/**/*.py

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

Use snake_case naming convention for Python identifiers (e.g., nemo_relay.tools.call)

Format changed Python wrapper and test files with uv run ruff format python

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

Files:

  • python/nemo_relay/observability.py
crates/node/**/*.{js,ts,jsx,tsx,json}

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

Format changed Node files with npm run format --workspace=nemo-relay-node

Files:

  • crates/node/observability.d.ts
crates/node/**/*.{ts,tsx,d.ts}

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

Use npm run check:docstrings --workspace=nemo-relay-node to validate public API docstring checks when surface docs changed

Files:

  • crates/node/observability.d.ts
crates/node/**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Node.js public entry points include the main runtime package plus nemo-relay-node/typed, nemo-relay-node/plugin, and nemo-relay-node/adaptive.

Files:

  • crates/node/observability.d.ts
**/*.rs

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

Use snake_case naming convention for Rust identifiers (e.g., nemo_relay_tool_call)

**/*.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: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly 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
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Use cargo fmt for Rust code formatting
Run cargo clippy -- -D warnings to lint Rust code and treat all warnings as errors
Use Rust snake_case naming convention for Rust identifiers
Include SPDX license header in all Rust source files using double-slash comment syntax
Validate Rust code with uv run pre-commit run --all-files to enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...

Files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/*.{h,hpp,c,cpp,rs}

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

Ensure FFI header and library naming follows consistent conventions across platform-specific builds

Files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.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

crates/core/**/*.rs: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.

Files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Keep async behavior on the existing tokio-based model. Bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Use Json = serde_json::Value in Rust-facing runtime APIs for JSON payload handling.

Files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.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/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
🧠 Learnings (22)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-observability/SKILL.md:0-0
Timestamp: 2026-05-21T22:48:57.484Z
Learning: Applies to crates/core/src/observability/{atif,otel,openinference}.rs : When changing event fields in ATIF, OpenTelemetry, or OpenInference observability surfaces, keep the core event model in `crates/core/src/observability/atif.rs`, `crates/core/src/observability/otel.rs`, and `crates/core/src/observability/openinference.rs` in sync
📚 Learning: 2026-05-07T18:04:44.387Z
Learnt from: mnajafian-nv
Repo: NVIDIA/NeMo-Flow PR: 67
File: integrations/openclaw/src/modules.ts:1-2
Timestamp: 2026-05-07T18:04:44.387Z
Learning: In NVIDIA/NeMo-Flow, TypeScript source files should use `//` line comments for SPDX headers (e.g., `// SPDX-FileCopyrightText: ...` and `// SPDX-License-Identifier: ...`) rather than C-style block comments (`/* ... */`). The repo’s copyright checker enforces this mapping, so `//` SPDX headers in `.ts` files should not be flagged as a style violation.

Applied to files:

  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/observability.d.ts
📚 Learning: 2026-05-21T22:51:04.073Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-go-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:04.073Z
Learning: Applies to crates/core/**/*.rs : If the change touched `crates/core` or shared runtime semantics, also use `validate-change` for broader validation

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:52:14.330Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/validate-change/SKILL.md:0-0
Timestamp: 2026-05-21T22:52:14.330Z
Learning: Applies to crates/{core,adaptive}/** : If `crates/core` or `crates/adaptive` changed, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:51:34.986Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-wasm-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:34.986Z
Learning: If the change touched shared runtime semantics in `crates/core` or `crates/adaptive`, also use the `validate-change` skill

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:49:46.956Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/rename-surfaces/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:46.956Z
Learning: Applies to **/Cargo.toml : Update WebAssembly crate names and generated package names during coordinated rename operations

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:47:33.109Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-binding-feature/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:33.109Z
Learning: Applies to crates/wasm/src/api/**/*.rs : Update WebAssembly binding in `crates/wasm/src/api/mod.rs` for language-native bindings

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:49:35.949Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/prepare-pr/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:35.949Z
Learning: Applies to {crates/core,crates/adaptive}/**/* : Changes to `crates/core` or `crates/adaptive` must run the full language matrix

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:51:11.713Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-node-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:11.713Z
Learning: If the change touched `crates/core`, `crates/adaptive`, or the generated Rust binding layer under `crates/node/src`, also use `validate-change` skill

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:51:21.017Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-python-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:21.017Z
Learning: If `crates/core`, `crates/adaptive`, or shared runtime semantics changed, also use `validate-change` skill

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:49:46.956Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/rename-surfaces/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:46.956Z
Learning: Applies to **/*.{rs,toml} : Update Rust crate names and module prefixes during coordinated rename operations

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:51:50.794Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/update-project-version/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:50.794Z
Learning: Applies to Cargo.toml : Keep `Cargo.toml` `[workspace.dependencies]` self-references aligned when the workspace version changes

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:52:14.330Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/validate-change/SKILL.md:0-0
Timestamp: 2026-05-21T22:52:14.330Z
Learning: For Node.js binding changes, use `test-node-binding`

Applied to files:

  • crates/node/tests/observability_plugin_tests.mjs
📚 Learning: 2026-05-21T22:48:57.484Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-observability/SKILL.md:0-0
Timestamp: 2026-05-21T22:48:57.484Z
Learning: Applies to crates/core/src/observability/{atif,otel,openinference}.rs : When changing event fields in ATIF, OpenTelemetry, or OpenInference observability surfaces, keep the core event model in `crates/core/src/observability/atif.rs`, `crates/core/src/observability/otel.rs`, and `crates/core/src/observability/openinference.rs` in sync

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
📚 Learning: 2026-05-21T22:48:57.484Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-observability/SKILL.md:0-0
Timestamp: 2026-05-21T22:48:57.484Z
Learning: When event fields change, run Rust crate tests and execute `just test-rust` to validate the affected observability modules

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
📚 Learning: 2026-05-21T22:51:04.073Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-go-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:04.073Z
Learning: Applies to crates/ffi/**/*.rs : If the change touched `crates/ffi`, also use `test-ffi-surface` for validation

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
📚 Learning: 2026-05-29T21:25:49.977Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-29T21:25:49.977Z
Learning: Run tests for every language affected by a change. If you touch the Rust core runtime, middleware semantics, event shape, scope behavior, typed codecs, plugins, or observability, expect to validate every affected binding because the bindings share the same runtime contract.

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
📚 Learning: 2026-05-21T22:51:27.841Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-rust-core/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:27.841Z
Learning: Use narrower crate tests as a local debug loop, not as the final validation story for Rust changes

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
📚 Learning: 2026-05-21T22:52:14.330Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/validate-change/SKILL.md:0-0
Timestamp: 2026-05-21T22:52:14.330Z
Learning: For core runtime or shared semantics changes, use `test-rust-core` which includes Rust testing, formatting, linting, and full cross-language matrix

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
📚 Learning: 2026-05-21T22:47:58.898Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-middleware/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:58.898Z
Learning: Applies to crates/core/src/api/runtime/state.rs : Add chain execution helpers to `NemoRelayContextState` following the pattern of existing methods like `tool_sanitize_request_chain` or `tool_request_intercepts_chain`

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
📚 Learning: 2026-05-21T22:49:09.811Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-optimizer/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:09.811Z
Learning: Applies to {crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**} : Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
📚 Learning: 2026-05-21T22:47:58.898Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-middleware/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:58.898Z
Learning: Applies to crates/core/src/api/runtime/state.rs : Add registry fields as `SortedRegistry<GuardrailEntry<T>>` or `SortedRegistry<Intercept<T>>` to `NemoRelayContextState` in `crates/core/src/api/runtime/state.rs`

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
🔇 Additional comments (15)
crates/node/observability.d.ts (1)

28-34: LGTM!

Also applies to: 45-45

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

59-77: LGTM!

crates/wasm/wrappers/esm/observability.d.ts (1)

16-34: LGTM!

Also applies to: 45-45

python/nemo_relay/observability.py (1)

113-132: LGTM!

Also applies to: 147-147, 248-248

python/nemo_relay/observability.pyi (1)

40-46: LGTM!

Also applies to: 58-58

python/tests/test_observability_plugin.py (1)

19-19: LGTM!

Also applies to: 99-115

crates/core/tests/unit/observability/plugin_component_tests.rs (4)

1169-1169: LGTM!

Also applies to: 1205-1205, 1239-1239, 1246-1246, 1504-1504


1177-1207: LGTM!


1233-1233: LGTM!

Also applies to: 1239-1239, 1243-1246


1320-1474: LGTM!

docs/observability-plugin/atif.mdx (5)

64-66: LGTM!


81-98: LGTM!


100-108: LGTM!


121-121: LGTM!

Also applies to: 134-136


110-115: ⚡ Quick win

Confirm timeout_millis default and “must be positive” validation

HttpStorageConfig.timeout_millis uses default_timeout_millis() which returns 3_000, matching the docs. Validation treats timeout_millis == 0 as invalid (error: “must be positive”), so the requirement effectively means timeout_millis >= 1.

Comment thread crates/core/src/observability/plugin_component.rs
Comment thread crates/core/tests/integration/atif_storage_tests.rs
@bbednarski9 bbednarski9 self-requested a review June 5, 2026 16:51
Comment thread crates/core/src/observability/plugin_component.rs
@willkill07 willkill07 force-pushed the wkk_feat/atif-http-storage branch from c1138b4 to 88bcd4d Compare June 5, 2026 16:56
@github-actions github-actions Bot added size:XL PR is extra large and removed size:L PR is large labels Jun 5, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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/src/observability/plugin_component.rs`:
- Around line 2225-2228: The S3 path currently omits calling
install_rustls_crypto_provider(), causing TLS provider not to be registered for
reqwest-backed S3 clients; update AtifRemoteStorage::build_s3 to call
install_rustls_crypto_provider() in the same thread setup where the
AmazonS3Builder/reqwest client is constructed (mirror the call in
AtifRemoteStorage::build_http) so the rustls crypto provider is initialized
before creating the S3 object_store client.

In `@crates/wasm/wrappers/esm/observability.d.ts`:
- Line 45: The TypeScript declaration for the observability config exposes the
storage property (storage?: S3StorageConfig | HttpStorageConfig |
Array<S3StorageConfig | HttpStorageConfig>) which is not actually supported at
runtime on WASM; add a descriptive JSDoc comment immediately above the storage
property in observability.d.ts stating that remote storage is unsupported on
WebAssembly targets and will be rejected at runtime (include note about runtime
validation), so authors see the limitation in their editor even though the type
remains for non-WASM targets.
🪄 Autofix (Beta)

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: b5024351-a921-4ae0-9c43-41a617a4aae8

📥 Commits

Reviewing files that changed from the base of the PR and between c1138b4 and 88bcd4d.

📒 Files selected for processing (11)
  • crates/core/Cargo.toml
  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/node/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
  • crates/wasm/wrappers/esm/observability.d.ts
  • docs/observability-plugin/atif.mdx
  • python/nemo_relay/observability.py
  • python/nemo_relay/observability.pyi
  • python/tests/test_observability_plugin.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (46)
**/{Cargo.toml,**/*.rs}

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

Maintain consistency between Rust package names in Cargo.toml and their actual usage across the codebase

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.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/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/*.{rs,toml}

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

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/*.{py,txt,toml,cfg,yaml,yml}

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

Update Python package names and top-level module imports during coordinated rename operations

Files:

  • crates/core/Cargo.toml
  • python/tests/test_observability_plugin.py
  • python/nemo_relay/observability.py
**/Cargo.toml

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

Update WebAssembly crate names and generated package names during coordinated rename operations

Confirm or infer the target release version from upstream/main:Cargo.toml. Derive the release branch as release/<major>.<minor>.

Files:

  • crates/core/Cargo.toml
crates/{core,adaptive}/**

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

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

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

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

Ensure renamed public surfaces are reflected consistently in manifests and docs for large or public-facing changes

Files:

  • crates/core/Cargo.toml
  • docs/observability-plugin/atif.mdx
**/*.{md,mdx,py,sh,yaml,yml,toml,json}

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

Keep package names, repo references, and build commands current

Files:

  • crates/core/Cargo.toml
  • python/tests/test_observability_plugin.py
  • docs/observability-plugin/atif.mdx
  • python/nemo_relay/observability.py
**/*.toml

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in TOML configuration files using hash comment syntax

Files:

  • crates/core/Cargo.toml
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.

Files:

  • crates/core/Cargo.toml
  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/observability.d.ts
  • python/tests/test_observability_plugin.py
  • python/nemo_relay/observability.py
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
**

⚙️ CodeRabbit configuration file

**:

AGENTS.md

This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.

Project Overview

NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go, WebAssembly, and the raw C FFI are experimental and source-first.

The shared runtime model is:

  1. Scope stacks decide where work belongs and which scope-local behavior is visible.
  2. Middleware registries decide what guardrails and intercepts run around managed calls.
  3. Plugins install reusable runtime behavior from configuration.
  4. Events record runtime behavior in ATOF form.
  5. Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.

Repository Structure

The repository layout separates the Rust runtime, language bindings, documentation,
integration patches, and agent-facing skills.

crates/
  core/       # Rust core runtime crate, published as nemo-relay
  adaptive/   # Adaptive runtime primitives and plugin components
  python/     # PyO3 native extension for the Python package
  ffi/        # Raw C ABI layer used by downstream bindings such as Go
  node/       # NAPI Node.js binding and JavaScript/TypeScript entry points
  wasm/       # wasm-bindgen WebAssembly binding and JS wrappers
python/
  nemo_relay/  # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers
  tests/      # Python tests
go/
  nemo_relay/  # Experimental Go CGo binding and tests
fern/         # Fern documentation site
scripts/      # Stable wrappers and helper scripts; build/test/docs entry points live in justfile
third_party/  # P...

Files:

  • crates/core/Cargo.toml
  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
  • crates/node/observability.d.ts
  • python/tests/test_observability_plugin.py
  • docs/observability-plugin/atif.mdx
  • python/nemo_relay/observability.py
  • crates/core/tests/integration/atif_storage_tests.rs
  • python/nemo_relay/observability.pyi
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
{crates/adaptive/**,python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,go/nemo_relay/!(adaptive)/**,**/node/**,**/wasm/**}

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

Keep adaptive surface in sync across crates/adaptive, shared plugin behavior in core and bindings, Python adaptive/plugin wrappers in python/nemo_relay/adaptive.py and python/nemo_relay/plugin.py, Go adaptive helpers under go/nemo_relay/adaptive plus shared plugin helpers in go/nemo_relay, and Node/WebAssembly adaptive helpers and plugin wrappers

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
  • crates/node/observability.d.ts
{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}

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

{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}: Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)
Keep plugin context surfaces aligned across all language implementations

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
  • crates/node/observability.d.ts
**/*.{wasm,js,ts}{,x}

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

Ensure WebAssembly package naming conventions are consistent with generated package expectations and downstream consumption

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/observability.d.ts
crates/wasm/{wrappers,tests-js,scripts}/**/*.{js,ts,jsx,tsx}

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

Format changed WebAssembly JS/TS wrapper files with npm run precommit:format --workspace=nemo-relay-node -- crates/wasm/wrappers crates/wasm/tests-js crates/wasm/scripts

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
**/*.{js,ts,jsx,tsx}

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

Run Node.js formatting with npm run format --workspace=nemo-relay-node

Include SPDX license header in all JavaScript and TypeScript source files using double-slash comment syntax

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/observability.d.ts
crates/wasm/**/*.{js,ts,jsx,tsx}

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

Run WebAssembly formatting with npm run precommit:format --workspace=nemo-relay-node -- crates/wasm/wrappers crates/wasm/tests-js crates/wasm/scripts

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions: Rust and Python use snake_case, C FFI exports prefixed nemo_relay_, Go uses PascalCase for public APIs, Node.js uses camelCase.

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/observability.d.ts
  • python/tests/test_observability_plugin.py
  • python/nemo_relay/observability.py
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
crates/{python,ffi,node,wasm}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node,wasm}/**/*: 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/wasm/wrappers/esm/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
  • crates/node/observability.d.ts
{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/observability_plugin_tests.mjs
  • python/tests/test_observability_plugin.py
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
crates/node/**/*.{js,ts,jsx,tsx,json}

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

Format changed Node files with npm run format --workspace=nemo-relay-node

Files:

  • crates/node/observability.d.ts
crates/node/**/*.{ts,tsx,d.ts}

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

Use npm run check:docstrings --workspace=nemo-relay-node to validate public API docstring checks when surface docs changed

Files:

  • crates/node/observability.d.ts
crates/node/**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Node.js public entry points include the main runtime package plus nemo-relay-node/typed, nemo-relay-node/plugin, and nemo-relay-node/adaptive.

Files:

  • crates/node/observability.d.ts
**/test_*.{py,py}

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

Relevant integration tests or smoke coverage must exist for the integration path

Files:

  • python/tests/test_observability_plugin.py
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

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

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • python/tests/test_observability_plugin.py
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
{pyproject.toml,**/*.py}

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

Maintain consistency between Python package names in pyproject.toml and import paths used throughout the codebase

Files:

  • python/tests/test_observability_plugin.py
  • python/nemo_relay/observability.py
python/**/*test*.py

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

python/**/*test*.py: Do not add @pytest.mark.asyncio to any test in Python test files
Do not add a -> None return type annotation to test functions
When mocking a class, use unittest.mock.MagicMock or unittest.mock.AsyncMock with the spec constructor argument when necessary, rather than defining a new class
Prefix mocked class names with mock, not fake
Prefer pytest fixtures over helper methods in Python tests
Prefer pytest.mark.parametrize over creating individual tests for different input types

Files:

  • python/tests/test_observability_plugin.py
python/**/{conftest.py,*test*.py}

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

When creating a fixture follow the pattern: @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) def <fixture_name>_fixture() -> <return_type>: and only specify the scope argument when the value is something other than "function"

Files:

  • python/tests/test_observability_plugin.py
**/*.py

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

**/*.py: Run Python formatting with uv run ruff format python
Run Python testing with uv run pytest -k "<pattern>"

**/*.py: Use Ruff with rule sets E, F, W, I for Python linting
Use Ruff formatter with line length 120 and double quotes for Python code formatting
Run ty for Python type checking
Use Python snake_case naming convention for Python identifiers
Include SPDX license header in all Python source files using hash comment syntax
Validate Python code with uv run pre-commit run --all-files to enforce Ruff linting and formatting, and ty type checking

Files:

  • python/tests/test_observability_plugin.py
  • python/nemo_relay/observability.py
{docs/**,README.md,CONTRIBUTING.md}

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

{docs/**,README.md,CONTRIBUTING.md}: For docs-only changes, run targeted checks only if commands, package names, or examples changed. Use just docs for docs-site builds and just docs-linkcheck when links changed
Run docs site build with just docs

Files:

  • docs/observability-plugin/atif.mdx
{docs/**,README.md,CONTRIBUTING.md,**/*.md}

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

Run docs link validation with just docs-linkcheck when links change

Files:

  • docs/observability-plugin/atif.mdx
{docs/**,README.md}

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

Verify README and docs entry points still match current package names and paths for large or public-facing changes

Files:

  • docs/observability-plugin/atif.mdx
{docs/**,examples/**,README.md}

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

Verify examples still run with documented commands for large or public-facing changes

Files:

  • docs/observability-plugin/atif.mdx
**/*.mdx

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

In MDX files, top-of-file comments must use JSX comment delimiters: {/* to open and */} to close. Do not use HTML comments for MDX SPDX headers.

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

Files:

  • docs/observability-plugin/atif.mdx
**/*.{html,md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in HTML and Markdown files using HTML comment syntax

Files:

  • docs/observability-plugin/atif.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update embedded documentation snippets, patch docs, and binding-support notes if examples or supported bindings changed

Files:

  • docs/observability-plugin/atif.mdx
docs/**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run just docs or ./scripts/build-docs.sh html to regenerate ignored Fern API reference pages before validation for documentation site changes

Files:

  • docs/observability-plugin/atif.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/observability-plugin/atif.mdx
{crates/python/src/py_api/**/*.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi}

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

Update Python native binding in crates/python/src/py_api/mod.rs with Python wrapper docstring in python/nemo_relay/<module>.py and type stubs in python/nemo_relay/*.pyi modules

Files:

  • python/nemo_relay/observability.py
  • python/nemo_relay/observability.pyi
python/nemo_relay/**/*.py

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

Use snake_case naming convention for Python identifiers (e.g., nemo_relay.tools.call)

Format changed Python wrapper and test files with uv run ruff format python

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

Files:

  • python/nemo_relay/observability.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/observability.py
  • python/nemo_relay/observability.pyi
**/*.rs

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

Use snake_case naming convention for Rust identifiers (e.g., nemo_relay_tool_call)

**/*.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: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly 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
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Use cargo fmt for Rust code formatting
Run cargo clippy -- -D warnings to lint Rust code and treat all warnings as errors
Use Rust snake_case naming convention for Rust identifiers
Include SPDX license header in all Rust source files using double-slash comment syntax
Validate Rust code with uv run pre-commit run --all-files to enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...

Files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/*.{h,hpp,c,cpp,rs}

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

Ensure FFI header and library naming follows consistent conventions across platform-specific builds

Files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.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

crates/core/**/*.rs: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.

Files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Keep async behavior on the existing tokio-based model. Bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Use Json = serde_json::Value in Rust-facing runtime APIs for JSON payload handling.

Files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.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/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
🧠 Learnings (20)
📓 Common learnings
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-observability/SKILL.md:0-0
Timestamp: 2026-05-21T22:48:57.484Z
Learning: Applies to crates/core/src/observability/{atif,otel,openinference}.rs : When changing event fields in ATIF, OpenTelemetry, or OpenInference observability surfaces, keep the core event model in `crates/core/src/observability/atif.rs`, `crates/core/src/observability/otel.rs`, and `crates/core/src/observability/openinference.rs` in sync
📚 Learning: 2026-05-21T22:51:04.073Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-go-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:04.073Z
Learning: Applies to crates/core/**/*.rs : If the change touched `crates/core` or shared runtime semantics, also use `validate-change` for broader validation

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:52:14.330Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/validate-change/SKILL.md:0-0
Timestamp: 2026-05-21T22:52:14.330Z
Learning: Applies to crates/{core,adaptive}/** : If `crates/core` or `crates/adaptive` changed, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:51:34.986Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-wasm-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:34.986Z
Learning: If the change touched shared runtime semantics in `crates/core` or `crates/adaptive`, also use the `validate-change` skill

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:47:33.109Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-binding-feature/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:33.109Z
Learning: Applies to crates/wasm/src/api/**/*.rs : Update WebAssembly binding in `crates/wasm/src/api/mod.rs` for language-native bindings

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:49:46.956Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/rename-surfaces/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:46.956Z
Learning: Applies to **/Cargo.toml : Update WebAssembly crate names and generated package names during coordinated rename operations

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:49:35.949Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/prepare-pr/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:35.949Z
Learning: Applies to {crates/core,crates/adaptive}/**/* : Changes to `crates/core` or `crates/adaptive` must run the full language matrix

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:49:46.956Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/rename-surfaces/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:46.956Z
Learning: Applies to **/*.{rs,toml} : Update Rust crate names and module prefixes during coordinated rename operations

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:51:21.017Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-python-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:21.017Z
Learning: If `crates/core`, `crates/adaptive`, or shared runtime semantics changed, also use `validate-change` skill

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:51:11.713Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-node-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:11.713Z
Learning: If the change touched `crates/core`, `crates/adaptive`, or the generated Rust binding layer under `crates/node/src`, also use `validate-change` skill

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:47:58.898Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-middleware/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:58.898Z
Learning: Applies to crates/core/src/api/runtime/state.rs : Add registry fields as `SortedRegistry<GuardrailEntry<T>>` or `SortedRegistry<Intercept<T>>` to `NemoRelayContextState` in `crates/core/src/api/runtime/state.rs`

Applied to files:

  • crates/core/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
📚 Learning: 2026-05-07T18:04:44.387Z
Learnt from: mnajafian-nv
Repo: NVIDIA/NeMo-Flow PR: 67
File: integrations/openclaw/src/modules.ts:1-2
Timestamp: 2026-05-07T18:04:44.387Z
Learning: In NVIDIA/NeMo-Flow, TypeScript source files should use `//` line comments for SPDX headers (e.g., `// SPDX-FileCopyrightText: ...` and `// SPDX-License-Identifier: ...`) rather than C-style block comments (`/* ... */`). The repo’s copyright checker enforces this mapping, so `//` SPDX headers in `.ts` files should not be flagged as a style violation.

Applied to files:

  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/observability.d.ts
📚 Learning: 2026-05-21T22:52:14.330Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/validate-change/SKILL.md:0-0
Timestamp: 2026-05-21T22:52:14.330Z
Learning: For Node.js binding changes, use `test-node-binding`

Applied to files:

  • crates/node/tests/observability_plugin_tests.mjs
📚 Learning: 2026-05-21T22:48:57.484Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-observability/SKILL.md:0-0
Timestamp: 2026-05-21T22:48:57.484Z
Learning: Applies to crates/core/src/observability/{atif,otel,openinference}.rs : When changing event fields in ATIF, OpenTelemetry, or OpenInference observability surfaces, keep the core event model in `crates/core/src/observability/atif.rs`, `crates/core/src/observability/otel.rs`, and `crates/core/src/observability/openinference.rs` in sync

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
📚 Learning: 2026-05-29T21:25:49.977Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-29T21:25:49.977Z
Learning: Run tests for every language affected by a change. If you touch the Rust core runtime, middleware semantics, event shape, scope behavior, typed codecs, plugins, or observability, expect to validate every affected binding because the bindings share the same runtime contract.

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
📚 Learning: 2026-05-21T22:48:57.484Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-observability/SKILL.md:0-0
Timestamp: 2026-05-21T22:48:57.484Z
Learning: When event fields change, run Rust crate tests and execute `just test-rust` to validate the affected observability modules

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
📚 Learning: 2026-05-21T22:51:27.841Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-rust-core/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:27.841Z
Learning: Use narrower crate tests as a local debug loop, not as the final validation story for Rust changes

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
📚 Learning: 2026-05-21T22:47:58.898Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-middleware/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:58.898Z
Learning: Applies to crates/core/src/api/runtime/state.rs : Add chain execution helpers to `NemoRelayContextState` following the pattern of existing methods like `tool_sanitize_request_chain` or `tool_request_intercepts_chain`

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
📚 Learning: 2026-05-21T22:49:09.811Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-optimizer/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:09.811Z
Learning: Applies to {crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**} : Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
📚 Learning: 2026-05-21T22:51:04.073Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-go-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:04.073Z
Learning: Applies to crates/ffi/**/*.rs : If the change touched `crates/ffi`, also use `test-ffi-surface` for validation

Applied to files:

  • crates/core/tests/unit/observability/plugin_component_tests.rs
🔇 Additional comments (27)
crates/node/observability.d.ts (1)

28-34: LGTM!

Also applies to: 45-45

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

59-77: LGTM!

crates/wasm/wrappers/esm/observability.d.ts (1)

16-34: LGTM!

Also applies to: 45-45

python/nemo_relay/observability.py (2)

113-132: LGTM!


147-147: LGTM!

Also applies to: 248-248

python/nemo_relay/observability.pyi (1)

40-46: LGTM!

Also applies to: 58-58

python/tests/test_observability_plugin.py (1)

99-115: LGTM!

docs/observability-plugin/atif.mdx (2)

6-7: LGTM!


64-66: LGTM!

Also applies to: 81-115, 121-136

crates/core/src/observability/plugin_component.rs (7)

310-330: LGTM!


780-796: LGTM!


978-983: ⚡ Quick win

Confirm intentional silent suppression of sink upload errors at teardown.

last_error_result() now only surfaces fatal_error and ignores per-sink errors stored in sink_errors. Failed remote uploads will not propagate through plugin teardown, making upload failures invisible to callers relying on shutdown errors.

If "best-effort upload with silent drop on failure" is intended, consider adding a debug/trace log of accumulated sink_errors before returning. Otherwise, aggregate them.


1530-1639: LGTM!


1641-1675: LGTM!


1966-2030: LGTM!


2127-2223: LGTM!

crates/core/Cargo.toml (1)

23-29: LGTM!

crates/core/tests/unit/observability/plugin_component_tests.rs (4)

1177-1207: LGTM!


1320-1382: LGTM!


1384-1430: LGTM!


1432-1522: LGTM!

crates/core/tests/integration/atif_storage_tests.rs (6)

32-38: LGTM!


118-149: LGTM!


151-217: LGTM!


235-274: LGTM!


390-472: LGTM!


474-527: LGTM!

Comment thread crates/core/src/observability/plugin_component.rs
Comment thread crates/wasm/wrappers/esm/observability.d.ts Outdated
Comment thread crates/core/src/observability/plugin_component.rs
Comment thread crates/wasm/wrappers/esm/observability.d.ts Outdated
Comment thread crates/core/tests/integration/atif_storage_tests.rs
@willkill07 willkill07 force-pushed the wkk_feat/atif-http-storage branch from 88bcd4d to ba984cc Compare June 5, 2026 17:15
Signed-off-by: Will Killian <wkillian@nvidia.com>
@willkill07 willkill07 force-pushed the wkk_feat/atif-http-storage branch from ba984cc to 7e457d7 Compare June 5, 2026 17:24
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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/atif_storage_tests.rs`:
- Around line 510-520: The test currently joins the HTTP server
(server.handle.join()) before calling clear_plugin_configuration(), which hides
whether teardown triggered retries against a live server; move the
clear_plugin_configuration() call to before server.handle.join() so teardown
runs while the server is still alive, then after joining assert the received
requests via server.received.lock().unwrap() remain exactly one and that the
request properties (method/path) match; update the order around
server.handle.join(), clear_plugin_configuration(), and the assertions
referencing server.received to reflect this sequence (look for
clear_plugin_configuration, server.handle.join, and server.received in the
test).
🪄 Autofix (Beta)

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: e7152077-7f4a-49d1-89f9-1a2ca3bfffed

📥 Commits

Reviewing files that changed from the base of the PR and between 88bcd4d and ba984cc.

📒 Files selected for processing (11)
  • crates/core/Cargo.toml
  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/node/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
  • crates/wasm/wrappers/esm/observability.d.ts
  • docs/observability-plugin/atif.mdx
  • python/nemo_relay/observability.py
  • python/nemo_relay/observability.pyi
  • python/tests/test_observability_plugin.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (46)
{crates/adaptive/**,python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,go/nemo_relay/!(adaptive)/**,**/node/**,**/wasm/**}

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

Keep adaptive surface in sync across crates/adaptive, shared plugin behavior in core and bindings, Python adaptive/plugin wrappers in python/nemo_relay/adaptive.py and python/nemo_relay/plugin.py, Go adaptive helpers under go/nemo_relay/adaptive plus shared plugin helpers in go/nemo_relay, and Node/WebAssembly adaptive helpers and plugin wrappers

Files:

  • crates/node/observability.d.ts
  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}

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

{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}: Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)
Keep plugin context surfaces aligned across all language implementations

Files:

  • crates/node/observability.d.ts
  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
**/*.{wasm,js,ts}{,x}

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

Ensure WebAssembly package naming conventions are consistent with generated package expectations and downstream consumption

Files:

  • crates/node/observability.d.ts
  • crates/wasm/wrappers/esm/observability.d.ts
crates/node/**/*.{js,ts,jsx,tsx,json}

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

Format changed Node files with npm run format --workspace=nemo-relay-node

Files:

  • crates/node/observability.d.ts
crates/node/**/*.{ts,tsx,d.ts}

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

Use npm run check:docstrings --workspace=nemo-relay-node to validate public API docstring checks when surface docs changed

Files:

  • crates/node/observability.d.ts
**/*.{js,ts,jsx,tsx}

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

Run Node.js formatting with npm run format --workspace=nemo-relay-node

Include SPDX license header in all JavaScript and TypeScript source files using double-slash comment syntax

Files:

  • crates/node/observability.d.ts
  • crates/wasm/wrappers/esm/observability.d.ts
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.

Files:

  • crates/node/observability.d.ts
  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/core/Cargo.toml
  • python/nemo_relay/observability.py
  • python/tests/test_observability_plugin.py
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions: Rust and Python use snake_case, C FFI exports prefixed nemo_relay_, Go uses PascalCase for public APIs, Node.js uses camelCase.

Files:

  • crates/node/observability.d.ts
  • crates/wasm/wrappers/esm/observability.d.ts
  • python/nemo_relay/observability.py
  • python/tests/test_observability_plugin.py
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/src/observability/plugin_component.rs
crates/node/**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Node.js public entry points include the main runtime package plus nemo-relay-node/typed, nemo-relay-node/plugin, and nemo-relay-node/adaptive.

Files:

  • crates/node/observability.d.ts
crates/{python,ffi,node,wasm}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node,wasm}/**/*: 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/observability.d.ts
  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
**

⚙️ CodeRabbit configuration file

**:

AGENTS.md

This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.

Project Overview

NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go, WebAssembly, and the raw C FFI are experimental and source-first.

The shared runtime model is:

  1. Scope stacks decide where work belongs and which scope-local behavior is visible.
  2. Middleware registries decide what guardrails and intercepts run around managed calls.
  3. Plugins install reusable runtime behavior from configuration.
  4. Events record runtime behavior in ATOF form.
  5. Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.

Repository Structure

The repository layout separates the Rust runtime, language bindings, documentation,
integration patches, and agent-facing skills.

crates/
  core/       # Rust core runtime crate, published as nemo-relay
  adaptive/   # Adaptive runtime primitives and plugin components
  python/     # PyO3 native extension for the Python package
  ffi/        # Raw C ABI layer used by downstream bindings such as Go
  node/       # NAPI Node.js binding and JavaScript/TypeScript entry points
  wasm/       # wasm-bindgen WebAssembly binding and JS wrappers
python/
  nemo_relay/  # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers
  tests/      # Python tests
go/
  nemo_relay/  # Experimental Go CGo binding and tests
fern/         # Fern documentation site
scripts/      # Stable wrappers and helper scripts; build/test/docs entry points live in justfile
third_party/  # P...

Files:

  • crates/node/observability.d.ts
  • python/nemo_relay/observability.pyi
  • crates/wasm/wrappers/esm/observability.d.ts
  • crates/core/Cargo.toml
  • python/nemo_relay/observability.py
  • docs/observability-plugin/atif.mdx
  • crates/node/tests/observability_plugin_tests.mjs
  • python/tests/test_observability_plugin.py
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/src/observability/plugin_component.rs
{crates/python/src/py_api/**/*.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi}

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

Update Python native binding in crates/python/src/py_api/mod.rs with Python wrapper docstring in python/nemo_relay/<module>.py and type stubs in python/nemo_relay/*.pyi modules

Files:

  • python/nemo_relay/observability.pyi
  • python/nemo_relay/observability.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/observability.pyi
  • python/nemo_relay/observability.py
crates/wasm/{wrappers,tests-js,scripts}/**/*.{js,ts,jsx,tsx}

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

Format changed WebAssembly JS/TS wrapper files with npm run precommit:format --workspace=nemo-relay-node -- crates/wasm/wrappers crates/wasm/tests-js crates/wasm/scripts

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
crates/wasm/**/*.{js,ts,jsx,tsx}

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

Run WebAssembly formatting with npm run precommit:format --workspace=nemo-relay-node -- crates/wasm/wrappers crates/wasm/tests-js crates/wasm/scripts

Files:

  • crates/wasm/wrappers/esm/observability.d.ts
**/{Cargo.toml,**/*.rs}

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

Maintain consistency between Rust package names in Cargo.toml and their actual usage across the codebase

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/src/observability/plugin_component.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/Cargo.toml
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/*.{rs,toml}

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

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/*.{py,txt,toml,cfg,yaml,yml}

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

Update Python package names and top-level module imports during coordinated rename operations

Files:

  • crates/core/Cargo.toml
  • python/nemo_relay/observability.py
  • python/tests/test_observability_plugin.py
**/Cargo.toml

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

Update WebAssembly crate names and generated package names during coordinated rename operations

Confirm or infer the target release version from upstream/main:Cargo.toml. Derive the release branch as release/<major>.<minor>.

Files:

  • crates/core/Cargo.toml
crates/{core,adaptive}/**

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

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

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/src/observability/plugin_component.rs
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

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

Ensure renamed public surfaces are reflected consistently in manifests and docs for large or public-facing changes

Files:

  • crates/core/Cargo.toml
  • docs/observability-plugin/atif.mdx
**/*.{md,mdx,py,sh,yaml,yml,toml,json}

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

Keep package names, repo references, and build commands current

Files:

  • crates/core/Cargo.toml
  • python/nemo_relay/observability.py
  • docs/observability-plugin/atif.mdx
  • python/tests/test_observability_plugin.py
**/*.toml

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in TOML configuration files using hash comment syntax

Files:

  • crates/core/Cargo.toml
python/nemo_relay/**/*.py

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

Use snake_case naming convention for Python identifiers (e.g., nemo_relay.tools.call)

Format changed Python wrapper and test files with uv run ruff format python

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

Files:

  • python/nemo_relay/observability.py
{pyproject.toml,**/*.py}

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

Maintain consistency between Python package names in pyproject.toml and import paths used throughout the codebase

Files:

  • python/nemo_relay/observability.py
  • python/tests/test_observability_plugin.py
**/*.py

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

**/*.py: Run Python formatting with uv run ruff format python
Run Python testing with uv run pytest -k "<pattern>"

**/*.py: Use Ruff with rule sets E, F, W, I for Python linting
Use Ruff formatter with line length 120 and double quotes for Python code formatting
Run ty for Python type checking
Use Python snake_case naming convention for Python identifiers
Include SPDX license header in all Python source files using hash comment syntax
Validate Python code with uv run pre-commit run --all-files to enforce Ruff linting and formatting, and ty type checking

Files:

  • python/nemo_relay/observability.py
  • python/tests/test_observability_plugin.py
{docs/**,README.md,CONTRIBUTING.md}

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

{docs/**,README.md,CONTRIBUTING.md}: For docs-only changes, run targeted checks only if commands, package names, or examples changed. Use just docs for docs-site builds and just docs-linkcheck when links changed
Run docs site build with just docs

Files:

  • docs/observability-plugin/atif.mdx
{docs/**,README.md,CONTRIBUTING.md,**/*.md}

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

Run docs link validation with just docs-linkcheck when links change

Files:

  • docs/observability-plugin/atif.mdx
{docs/**,README.md}

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

Verify README and docs entry points still match current package names and paths for large or public-facing changes

Files:

  • docs/observability-plugin/atif.mdx
{docs/**,examples/**,README.md}

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

Verify examples still run with documented commands for large or public-facing changes

Files:

  • docs/observability-plugin/atif.mdx
**/*.mdx

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

In MDX files, top-of-file comments must use JSX comment delimiters: {/* to open and */} to close. Do not use HTML comments for MDX SPDX headers.

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

Files:

  • docs/observability-plugin/atif.mdx
**/*.{html,md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in HTML and Markdown files using HTML comment syntax

Files:

  • docs/observability-plugin/atif.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update embedded documentation snippets, patch docs, and binding-support notes if examples or supported bindings changed

Files:

  • docs/observability-plugin/atif.mdx
docs/**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run just docs or ./scripts/build-docs.sh html to regenerate ignored Fern API reference pages before validation for documentation site changes

Files:

  • docs/observability-plugin/atif.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/observability-plugin/atif.mdx
{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/observability_plugin_tests.mjs
  • python/tests/test_observability_plugin.py
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
**/test_*.{py,py}

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

Relevant integration tests or smoke coverage must exist for the integration path

Files:

  • python/tests/test_observability_plugin.py
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

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

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • python/tests/test_observability_plugin.py
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
python/**/*test*.py

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

python/**/*test*.py: Do not add @pytest.mark.asyncio to any test in Python test files
Do not add a -> None return type annotation to test functions
When mocking a class, use unittest.mock.MagicMock or unittest.mock.AsyncMock with the spec constructor argument when necessary, rather than defining a new class
Prefix mocked class names with mock, not fake
Prefer pytest fixtures over helper methods in Python tests
Prefer pytest.mark.parametrize over creating individual tests for different input types

Files:

  • python/tests/test_observability_plugin.py
python/**/{conftest.py,*test*.py}

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

When creating a fixture follow the pattern: @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) def <fixture_name>_fixture() -> <return_type>: and only specify the scope argument when the value is something other than "function"

Files:

  • python/tests/test_observability_plugin.py
**/*.rs

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

Use snake_case naming convention for Rust identifiers (e.g., nemo_relay_tool_call)

**/*.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: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly 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
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Use cargo fmt for Rust code formatting
Run cargo clippy -- -D warnings to lint Rust code and treat all warnings as errors
Use Rust snake_case naming convention for Rust identifiers
Include SPDX license header in all Rust source files using double-slash comment syntax
Validate Rust code with uv run pre-commit run --all-files to enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...

Files:

  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/*.{h,hpp,c,cpp,rs}

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

Ensure FFI header and library naming follows consistent conventions across platform-specific builds

Files:

  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/src/observability/plugin_component.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

crates/core/**/*.rs: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.

Files:

  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/src/observability/plugin_component.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Keep async behavior on the existing tokio-based model. Bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Use Json = serde_json::Value in Rust-facing runtime APIs for JSON payload handling.

Files:

  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/src/observability/plugin_component.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/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/src/observability/plugin_component.rs
🧠 Learnings (21)
📚 Learning: 2026-05-07T18:04:44.387Z
Learnt from: mnajafian-nv
Repo: NVIDIA/NeMo-Flow PR: 67
File: integrations/openclaw/src/modules.ts:1-2
Timestamp: 2026-05-07T18:04:44.387Z
Learning: In NVIDIA/NeMo-Flow, TypeScript source files should use `//` line comments for SPDX headers (e.g., `// SPDX-FileCopyrightText: ...` and `// SPDX-License-Identifier: ...`) rather than C-style block comments (`/* ... */`). The repo’s copyright checker enforces this mapping, so `//` SPDX headers in `.ts` files should not be flagged as a style violation.

Applied to files:

  • crates/node/observability.d.ts
  • crates/wasm/wrappers/esm/observability.d.ts
📚 Learning: 2026-05-21T22:49:17.713Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-packaging/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:17.713Z
Learning: Applies to **/*.{wasm,js,ts}{,x} : Ensure WebAssembly package naming conventions are consistent with generated package expectations and downstream consumption

Applied to files:

  • crates/wasm/wrappers/esm/observability.d.ts
📚 Learning: 2026-05-26T21:03:12.012Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/review-doc-style/SKILL.md:0-0
Timestamp: 2026-05-26T21:03:12.012Z
Learning: Applies to **/*.md|**/*.mdx|**/*.rst : Documentation must not claim support for bindings, features, or workflows that the repo no longer provides (Must-Fix)

Applied to files:

  • crates/wasm/wrappers/esm/observability.d.ts
📚 Learning: 2026-05-21T22:51:11.713Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-node-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:11.713Z
Learning: Applies to crates/node/**/*.{ts,tsx,d.ts} : Use `npm run check:docstrings --workspace=nemo-relay-node` to validate public API docstring checks when surface docs changed

Applied to files:

  • crates/wasm/wrappers/esm/observability.d.ts
📚 Learning: 2026-05-21T22:51:04.073Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-go-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:04.073Z
Learning: Applies to crates/core/**/*.rs : If the change touched `crates/core` or shared runtime semantics, also use `validate-change` for broader validation

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:47:33.109Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-binding-feature/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:33.109Z
Learning: Applies to crates/wasm/src/api/**/*.rs : Update WebAssembly binding in `crates/wasm/src/api/mod.rs` for language-native bindings

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:49:46.956Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/rename-surfaces/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:46.956Z
Learning: Applies to **/Cargo.toml : Update WebAssembly crate names and generated package names during coordinated rename operations

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:51:34.986Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-wasm-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:34.986Z
Learning: If the change touched shared runtime semantics in `crates/core` or `crates/adaptive`, also use the `validate-change` skill

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:52:14.330Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/validate-change/SKILL.md:0-0
Timestamp: 2026-05-21T22:52:14.330Z
Learning: Applies to crates/{core,adaptive}/** : If `crates/core` or `crates/adaptive` changed, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:49:46.956Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/rename-surfaces/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:46.956Z
Learning: Applies to **/*.{rs,toml} : Update Rust crate names and module prefixes during coordinated rename operations

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:47:58.898Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-middleware/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:58.898Z
Learning: Applies to crates/core/src/api/runtime/state.rs : Add registry fields as `SortedRegistry<GuardrailEntry<T>>` or `SortedRegistry<Intercept<T>>` to `NemoRelayContextState` in `crates/core/src/api/runtime/state.rs`

Applied to files:

  • crates/core/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
📚 Learning: 2026-05-21T22:49:35.949Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/prepare-pr/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:35.949Z
Learning: Applies to {crates/core,crates/adaptive}/**/* : Changes to `crates/core` or `crates/adaptive` must run the full language matrix

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:51:50.794Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/update-project-version/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:50.794Z
Learning: Applies to Cargo.toml : Keep `Cargo.toml` `[workspace.dependencies]` self-references aligned when the workspace version changes

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:51:21.017Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-python-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:21.017Z
Learning: If `crates/core`, `crates/adaptive`, or shared runtime semantics changed, also use `validate-change` skill

Applied to files:

  • crates/core/Cargo.toml
📚 Learning: 2026-05-21T22:52:14.330Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/validate-change/SKILL.md:0-0
Timestamp: 2026-05-21T22:52:14.330Z
Learning: For Node.js binding changes, use `test-node-binding`

Applied to files:

  • crates/node/tests/observability_plugin_tests.mjs
📚 Learning: 2026-05-21T22:48:57.484Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-observability/SKILL.md:0-0
Timestamp: 2026-05-21T22:48:57.484Z
Learning: Applies to crates/core/src/observability/{atif,otel,openinference}.rs : When changing event fields in ATIF, OpenTelemetry, or OpenInference observability surfaces, keep the core event model in `crates/core/src/observability/atif.rs`, `crates/core/src/observability/otel.rs`, and `crates/core/src/observability/openinference.rs` in sync

Applied to files:

  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/src/observability/plugin_component.rs
📚 Learning: 2026-05-21T22:48:57.484Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-observability/SKILL.md:0-0
Timestamp: 2026-05-21T22:48:57.484Z
Learning: When event fields change, run Rust crate tests and execute `just test-rust` to validate the affected observability modules

Applied to files:

  • crates/core/tests/unit/observability/plugin_component_tests.rs
📚 Learning: 2026-05-29T21:25:49.977Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-05-29T21:25:49.977Z
Learning: Run tests for every language affected by a change. If you touch the Rust core runtime, middleware semantics, event shape, scope behavior, typed codecs, plugins, or observability, expect to validate every affected binding because the bindings share the same runtime contract.

Applied to files:

  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/tests/integration/atif_storage_tests.rs
📚 Learning: 2026-05-21T22:51:04.073Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/test-go-binding/SKILL.md:0-0
Timestamp: 2026-05-21T22:51:04.073Z
Learning: Applies to crates/ffi/**/*.rs : If the change touched `crates/ffi`, also use `test-ffi-surface` for validation

Applied to files:

  • crates/core/tests/unit/observability/plugin_component_tests.rs
📚 Learning: 2026-05-21T22:47:58.898Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/add-middleware/SKILL.md:0-0
Timestamp: 2026-05-21T22:47:58.898Z
Learning: Applies to crates/core/src/api/runtime/state.rs : Add chain execution helpers to `NemoRelayContextState` following the pattern of existing methods like `tool_sanitize_request_chain` or `tool_request_intercepts_chain`

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
📚 Learning: 2026-05-21T22:49:09.811Z
Learnt from: CR
Repo: NVIDIA/NeMo-Relay PR: 0
File: .agents/skills/maintain-optimizer/SKILL.md:0-0
Timestamp: 2026-05-21T22:49:09.811Z
Learning: Applies to {crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**} : Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)

Applied to files:

  • crates/core/tests/integration/atif_storage_tests.rs
🔇 Additional comments (16)
crates/wasm/wrappers/esm/observability.d.ts (1)

16-34: WASM storage support mismatch already flagged.

Previous reviewers noted that these type definitions advertise storage support that is rejected at runtime on WebAssembly targets (docs state "remote storage is not supported" on WebAssembly at line 393-394). This remains unaddressed.

Also applies to: 45-45

crates/node/observability.d.ts (2)

28-34: LGTM!


45-45: LGTM!

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

59-77: LGTM!

python/nemo_relay/observability.py (3)

113-133: LGTM!


147-147: LGTM!


248-248: LGTM!

python/nemo_relay/observability.pyi (1)

40-46: LGTM!

Also applies to: 58-58

python/tests/test_observability_plugin.py (1)

19-19: LGTM!

Also applies to: 99-116

docs/observability-plugin/atif.mdx (4)

64-66: LGTM!


81-116: LGTM!


121-136: LGTM!


391-394: LGTM!

crates/core/tests/unit/observability/plugin_component_tests.rs (1)

1433-1522: ⚡ Quick win

Serialize the header_env env-var tests to avoid process-wide env races.

These tests mutate global process environment using unsafe { std::env::set_var/remove_var }; add a shared env mutex/guard (e.g., reuse crate::observability::test_mutex() if available, otherwise a dedicated env mutex) and wrap the entire test body to prevent parallel-test flakiness.

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

316-330: ⚡ Quick win

Reject unknown fields in HttpStorageConfig.

HttpStorageConfig currently relies on Serde’s default struct deserialization, which ignores unknown keys—so config typos can be silently accepted. Add #[serde(deny_unknown_fields)] to fail fast on invalid config.

Suggested fix
-#[derive(Debug, Clone, Serialize, Deserialize)]
+#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(deny_unknown_fields)]
 pub struct HttpStorageConfig {
crates/core/tests/integration/atif_storage_tests.rs (1)

49-49: ⚡ Quick win

Serialize std::env mutations in atif_storage_tests

In crates/core/tests/integration/atif_storage_tests.rs, any std::env::set_var/remove_var should be protected by a process-wide env guard that restores values via Drop (to avoid cross-test races and leaked state on failure). For the non-2xx unhealthy-sink test, ensure plugin teardown/clear_plugin_configuration() happens while the HTTP server is still running, and assert the request count doesn’t change after teardown to validate “no extra HTTP attempt during teardown”.

Comment thread crates/core/tests/integration/atif_storage_tests.rs
Copy link
Copy Markdown
Contributor

@mnajafian-nv mnajafian-nv left a comment

Choose a reason for hiding this comment

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

LGTM, happy to approve to unblock as inline questions/suggestions are being addressed

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
crates/core/src/observability/plugin_component.rs (1)

1507-1519: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validate rendered ATIF filename_template as an HTTP header value for x-nemo-relay-atif-filename

filename_template is only checked for the {session_id} placeholder in validate_atif_values, but for HTTP uploads the rendered filename is used directly as the request header x-nemo-relay-atif-filename in post_atif_http. Configs that render to invalid header values (control characters / non-visible ASCII) will pass config validation and fail later during request construction. Render/validate a sample rendered filename (using the same HeaderValue::from_str rules) and emit a config diagnostic when it’s invalid; note that configured HTTP header values are already validated via HeaderValue::from_str. (docs.rs)

🤖 Prompt for 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.

In `@crates/core/src/observability/plugin_component.rs` around lines 1507 - 1519,
validate_atif_values only checks for "{session_id}" in section.filename_template
but doesn't ensure the rendered filename is a valid HTTP header value; update
validate_atif_values to render a sample filename (replace "{session_id}" with a
safe sample like "sample-session") and validate it using the same rules as
post_atif_http by attempting HeaderValue::from_str on the rendered string, and
if that fails call push_policy_diag (same usage as the existing
filename_template diagnostic) to emit a configuration diagnostic; reference
function names: validate_atif_values, post_atif_http, push_policy_diag, and the
field filename_template so reviewers can find and apply the change consistently.
🤖 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/atif_storage_tests.rs`:
- Around line 395-398: The test is mutating the process-wide env var
"NEMO_RELAY_ATIF_HTTP_TEST_TOKEN" unsafely; instead, update the tests to avoid
touching std::env by passing a literal authorization header into the config
builder: modify build_http_observability_config (or the call site in the test)
to use a concrete headers entry for "authorization" rather than relying on
header_env.authorization resolution, remove the unsafe
std::env::set_var/remove_var and PLUGIN_TEST_LOCK usage from these tests, and
ensure the test constructs the observability config with the explicit
authorization header (or alternatively move env-resolution into an isolated
subprocess) so no process-wide env mutations occur.

In `@crates/core/tests/unit/observability/plugin_component_tests.rs`:
- Around line 1432-1522: Tests
atif_storage_http_header_env_missing_env_is_rejected,
atif_storage_http_header_env_empty_env_is_rejected and
atif_storage_http_header_env_present_env_is_accepted use unnecessary unsafe
blocks to set/remove environment variables which is fragile under parallel test
execution; remove the unsafe blocks and call std::env::set_var /
std::env::remove_var directly, and to ensure isolation add a test-level
serialization strategy (e.g. annotate those test functions with
serial_test::serial) or switch to a scoped env helper like the temp_env crate so
the env is reliably restored on panic.

---

Outside diff comments:
In `@crates/core/src/observability/plugin_component.rs`:
- Around line 1507-1519: validate_atif_values only checks for "{session_id}" in
section.filename_template but doesn't ensure the rendered filename is a valid
HTTP header value; update validate_atif_values to render a sample filename
(replace "{session_id}" with a safe sample like "sample-session") and validate
it using the same rules as post_atif_http by attempting HeaderValue::from_str on
the rendered string, and if that fails call push_policy_diag (same usage as the
existing filename_template diagnostic) to emit a configuration diagnostic;
reference function names: validate_atif_values, post_atif_http,
push_policy_diag, and the field filename_template so reviewers can find and
apply the change consistently.
🪄 Autofix (Beta)

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: 8ea267a7-cf34-4c1b-86ca-bdbceebc36dc

📥 Commits

Reviewing files that changed from the base of the PR and between ba984cc and 7e457d7.

📒 Files selected for processing (10)
  • crates/core/Cargo.toml
  • crates/core/src/observability/plugin_component.rs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/node/observability.d.ts
  • crates/node/tests/observability_plugin_tests.mjs
  • docs/observability-plugin/atif.mdx
  • python/nemo_relay/observability.py
  • python/nemo_relay/observability.pyi
  • python/tests/test_observability_plugin.py
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Check / Run
🧰 Additional context used
📓 Path-based instructions (44)
{crates/python/src/py_api/**/*.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi}

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

Update Python native binding in crates/python/src/py_api/mod.rs with Python wrapper docstring in python/nemo_relay/<module>.py and type stubs in python/nemo_relay/*.pyi modules

Files:

  • python/nemo_relay/observability.py
  • python/nemo_relay/observability.pyi
python/nemo_relay/**/*.py

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

Use snake_case naming convention for Python identifiers (e.g., nemo_relay.tools.call)

Format changed Python wrapper and test files with uv run ruff format python

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

Files:

  • python/nemo_relay/observability.py
{pyproject.toml,**/*.py}

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

Maintain consistency between Python package names in pyproject.toml and import paths used throughout the codebase

Files:

  • python/nemo_relay/observability.py
  • python/tests/test_observability_plugin.py
**/*.{py,txt,toml,cfg,yaml,yml}

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

Update Python package names and top-level module imports during coordinated rename operations

Files:

  • python/nemo_relay/observability.py
  • crates/core/Cargo.toml
  • python/tests/test_observability_plugin.py
**/*.py

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

**/*.py: Run Python formatting with uv run ruff format python
Run Python testing with uv run pytest -k "<pattern>"

**/*.py: Use Ruff with rule sets E, F, W, I for Python linting
Use Ruff formatter with line length 120 and double quotes for Python code formatting
Run ty for Python type checking
Use Python snake_case naming convention for Python identifiers
Include SPDX license header in all Python source files using hash comment syntax
Validate Python code with uv run pre-commit run --all-files to enforce Ruff linting and formatting, and ty type checking

Files:

  • python/nemo_relay/observability.py
  • python/tests/test_observability_plugin.py
**/*.{md,mdx,py,sh,yaml,yml,toml,json}

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

Keep package names, repo references, and build commands current

Files:

  • python/nemo_relay/observability.py
  • crates/core/Cargo.toml
  • python/tests/test_observability_plugin.py
  • docs/observability-plugin/atif.mdx
**/*.{rs,py,js,ts,tsx,jsx,go,sh,toml,yaml,yml,md}

📄 CodeRabbit inference engine (AGENTS.md)

Keep SPDX headers on source, docs, scripts, and configuration files. The project is Apache-2.0.

Files:

  • python/nemo_relay/observability.py
  • crates/core/Cargo.toml
  • python/tests/test_observability_plugin.py
  • crates/node/observability.d.ts
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/*.{rs,py,go,js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Follow binding naming conventions: Rust and Python use snake_case, C FFI exports prefixed nemo_relay_, Go uses PascalCase for public APIs, Node.js uses camelCase.

Files:

  • python/nemo_relay/observability.py
  • python/tests/test_observability_plugin.py
  • crates/node/observability.d.ts
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
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/observability.py
  • python/nemo_relay/observability.pyi
**

⚙️ CodeRabbit configuration file

**:

AGENTS.md

This file provides guidance to agents, including Claude Code and OpenAI Codex, when working in this repository.

Project Overview

NeMo Relay is a multi-language agent runtime framework for execution scopes, lifecycle events, middleware, plugins, and observability around tool and LLM calls. The core runtime is Rust. Primary supported bindings are Rust, Python, and Node.js. Go, WebAssembly, and the raw C FFI are experimental and source-first.

The shared runtime model is:

  1. Scope stacks decide where work belongs and which scope-local behavior is visible.
  2. Middleware registries decide what guardrails and intercepts run around managed calls.
  3. Plugins install reusable runtime behavior from configuration.
  4. Events record runtime behavior in ATOF form.
  5. Subscribers and exporters consume events in-process or export them to ATIF, OpenTelemetry, OpenInference, or other backends.

Repository Structure

The repository layout separates the Rust runtime, language bindings, documentation,
integration patches, and agent-facing skills.

crates/
  core/       # Rust core runtime crate, published as nemo-relay
  adaptive/   # Adaptive runtime primitives and plugin components
  python/     # PyO3 native extension for the Python package
  ffi/        # Raw C ABI layer used by downstream bindings such as Go
  node/       # NAPI Node.js binding and JavaScript/TypeScript entry points
  wasm/       # wasm-bindgen WebAssembly binding and JS wrappers
python/
  nemo_relay/  # Python wrapper package: scopes, tools, LLM, middleware, typed helpers, plugins, adaptive helpers
  tests/      # Python tests
go/
  nemo_relay/  # Experimental Go CGo binding and tests
fern/         # Fern documentation site
scripts/      # Stable wrappers and helper scripts; build/test/docs entry points live in justfile
third_party/  # P...

Files:

  • python/nemo_relay/observability.py
  • crates/core/Cargo.toml
  • python/tests/test_observability_plugin.py
  • crates/node/tests/observability_plugin_tests.mjs
  • python/nemo_relay/observability.pyi
  • docs/observability-plugin/atif.mdx
  • crates/node/observability.d.ts
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/{Cargo.toml,**/*.rs}

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

Maintain consistency between Rust package names in Cargo.toml and their actual usage across the codebase

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.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/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/*.{rs,toml}

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

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/Cargo.toml

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

Update WebAssembly crate names and generated package names during coordinated rename operations

Confirm or infer the target release version from upstream/main:Cargo.toml. Derive the release branch as release/<major>.<minor>.

Files:

  • crates/core/Cargo.toml
crates/{core,adaptive}/**

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

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

Files:

  • crates/core/Cargo.toml
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

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

Ensure renamed public surfaces are reflected consistently in manifests and docs for large or public-facing changes

Files:

  • crates/core/Cargo.toml
  • docs/observability-plugin/atif.mdx
**/*.toml

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in TOML configuration files using hash comment syntax

Files:

  • crates/core/Cargo.toml
**/test_*.{py,py}

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

Relevant integration tests or smoke coverage must exist for the integration path

Files:

  • python/tests/test_observability_plugin.py
{crates/adaptive/**/*.rs,**/*test*.{rs,py,go,ts,js},**/*adaptive*test*.{rs,py,go,ts,js},docs/plugins/adaptive/**}

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

Maintain documented and tested validation and report behavior for adaptive surfaces

Files:

  • python/tests/test_observability_plugin.py
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
python/**/*test*.py

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

python/**/*test*.py: Do not add @pytest.mark.asyncio to any test in Python test files
Do not add a -> None return type annotation to test functions
When mocking a class, use unittest.mock.MagicMock or unittest.mock.AsyncMock with the spec constructor argument when necessary, rather than defining a new class
Prefix mocked class names with mock, not fake
Prefer pytest fixtures over helper methods in Python tests
Prefer pytest.mark.parametrize over creating individual tests for different input types

Files:

  • python/tests/test_observability_plugin.py
python/**/{conftest.py,*test*.py}

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

When creating a fixture follow the pattern: @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) def <fixture_name>_fixture() -> <return_type>: and only specify the scope argument when the value is something other than "function"

Files:

  • python/tests/test_observability_plugin.py
{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:

  • python/tests/test_observability_plugin.py
  • crates/node/tests/observability_plugin_tests.mjs
  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
{crates/adaptive/**,python/nemo_relay/adaptive.py,python/nemo_relay/plugin.py,go/nemo_relay/adaptive/**,go/nemo_relay/!(adaptive)/**,**/node/**,**/wasm/**}

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

Keep adaptive surface in sync across crates/adaptive, shared plugin behavior in core and bindings, Python adaptive/plugin wrappers in python/nemo_relay/adaptive.py and python/nemo_relay/plugin.py, Go adaptive helpers under go/nemo_relay/adaptive plus shared plugin helpers in go/nemo_relay, and Node/WebAssembly adaptive helpers and plugin wrappers

Files:

  • crates/node/tests/observability_plugin_tests.mjs
  • crates/node/observability.d.ts
{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}

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

{crates/adaptive/**,python/nemo_relay/plugin.py,go/nemo_relay/**,**/node/**,**/wasm/**}: Maintain consistent plugin lifecycle across all language bindings (Python, Go, Node/WebAssembly, and Rust)
Keep plugin context surfaces aligned across all language implementations

Files:

  • crates/node/tests/observability_plugin_tests.mjs
  • crates/node/observability.d.ts
crates/{python,ffi,node,wasm}/**/*

⚙️ CodeRabbit configuration file

crates/{python,ffi,node,wasm}/**/*: 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/observability_plugin_tests.mjs
  • crates/node/observability.d.ts
{docs/**,README.md,CONTRIBUTING.md}

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

{docs/**,README.md,CONTRIBUTING.md}: For docs-only changes, run targeted checks only if commands, package names, or examples changed. Use just docs for docs-site builds and just docs-linkcheck when links changed
Run docs site build with just docs

Files:

  • docs/observability-plugin/atif.mdx
{docs/**,README.md,CONTRIBUTING.md,**/*.md}

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

Run docs link validation with just docs-linkcheck when links change

Files:

  • docs/observability-plugin/atif.mdx
{docs/**,README.md}

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

Verify README and docs entry points still match current package names and paths for large or public-facing changes

Files:

  • docs/observability-plugin/atif.mdx
{docs/**,examples/**,README.md}

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

Verify examples still run with documented commands for large or public-facing changes

Files:

  • docs/observability-plugin/atif.mdx
**/*.mdx

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

In MDX files, top-of-file comments must use JSX comment delimiters: {/* to open and */} to close. Do not use HTML comments for MDX SPDX headers.

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

Files:

  • docs/observability-plugin/atif.mdx
**/*.{html,md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header in HTML and Markdown files using HTML comment syntax

Files:

  • docs/observability-plugin/atif.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update embedded documentation snippets, patch docs, and binding-support notes if examples or supported bindings changed

Files:

  • docs/observability-plugin/atif.mdx
docs/**

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Run just docs or ./scripts/build-docs.sh html to regenerate ignored Fern API reference pages before validation for documentation site changes

Files:

  • docs/observability-plugin/atif.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/observability-plugin/atif.mdx
**/*.{wasm,js,ts}{,x}

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

Ensure WebAssembly package naming conventions are consistent with generated package expectations and downstream consumption

Files:

  • crates/node/observability.d.ts
crates/node/**/*.{js,ts,jsx,tsx,json}

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

Format changed Node files with npm run format --workspace=nemo-relay-node

Files:

  • crates/node/observability.d.ts
crates/node/**/*.{ts,tsx,d.ts}

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

Use npm run check:docstrings --workspace=nemo-relay-node to validate public API docstring checks when surface docs changed

Files:

  • crates/node/observability.d.ts
**/*.{js,ts,jsx,tsx}

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

Run Node.js formatting with npm run format --workspace=nemo-relay-node

Include SPDX license header in all JavaScript and TypeScript source files using double-slash comment syntax

Files:

  • crates/node/observability.d.ts
crates/node/**/*.{js,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Node.js public entry points include the main runtime package plus nemo-relay-node/typed, nemo-relay-node/plugin, and nemo-relay-node/adaptive.

Files:

  • crates/node/observability.d.ts
**/*.rs

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

Use snake_case naming convention for Rust identifiers (e.g., nemo_relay_tool_call)

**/*.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: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly 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
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

**/*.rs: Use cargo fmt for Rust code formatting
Run cargo clippy -- -D warnings to lint Rust code and treat all warnings as errors
Use Rust snake_case naming convention for Rust identifiers
Include SPDX license header in all Rust source files using double-slash comment syntax
Validate Rust code with uv run pre-commit run --all-files to enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...

Files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
**/*.{h,hpp,c,cpp,rs}

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

Ensure FFI header and library naming follows consistent conventions across platform-specific builds

Files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.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

crates/core/**/*.rs: Use Json = serde_json::Value in Rust-facing runtime APIs where the existing code expects JSON payloads.
Use Result<T> with FlowError in core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.

Files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
crates/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

crates/**/*.rs: Keep async behavior on the existing tokio-based model. Bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Use Json = serde_json::Value in Rust-facing runtime APIs for JSON payload handling.

Files:

  • crates/core/tests/integration/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.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/atif_storage_tests.rs
  • crates/core/tests/unit/observability/plugin_component_tests.rs
  • crates/core/src/observability/plugin_component.rs
🧠 Learnings (1)
📚 Learning: 2026-05-07T18:04:44.387Z
Learnt from: mnajafian-nv
Repo: NVIDIA/NeMo-Flow PR: 67
File: integrations/openclaw/src/modules.ts:1-2
Timestamp: 2026-05-07T18:04:44.387Z
Learning: In NVIDIA/NeMo-Flow, TypeScript source files should use `//` line comments for SPDX headers (e.g., `// SPDX-FileCopyrightText: ...` and `// SPDX-License-Identifier: ...`) rather than C-style block comments (`/* ... */`). The repo’s copyright checker enforces this mapping, so `//` SPDX headers in `.ts` files should not be flagged as a style violation.

Applied to files:

  • crates/node/observability.d.ts
🔇 Additional comments (21)
crates/core/tests/unit/observability/plugin_component_tests.rs (7)

1169-1169: LGTM!

Also applies to: 1239-1239, 1246-1246, 1552-1552


1177-1207: LGTM!


1227-1248: LGTM!


1013-1013: LGTM!


1320-1338: LGTM!


1340-1358: LGTM!


1360-1382: LGTM!

crates/node/observability.d.ts (2)

28-34: LGTM!


45-45: LGTM!

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

59-77: LGTM!

python/nemo_relay/observability.py (3)

113-133: LGTM!


147-147: LGTM!


248-248: LGTM!

python/nemo_relay/observability.pyi (2)

40-46: LGTM!


58-58: LGTM!

python/tests/test_observability_plugin.py (2)

19-19: LGTM!


99-115: LGTM!

docs/observability-plugin/atif.mdx (1)

64-66: LGTM!

Also applies to: 81-116, 134-135

crates/core/Cargo.toml (1)

23-29: LGTM!

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

1546-1567: ⚡ Quick win

Reject user-supplied ATIF reserved HTTP headers to prevent duplicate values

validate_atif_http_header_name should reject reserved ATIF header names (not just header-name syntax) so post_atif_http can’t merge user-supplied values with runtime ATIF headers in a way that produces duplicate header values (e.g., content-type, x-nemo-relay-atif-*) and breaks parsers. Add case-insensitive reserved-name collision checks and ensure runtime ATIF headers replace user values on collision.

crates/core/src/observability/plugin_component.rs (validate_atif_http_header_name ~1618, post_atif_http ~2198-2203).

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

510-520: Run teardown before shutting down the test server.

Joining the server first still leaves a blind spot: this test will pass even if teardown retries the unhealthy sink only after the listener is gone and the error gets swallowed. Move clear_plugin_configuration() before join() and assert the request count afterward. As per coding guidelines, {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.

Comment thread crates/core/tests/integration/atif_storage_tests.rs
Comment thread crates/core/tests/unit/observability/plugin_component_tests.rs
@willkill07
Copy link
Copy Markdown
Member Author

/merge

@rapids-bot rapids-bot Bot merged commit 4fcd183 into NVIDIA:main Jun 5, 2026
72 checks passed
Comment thread crates/core/src/observability/plugin_component.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants