feat: add ATIF HTTP storage export#231
Conversation
WalkthroughThis PR adds HTTP endpoint support for ATIF remote trajectory uploads alongside S3, extending the observability plugin with a new ChangesHTTP Storage Backend Integration
🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
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 winDon't turn quarantined sink failures into teardown failures.
complete_scope_write()already marks a bad remote sink unhealthy andsink_targets()stops using it on later trajectories. Foldingsink_errorsback intolast_error_result()means one 5xx response still makesclear_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
📒 Files selected for processing (11)
crates/core/Cargo.tomlcrates/core/src/observability/plugin_component.rscrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/node/observability.d.tscrates/node/tests/observability_plugin_tests.mjscrates/wasm/wrappers/esm/observability.d.tsdocs/observability-plugin/atif.mdxpython/nemo_relay/observability.pypython/nemo_relay/observability.pyipython/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.pycrates/core/tests/integration/atif_storage_tests.rscrates/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.tomland import paths used throughout the codebase
Files:
python/tests/test_observability_plugin.pypython/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.pycrates/core/Cargo.tomlpython/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.asyncioto any test in Python test files
Do not add a-> Nonereturn type annotation to test functions
When mocking a class, useunittest.mock.MagicMockorunittest.mock.AsyncMockwith thespecconstructor argument when necessary, rather than defining a new class
Prefix mocked class names withmock, notfake
Prefer pytest fixtures over helper methods in Python tests
Preferpytest.mark.parametrizeover 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 withuv run ruff format python
Run Python testing withuv 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
Runtyfor 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 withuv run pre-commit run --all-filesto enforce Ruff linting and formatting, and ty type checking
Files:
python/tests/test_observability_plugin.pypython/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.pycrates/core/Cargo.tomldocs/observability-plugin/atif.mdxpython/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.pycrates/wasm/wrappers/esm/observability.d.tscrates/core/Cargo.tomlpython/nemo_relay/observability.pycrates/node/observability.d.tscrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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 prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
python/tests/test_observability_plugin.pycrates/wasm/wrappers/esm/observability.d.tspython/nemo_relay/observability.pycrates/node/observability.d.tscrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.pycrates/node/tests/observability_plugin_tests.mjscrates/core/tests/integration/atif_storage_tests.rscrates/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:
- Scope stacks decide where work belongs and which scope-local behavior is visible.
- Middleware registries decide what guardrails and intercepts run around managed calls.
- Plugins install reusable runtime behavior from configuration.
- Events record runtime behavior in ATOF form.
- 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.pypython/nemo_relay/observability.pyicrates/wasm/wrappers/esm/observability.d.tscrates/core/Cargo.tomldocs/observability-plugin/atif.mdxpython/nemo_relay/observability.pycrates/node/tests/observability_plugin_tests.mjscrates/node/observability.d.tscrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.rswith Python wrapper docstring inpython/nemo_relay/<module>.pyand type stubs inpython/nemo_relay/*.pyimodules
Files:
python/nemo_relay/observability.pyipython/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.pyipython/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.tscrates/node/tests/observability_plugin_tests.mjscrates/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.tscrates/node/tests/observability_plugin_tests.mjscrates/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.tscrates/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-nodeInclude SPDX license header in all JavaScript and TypeScript source files using double-slash comment syntax
Files:
crates/wasm/wrappers/esm/observability.d.tscrates/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.tscrates/node/tests/observability_plugin_tests.mjscrates/node/observability.d.ts
**/{Cargo.toml,**/*.rs}
📄 CodeRabbit inference engine (.agents/skills/maintain-packaging/SKILL.md)
Maintain consistency between Rust package names in
Cargo.tomland their actual usage across the codebase
Files:
crates/core/Cargo.tomlcrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/core/src/observability/plugin_component.rs
{crates/core,crates/adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
Changes to
crates/coreorcrates/adaptivemust run the full language matrix
Files:
crates/core/Cargo.tomlcrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.tomlcrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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 asrelease/<major>.<minor>.
Files:
crates/core/Cargo.toml
crates/{core,adaptive}/**
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If
crates/coreorcrates/adaptivechanged, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly
Files:
crates/core/Cargo.tomlcrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.tomldocs/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. Usejust docsfor docs-site builds andjust docs-linkcheckwhen links changed
Run docs site build withjust 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-linkcheckwhen 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 docsor./scripts/build-docs.sh htmlto 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_casenaming convention for Python identifiers (e.g.,nemo_relay.tools.call)Format changed Python wrapper and test files with
uv run ruff format pythonPython wrapper modules live under
python/nemo_relay/; the native extension is built fromcrates/pythonwithmaturin.
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-nodeto 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, andnemo-relay-node/adaptive.
Files:
crates/node/observability.d.ts
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Use
snake_casenaming convention for Rust identifiers (e.g.,nemo_relay_tool_call)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node work
**/*.rs: Runcargo fmt --allto format all Rust code
Runcargo clippy --workspace --all-targets -- -D warningsto enforce all clippy lints as errors
**/*.rs: Runcargo fmt --allwhen Rust files changed as part of WebAssembly work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files changed as part of WebAssembly work
**/*.rs: If any Rust code changed, always runjust test-rust
If any Rust code changed, also runcargo fmt --all
If any Rust code changed, also runcargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting withcargo fmt --all
Run Rust linting withcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Usecargo fmtfor Rust code formatting
Runcargo clippy -- -D warningsto 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 withuv run pre-commit run --all-filesto enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...
Files:
crates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/core/src/observability/plugin_component.rs
crates/core/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)
If the change touched
crates/coreor shared runtime semantics, also usevalidate-changefor broader validation
crates/core/**/*.rs: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.
Files:
crates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.
UseJson = serde_json::Valuein Rust-facing runtime APIs for JSON payload handling.
Files:
crates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.tscrates/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.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.rscrates/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.rscrates/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 winConfirm
timeout_millisdefault and “must be positive” validation
HttpStorageConfig.timeout_millisusesdefault_timeout_millis()which returns3_000, matching the docs. Validation treatstimeout_millis == 0as invalid (error: “must be positive”), so the requirement effectively meanstimeout_millis >= 1.
c1138b4 to
88bcd4d
Compare
There was a problem hiding this comment.
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
📒 Files selected for processing (11)
crates/core/Cargo.tomlcrates/core/src/observability/plugin_component.rscrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/node/observability.d.tscrates/node/tests/observability_plugin_tests.mjscrates/wasm/wrappers/esm/observability.d.tsdocs/observability-plugin/atif.mdxpython/nemo_relay/observability.pypython/nemo_relay/observability.pyipython/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.tomland their actual usage across the codebase
Files:
crates/core/Cargo.tomlcrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/core/src/observability/plugin_component.rs
{crates/core,crates/adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
Changes to
crates/coreorcrates/adaptivemust run the full language matrix
Files:
crates/core/Cargo.tomlcrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.tomlcrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.tomlpython/tests/test_observability_plugin.pypython/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 asrelease/<major>.<minor>.
Files:
crates/core/Cargo.toml
crates/{core,adaptive}/**
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If
crates/coreorcrates/adaptivechanged, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly
Files:
crates/core/Cargo.tomlcrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.tomldocs/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.tomlpython/tests/test_observability_plugin.pydocs/observability-plugin/atif.mdxpython/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.tomlcrates/wasm/wrappers/esm/observability.d.tscrates/node/observability.d.tspython/tests/test_observability_plugin.pypython/nemo_relay/observability.pycrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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:
- Scope stacks decide where work belongs and which scope-local behavior is visible.
- Middleware registries decide what guardrails and intercepts run around managed calls.
- Plugins install reusable runtime behavior from configuration.
- Events record runtime behavior in ATOF form.
- 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.tomlcrates/wasm/wrappers/esm/observability.d.tscrates/node/tests/observability_plugin_tests.mjscrates/node/observability.d.tspython/tests/test_observability_plugin.pydocs/observability-plugin/atif.mdxpython/nemo_relay/observability.pycrates/core/tests/integration/atif_storage_tests.rspython/nemo_relay/observability.pyicrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.tscrates/node/tests/observability_plugin_tests.mjscrates/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.tscrates/node/tests/observability_plugin_tests.mjscrates/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.tscrates/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-nodeInclude SPDX license header in all JavaScript and TypeScript source files using double-slash comment syntax
Files:
crates/wasm/wrappers/esm/observability.d.tscrates/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 prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
crates/wasm/wrappers/esm/observability.d.tscrates/node/observability.d.tspython/tests/test_observability_plugin.pypython/nemo_relay/observability.pycrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.tscrates/node/tests/observability_plugin_tests.mjscrates/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.mjspython/tests/test_observability_plugin.pycrates/core/tests/integration/atif_storage_tests.rscrates/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-nodeto 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, andnemo-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.pycrates/core/tests/integration/atif_storage_tests.rscrates/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.tomland import paths used throughout the codebase
Files:
python/tests/test_observability_plugin.pypython/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.asyncioto any test in Python test files
Do not add a-> Nonereturn type annotation to test functions
When mocking a class, useunittest.mock.MagicMockorunittest.mock.AsyncMockwith thespecconstructor argument when necessary, rather than defining a new class
Prefix mocked class names withmock, notfake
Prefer pytest fixtures over helper methods in Python tests
Preferpytest.mark.parametrizeover 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 withuv run ruff format python
Run Python testing withuv 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
Runtyfor 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 withuv run pre-commit run --all-filesto enforce Ruff linting and formatting, and ty type checking
Files:
python/tests/test_observability_plugin.pypython/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. Usejust docsfor docs-site builds andjust docs-linkcheckwhen links changed
Run docs site build withjust 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-linkcheckwhen 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 docsor./scripts/build-docs.sh htmlto 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.rswith Python wrapper docstring inpython/nemo_relay/<module>.pyand type stubs inpython/nemo_relay/*.pyimodules
Files:
python/nemo_relay/observability.pypython/nemo_relay/observability.pyi
python/nemo_relay/**/*.py
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Use
snake_casenaming convention for Python identifiers (e.g.,nemo_relay.tools.call)Format changed Python wrapper and test files with
uv run ruff format pythonPython wrapper modules live under
python/nemo_relay/; the native extension is built fromcrates/pythonwithmaturin.
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.pypython/nemo_relay/observability.pyi
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Use
snake_casenaming convention for Rust identifiers (e.g.,nemo_relay_tool_call)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node work
**/*.rs: Runcargo fmt --allto format all Rust code
Runcargo clippy --workspace --all-targets -- -D warningsto enforce all clippy lints as errors
**/*.rs: Runcargo fmt --allwhen Rust files changed as part of WebAssembly work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files changed as part of WebAssembly work
**/*.rs: If any Rust code changed, always runjust test-rust
If any Rust code changed, also runcargo fmt --all
If any Rust code changed, also runcargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting withcargo fmt --all
Run Rust linting withcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Usecargo fmtfor Rust code formatting
Runcargo clippy -- -D warningsto 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 withuv run pre-commit run --all-filesto enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...
Files:
crates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/core/src/observability/plugin_component.rs
crates/core/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)
If the change touched
crates/coreor shared runtime semantics, also usevalidate-changefor broader validation
crates/core/**/*.rs: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.
Files:
crates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.
UseJson = serde_json::Valuein Rust-facing runtime APIs for JSON payload handling.
Files:
crates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.tomlcrates/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.tscrates/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.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.rscrates/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 winConfirm intentional silent suppression of sink upload errors at teardown.
last_error_result()now only surfacesfatal_errorand ignores per-sink errors stored insink_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_errorsbefore 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!
88bcd4d to
ba984cc
Compare
Signed-off-by: Will Killian <wkillian@nvidia.com>
ba984cc to
7e457d7
Compare
There was a problem hiding this comment.
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
📒 Files selected for processing (11)
crates/core/Cargo.tomlcrates/core/src/observability/plugin_component.rscrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/node/observability.d.tscrates/node/tests/observability_plugin_tests.mjscrates/wasm/wrappers/esm/observability.d.tsdocs/observability-plugin/atif.mdxpython/nemo_relay/observability.pypython/nemo_relay/observability.pyipython/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.tscrates/wasm/wrappers/esm/observability.d.tscrates/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.tscrates/wasm/wrappers/esm/observability.d.tscrates/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.tscrates/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-nodeto 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-nodeInclude SPDX license header in all JavaScript and TypeScript source files using double-slash comment syntax
Files:
crates/node/observability.d.tscrates/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.tscrates/wasm/wrappers/esm/observability.d.tscrates/core/Cargo.tomlpython/nemo_relay/observability.pypython/tests/test_observability_plugin.pycrates/core/tests/unit/observability/plugin_component_tests.rscrates/core/tests/integration/atif_storage_tests.rscrates/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 prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
crates/node/observability.d.tscrates/wasm/wrappers/esm/observability.d.tspython/nemo_relay/observability.pypython/tests/test_observability_plugin.pycrates/core/tests/unit/observability/plugin_component_tests.rscrates/core/tests/integration/atif_storage_tests.rscrates/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, andnemo-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.tscrates/wasm/wrappers/esm/observability.d.tscrates/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:
- Scope stacks decide where work belongs and which scope-local behavior is visible.
- Middleware registries decide what guardrails and intercepts run around managed calls.
- Plugins install reusable runtime behavior from configuration.
- Events record runtime behavior in ATOF form.
- 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.tspython/nemo_relay/observability.pyicrates/wasm/wrappers/esm/observability.d.tscrates/core/Cargo.tomlpython/nemo_relay/observability.pydocs/observability-plugin/atif.mdxcrates/node/tests/observability_plugin_tests.mjspython/tests/test_observability_plugin.pycrates/core/tests/unit/observability/plugin_component_tests.rscrates/core/tests/integration/atif_storage_tests.rscrates/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.rswith Python wrapper docstring inpython/nemo_relay/<module>.pyand type stubs inpython/nemo_relay/*.pyimodules
Files:
python/nemo_relay/observability.pyipython/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.pyipython/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.tomland their actual usage across the codebase
Files:
crates/core/Cargo.tomlcrates/core/tests/unit/observability/plugin_component_tests.rscrates/core/tests/integration/atif_storage_tests.rscrates/core/src/observability/plugin_component.rs
{crates/core,crates/adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
Changes to
crates/coreorcrates/adaptivemust run the full language matrix
Files:
crates/core/Cargo.tomlcrates/core/tests/unit/observability/plugin_component_tests.rscrates/core/tests/integration/atif_storage_tests.rscrates/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.tomlcrates/core/tests/unit/observability/plugin_component_tests.rscrates/core/tests/integration/atif_storage_tests.rscrates/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.tomlpython/nemo_relay/observability.pypython/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 asrelease/<major>.<minor>.
Files:
crates/core/Cargo.toml
crates/{core,adaptive}/**
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If
crates/coreorcrates/adaptivechanged, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly
Files:
crates/core/Cargo.tomlcrates/core/tests/unit/observability/plugin_component_tests.rscrates/core/tests/integration/atif_storage_tests.rscrates/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.tomldocs/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.tomlpython/nemo_relay/observability.pydocs/observability-plugin/atif.mdxpython/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_casenaming convention for Python identifiers (e.g.,nemo_relay.tools.call)Format changed Python wrapper and test files with
uv run ruff format pythonPython wrapper modules live under
python/nemo_relay/; the native extension is built fromcrates/pythonwithmaturin.
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.tomland import paths used throughout the codebase
Files:
python/nemo_relay/observability.pypython/tests/test_observability_plugin.py
**/*.py
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*.py: Run Python formatting withuv run ruff format python
Run Python testing withuv 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
Runtyfor 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 withuv run pre-commit run --all-filesto enforce Ruff linting and formatting, and ty type checking
Files:
python/nemo_relay/observability.pypython/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. Usejust docsfor docs-site builds andjust docs-linkcheckwhen links changed
Run docs site build withjust 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-linkcheckwhen 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 docsor./scripts/build-docs.sh htmlto 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.mjspython/tests/test_observability_plugin.pycrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.pycrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.asyncioto any test in Python test files
Do not add a-> Nonereturn type annotation to test functions
When mocking a class, useunittest.mock.MagicMockorunittest.mock.AsyncMockwith thespecconstructor argument when necessary, rather than defining a new class
Prefix mocked class names withmock, notfake
Prefer pytest fixtures over helper methods in Python tests
Preferpytest.mark.parametrizeover 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_casenaming convention for Rust identifiers (e.g.,nemo_relay_tool_call)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node work
**/*.rs: Runcargo fmt --allto format all Rust code
Runcargo clippy --workspace --all-targets -- -D warningsto enforce all clippy lints as errors
**/*.rs: Runcargo fmt --allwhen Rust files changed as part of WebAssembly work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files changed as part of WebAssembly work
**/*.rs: If any Rust code changed, always runjust test-rust
If any Rust code changed, also runcargo fmt --all
If any Rust code changed, also runcargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting withcargo fmt --all
Run Rust linting withcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Usecargo fmtfor Rust code formatting
Runcargo clippy -- -D warningsto 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 withuv run pre-commit run --all-filesto enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...
Files:
crates/core/tests/unit/observability/plugin_component_tests.rscrates/core/tests/integration/atif_storage_tests.rscrates/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.rscrates/core/tests/integration/atif_storage_tests.rscrates/core/src/observability/plugin_component.rs
crates/core/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)
If the change touched
crates/coreor shared runtime semantics, also usevalidate-changefor broader validation
crates/core/**/*.rs: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.
Files:
crates/core/tests/unit/observability/plugin_component_tests.rscrates/core/tests/integration/atif_storage_tests.rscrates/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.
UseJson = serde_json::Valuein Rust-facing runtime APIs for JSON payload handling.
Files:
crates/core/tests/unit/observability/plugin_component_tests.rscrates/core/tests/integration/atif_storage_tests.rscrates/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.rscrates/core/tests/integration/atif_storage_tests.rscrates/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.tscrates/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.tomlcrates/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.rscrates/core/tests/integration/atif_storage_tests.rscrates/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.rscrates/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 winSerialize the
header_envenv-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., reusecrate::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 winReject unknown fields in
HttpStorageConfig.
HttpStorageConfigcurrently 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 winSerialize
std::envmutations inatif_storage_testsIn
crates/core/tests/integration/atif_storage_tests.rs, anystd::env::set_var/remove_varshould be protected by a process-wide env guard that restores values viaDrop(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”.
mnajafian-nv
left a comment
There was a problem hiding this comment.
LGTM, happy to approve to unblock as inline questions/suggestions are being addressed
There was a problem hiding this comment.
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 winValidate rendered ATIF
filename_templateas an HTTP header value forx-nemo-relay-atif-filename
filename_templateis only checked for the{session_id}placeholder invalidate_atif_values, but for HTTP uploads the renderedfilenameis used directly as the request headerx-nemo-relay-atif-filenameinpost_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 sameHeaderValue::from_strrules) and emit a config diagnostic when it’s invalid; note that configured HTTP header values are already validated viaHeaderValue::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
📒 Files selected for processing (10)
crates/core/Cargo.tomlcrates/core/src/observability/plugin_component.rscrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/node/observability.d.tscrates/node/tests/observability_plugin_tests.mjsdocs/observability-plugin/atif.mdxpython/nemo_relay/observability.pypython/nemo_relay/observability.pyipython/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.rswith Python wrapper docstring inpython/nemo_relay/<module>.pyand type stubs inpython/nemo_relay/*.pyimodules
Files:
python/nemo_relay/observability.pypython/nemo_relay/observability.pyi
python/nemo_relay/**/*.py
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Use
snake_casenaming convention for Python identifiers (e.g.,nemo_relay.tools.call)Format changed Python wrapper and test files with
uv run ruff format pythonPython wrapper modules live under
python/nemo_relay/; the native extension is built fromcrates/pythonwithmaturin.
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.tomland import paths used throughout the codebase
Files:
python/nemo_relay/observability.pypython/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.pycrates/core/Cargo.tomlpython/tests/test_observability_plugin.py
**/*.py
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*.py: Run Python formatting withuv run ruff format python
Run Python testing withuv 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
Runtyfor 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 withuv run pre-commit run --all-filesto enforce Ruff linting and formatting, and ty type checking
Files:
python/nemo_relay/observability.pypython/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.pycrates/core/Cargo.tomlpython/tests/test_observability_plugin.pydocs/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.pycrates/core/Cargo.tomlpython/tests/test_observability_plugin.pycrates/node/observability.d.tscrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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 prefixednemo_relay_, Go usesPascalCasefor public APIs, Node.js usescamelCase.
Files:
python/nemo_relay/observability.pypython/tests/test_observability_plugin.pycrates/node/observability.d.tscrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.pypython/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:
- Scope stacks decide where work belongs and which scope-local behavior is visible.
- Middleware registries decide what guardrails and intercepts run around managed calls.
- Plugins install reusable runtime behavior from configuration.
- Events record runtime behavior in ATOF form.
- 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.pycrates/core/Cargo.tomlpython/tests/test_observability_plugin.pycrates/node/tests/observability_plugin_tests.mjspython/nemo_relay/observability.pyidocs/observability-plugin/atif.mdxcrates/node/observability.d.tscrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.tomland their actual usage across the codebase
Files:
crates/core/Cargo.tomlcrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/core/src/observability/plugin_component.rs
{crates/core,crates/adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
Changes to
crates/coreorcrates/adaptivemust run the full language matrix
Files:
crates/core/Cargo.tomlcrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.tomlcrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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 asrelease/<major>.<minor>.
Files:
crates/core/Cargo.toml
crates/{core,adaptive}/**
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If
crates/coreorcrates/adaptivechanged, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly
Files:
crates/core/Cargo.tomlcrates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.tomldocs/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.pycrates/core/tests/integration/atif_storage_tests.rscrates/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.asyncioto any test in Python test files
Do not add a-> Nonereturn type annotation to test functions
When mocking a class, useunittest.mock.MagicMockorunittest.mock.AsyncMockwith thespecconstructor argument when necessary, rather than defining a new class
Prefix mocked class names withmock, notfake
Prefer pytest fixtures over helper methods in Python tests
Preferpytest.mark.parametrizeover 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.pycrates/node/tests/observability_plugin_tests.mjscrates/core/tests/integration/atif_storage_tests.rscrates/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.mjscrates/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.mjscrates/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.mjscrates/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. Usejust docsfor docs-site builds andjust docs-linkcheckwhen links changed
Run docs site build withjust 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-linkcheckwhen 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 docsor./scripts/build-docs.sh htmlto 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-nodeto 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-nodeInclude 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, andnemo-relay-node/adaptive.
Files:
crates/node/observability.d.ts
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Use
snake_casenaming convention for Rust identifiers (e.g.,nemo_relay_tool_call)
**/*.rs: Any Rust change must runjust test-rust
Any Rust change must runcargo fmt --all
Any Rust change must runcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allfor all FFI work since it is Rust work
Runjust test-rustto validate FFI changes
Runcargo clippy --workspace --all-targets -- -D warningsto enforce strict linting on FFI workWhen Rust files changed as part of Go work, also run
cargo fmt --all,just test-rust, andcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Runcargo fmt --allwhen Rust files are changed as part of Node work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files are changed as part of Node work
Runjust test-rustwhen Rust files are changed as part of Node work
**/*.rs: Runcargo fmt --allto format all Rust code
Runcargo clippy --workspace --all-targets -- -D warningsto enforce all clippy lints as errors
**/*.rs: Runcargo fmt --allwhen Rust files changed as part of WebAssembly work
Runcargo clippy --workspace --all-targets -- -D warningswhen Rust files changed as part of WebAssembly work
**/*.rs: If any Rust code changed, always runjust test-rust
If any Rust code changed, also runcargo fmt --all
If any Rust code changed, also runcargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting withcargo fmt --all
Run Rust linting withcargo clippy --workspace --all-targets -- -D warnings
**/*.rs: Usecargo fmtfor Rust code formatting
Runcargo clippy -- -D warningsto 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 withuv run pre-commit run --all-filesto enforce cargo fmt formatting check, cargo clippy lints, and cargo deny aud...
Files:
crates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/core/src/observability/plugin_component.rs
crates/core/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/test-go-binding/SKILL.md)
If the change touched
crates/coreor shared runtime semantics, also usevalidate-changefor broader validation
crates/core/**/*.rs: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths. Keep errors explicit and binding-appropriate at the wrapper layer.
Files:
crates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.
UseJson = serde_json::Valuein Rust-facing runtime APIs for JSON payload handling.
Files:
crates/core/tests/integration/atif_storage_tests.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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.rscrates/core/tests/unit/observability/plugin_component_tests.rscrates/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 winReject user-supplied ATIF reserved HTTP headers to prevent duplicate values
validate_atif_http_header_nameshould reject reserved ATIF header names (not just header-name syntax) sopost_atif_httpcan’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()beforejoin()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.
|
/merge |
Overview
Add HTTP endpoint storage as a first-class ATIF remote export backend, alongside existing S3-compatible storage.
Details
type = "http"ATIF storage configuration withendpoint,headers,header_env, andtimeout_millis.Validation:
cargo test -p nemo-relay atif_storageuv run pytest python/tests/test_observability_plugin.pycd crates/node && node --test tests/observability_plugin_tests.mjsjust test-pythonjust test-nodejust test-rustwas 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.rsfor the new HTTP storage config, validation, and upload path. The local HTTP integration coverage is incrates/core/tests/integration/atif_storage_tests.rs.Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)
Summary by CodeRabbit
New Features
Documentation