fix: map FlowError to OpenTelemetry error types - #612
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThe change adds structured OpenTelemetry error metadata across Rust, Node.js, and Python paths. Lifecycle, stream, callback, scope, and LangChain failures now emit stable ChangesStructured OTel Error Metadata
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Execution
participant ErrorClassifier
participant MetadataHelper
participant EndEvent
Execution->>ErrorClassifier: report failure
ErrorClassifier->>MetadataHelper: provide error type
MetadataHelper->>EndEvent: attach ERROR status, description, and error.type
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
ac05dbf to
db734e7
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 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/api/shared.rs`:
- Around line 209-218: Extend the shared metadata/error handling around
metadata_with_otel_error with a fallback helper that produces ERROR metadata
with error.type set to _OTHER when no concrete FlowError exists. Update
LlmStreamWrapper::finish and ManagedToolCompletion::drop cancellation/drop paths
to use this fallback, while preserving metadata_with_otel_error for paths with
an actual error and ensuring all such paths retain _OTHER.
In `@python/nemo_relay/scope.py`:
- Around line 256-264: Restrict the message-derived override in the error-type
extraction logic to a bounded, stable Relay/Python error taxonomy, or remove the
override and retain type(e).__name__ as the default. Update the loop around
status_message parsing so dynamic identifiers such as tenant_123Error cannot
replace error_type, and add a regression case covering that token.
In `@python/tests/test_scope.py`:
- Around line 110-123: Update test_scope_ctx_mgr_records_exception_type by
annotating the nested capture_pop callback with -> None to satisfy ANN202, and
combine the pytest.raises and scope.scope context managers into one with
statement, keeping pytest.raises first to satisfy SIM117.
🪄 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: e3a73248-cf40-4370-b065-6be39c0c42b7
📒 Files selected for processing (11)
crates/core/src/api/llm.rscrates/core/src/api/shared.rscrates/core/src/api/tool.rscrates/core/src/error.rscrates/core/src/stream.rscrates/core/tests/coverage/error_tests.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/shared_tests.rscrates/core/tests/unit/tool_api_tests.rspython/nemo_relay/scope.pypython/tests/test_scope.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (24)
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
**/*.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 workWhen changing the core Rust runtime or Rust-facing API surface, format Rust code with
cargo fmt(rustfmt defaults), keepcargo clippy -- -D warningsclean, and satisfycargo deny checkperdeny.toml.
**/*.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.
For Rust changes headed for review, runcargo fmt --allandcargo clippy --workspace --all-targets -- -D warningseven if relying on pre-commit.
Files:
crates/core/tests/unit/shared_tests.rscrates/core/tests/coverage/error_tests.rscrates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/stream.rscrates/core/src/api/shared.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/tests/unit/shared_tests.rscrates/core/tests/coverage/error_tests.rscrates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/stream.rscrates/core/src/api/shared.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
Files:
crates/core/tests/unit/shared_tests.rscrates/core/tests/coverage/error_tests.rscrates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/stream.rscrates/core/src/api/shared.rs
**/*.{rs,py}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions in Rust and Python: use
snake_case.
Files:
crates/core/tests/unit/shared_tests.rscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/stream.rscrates/core/src/api/shared.rspython/nemo_relay/scope.py
**/*.{rs,py,js,mjs,cjs,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{rs,py,js,mjs,cjs,ts,tsx}: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Files:
crates/core/tests/unit/shared_tests.rscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/stream.rscrates/core/src/api/shared.rspython/nemo_relay/scope.py
**/*.{rs,py,go,js,ts,c,h}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use language-appropriate naming conventions: Rust
snake_case, C FFI exports prefixednemo_relay_, GoPascalCase, Node.jscamelCase, and Pythonsnake_case.
Files:
crates/core/tests/unit/shared_tests.rscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/stream.rscrates/core/src/api/shared.rspython/nemo_relay/scope.py
**/*.{rs,go,js,ts}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding
//comment form.
Files:
crates/core/tests/unit/shared_tests.rscrates/core/tests/coverage/error_tests.rscrates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/stream.rscrates/core/src/api/shared.rs
**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, usemaintain-dynamic-pluginsand include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, preferuv run pre-commit run --files <changed files...>.
Before review or handoff, runuv run pre-commit run --all-files.
Files:
crates/core/tests/unit/shared_tests.rscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/stream.rscrates/core/src/api/shared.rspython/nemo_relay/scope.py
crates/{core,adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If
crates/coreorcrates/adaptivechanged, run the full validation matrix across Rust, Python, Go, and Node.js.
Files:
crates/core/tests/unit/shared_tests.rscrates/core/tests/coverage/error_tests.rscrates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/stream.rscrates/core/src/api/shared.rs
**/*.{rs,py,go,js,ts}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If a language surface changed, always run that language's test target even when Rust core did not change.
**/*.{rs,py,go,js,ts}: When observability configuration or lifecycle is exposed, keep FFI and Python, Go, and Node.js binding-native config objects and subscriber/exporter methods aligned in logical knobs and semantics.
Require every OpenTelemetry endpoint to have a type and nonblank destination; resolveheader_envvalues at activation and reject missing, blank, or duplicate headers.
Concatenate layered ATOF sink, ATIF storage, and OpenTelemetry endpoint lists with higher-precedence entries first.
Preserve correct handling of mark events, start/end events, orphan cases, and span or trajectory fields derived from intended event data.
Run affected Rust tests andjust test-rustwhen event fields change; runjust test-python,just test-go, andjust test-nodewhen binding-native configuration or lifecycle changes.
Files:
crates/core/tests/unit/shared_tests.rscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/stream.rscrates/core/src/api/shared.rspython/nemo_relay/scope.py
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.
Files:
crates/core/tests/unit/shared_tests.rscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/stream.rscrates/core/src/api/shared.rspython/nemo_relay/scope.py
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/shared_tests.rscrates/core/tests/coverage/error_tests.rscrates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/stream.rscrates/core/src/api/shared.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}
⚙️ CodeRabbit configuration file
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.
Files:
crates/core/tests/unit/shared_tests.rscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/tool_api_tests.rs
**/*.py
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.py: When changing the Python wrapper package, tests, or docs tooling, lint with Ruff (E,F,W,I), format with Ruff formatter (120-character lines, double quotes), and passtytype checking.
Add the SPDX license header to all Python source files using the#comment form.
Files:
python/tests/test_scope.pypython/nemo_relay/scope.py
{crates/**/src/**/*.rs,python/**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Do not add tests under
src; Rust tests belong in cratetests/trees, and Python SDK tests belong underpython/tests.
Files:
python/tests/test_scope.pycrates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/src/stream.rscrates/core/src/api/shared.rspython/nemo_relay/scope.py
python/tests/**/*.py
📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)
python/tests/**/*.py: Pytest is used to run tests.
Do not add@pytest.mark.asyncioto any test; async tests are automatically detected and run by the async runner.
Do not add a-> Nonereturn type annotation to test functions.
When mocking a class, do not define a new class; useunittest.mock.MagicMockorunittest.mock.AsyncMock, with thespecconstructor argument when necessary.
Name mocked classes with themockprefix, notfake.
Prefer pytest fixtures over helper methods.
Do not repeat fixtures; if a fixture is needed in multiple test files, place it in aconftest.pyfile.
When creating a fixture, use@pytest.fixture(name="<fixture_name>"[, scope="<scope>"])and define the fixture function asdef <fixture_name>_fixture() -> <return_type>:; only specifyscopewhen it is notfunction.
Preferpytest.mark.parametrizeover creating individual tests for different input types.
Files:
python/tests/test_scope.py
**/*.{md,mdx,py,go,js,ts}
📄 CodeRabbit inference engine (.agents/skills/maintain-observability/SKILL.md)
Examples and documentation must use each exporter's documented flush/deregister order before shutdown.
Files:
python/tests/test_scope.pypython/nemo_relay/scope.py
crates/core/src/{api/**/*.rs,api/runtime/**/*.rs,codec/**/*.rs,json.rs}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Implement the new or changed public runtime behavior first in the Rust core, especially under
crates/core/src/api/and related core modules such ascrates/core/src/api/runtime/,crates/core/src/codec/, andcrates/core/src/json.rs.
Files:
crates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/src/api/shared.rs
crates/core/src/api/{tool,llm,shared,scope}.rs
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Wire the new middleware chain into the appropriate lifecycle owner and pipeline stage: tool and LLM execution paths use
tool.rsorllm.rs; shared mark and scope event sanitization usesshared.rsand is called fromscope.rs.
Files:
crates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/src/api/shared.rs
crates/core/src/api/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Preserve the documented pipeline order: conditional guardrails, request intercepts, request sanitization, execution intercepts, and response sanitization for tool and LLM execution; specialized sanitization, event creation, and dispatch for mark and scope events.
Files:
crates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/src/api/shared.rs
python/nemo_relay/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Python wrapper modules live under
python/nemo_relay/, and the native extension is built fromcrates/pythonwithmaturin.
Files:
python/nemo_relay/scope.py
{crates/python/src/py_api/mod.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go,crates/node/src/api/**/*.rs}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Update the language-native bindings for every exposed surface in Python, Go, and Node.js.
Files:
python/nemo_relay/scope.py
{python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Update language wrapper helpers such as Python wrapper modules, Python type stubs, and Go shorthand packages when the new behavior belongs in those helper layers.
Files:
python/nemo_relay/scope.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/scope.py
🧠 Learnings (1)
📚 Learning: 2026-07-28T20:07:29.880Z
Learnt from: willkill07
Repo: NVIDIA/NeMo-Relay PR: 571
File: crates/core/src/api/runtime/state.rs:996-1020
Timestamp: 2026-07-28T20:07:29.880Z
Learning: In NeMo Relay (RELAY-509), sanitizer callback failures must be treated as intentional fail-open behavior. When an event/tool (request/response) or LLM (request/response) sanitizer callback fails, the sanitizer chain should retain and publish the last valid event/payload snapshot (rather than dropping/invalidating the data) and log the failure including callback context (e.g., which sanitizer/callback failed and relevant identifiers). Apply this consistently across all sanitizer chains mentioned in the RELAY-509 documentation/migration guide.
Applied to files:
crates/core/src/error.rscrates/core/src/api/tool.rscrates/core/src/api/llm.rscrates/core/src/stream.rscrates/core/src/api/shared.rs
🪛 Ruff (0.16.0)
python/tests/test_scope.py
[warning] 114-114: Missing return type annotation for private function capture_pop
Add return type annotation: None
(ANN202)
[warning] 121-122: Use a single with statement with multiple contexts instead of nested with statements
(SIM117)
🔇 Additional comments (10)
crates/core/src/error.rs (1)
137-172: LGTM!crates/core/tests/coverage/error_tests.rs (1)
57-76: LGTM!crates/core/tests/unit/shared_tests.rs (1)
123-137: LGTM!crates/core/src/api/llm.rs (1)
37-39: LGTM!Also applies to: 1520-1520, 1726-1726
crates/core/src/api/tool.rs (1)
20-20: LGTM!Also applies to: 809-809
crates/core/src/stream.rs (1)
47-49: LGTM!Also applies to: 217-225, 456-464
crates/core/tests/unit/llm_api_tests.rs (1)
1691-1693: LGTM!Also applies to: 1723-1723, 1821-1821, 1849-1851, 1883-1886, 1900-1900
crates/core/tests/unit/tool_api_tests.rs (1)
72-76: LGTM!Also applies to: 106-109
python/nemo_relay/scope.py (1)
239-239: LGTM!Also applies to: 271-272
python/tests/test_scope.py (1)
103-109: LGTM!Also applies to: 125-130
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/src/api/shared.rs`:
- Line 177: Before handoff, validate the change around metadata_with_otel_status
with just test-rust, cargo fmt --all, cargo clippy --workspace --all-targets --
-D warnings, validate-change, just test-go, cargo deny check, the required
Rust/Python/Go/Node language checks, and uv run pre-commit run --all-files;
record the exact blocker for any command that cannot run.
🪄 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: 0b9c3d3b-4198-40f2-98dd-620268ea3a00
📒 Files selected for processing (5)
crates/core/src/api/llm.rscrates/core/src/api/shared.rscrates/core/src/api/tool.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: Check / Run
- GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (17)
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
**/*.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 workWhen changing the core Rust runtime or Rust-facing API surface, format Rust code with
cargo fmt(rustfmt defaults), keepcargo clippy -- -D warningsclean, and satisfycargo deny checkperdeny.toml.
**/*.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.
For Rust changes headed for review, runcargo fmt --allandcargo clippy --workspace --all-targets -- -D warningseven if relying on pre-commit.
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.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/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.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
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rs
**/*.{rs,py}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions in Rust and Python: use
snake_case.
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rs
**/*.{rs,py,js,mjs,cjs,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{rs,py,js,mjs,cjs,ts,tsx}: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rs
**/*.{rs,py,go,js,ts,c,h}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use language-appropriate naming conventions: Rust
snake_case, C FFI exports prefixednemo_relay_, GoPascalCase, Node.jscamelCase, and Pythonsnake_case.
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rs
**/*.{rs,go,js,ts}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding
//comment form.
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rs
crates/core/src/{api/**/*.rs,api/runtime/**/*.rs,codec/**/*.rs,json.rs}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Implement the new or changed public runtime behavior first in the Rust core, especially under
crates/core/src/api/and related core modules such ascrates/core/src/api/runtime/,crates/core/src/codec/, andcrates/core/src/json.rs.
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/api/llm.rs
{crates/**/src/**/*.rs,python/**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Do not add tests under
src; Rust tests belong in cratetests/trees, and Python SDK tests belong underpython/tests.
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/src/api/llm.rs
**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, usemaintain-dynamic-pluginsand include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, preferuv run pre-commit run --files <changed files...>.
Before review or handoff, runuv run pre-commit run --all-files.
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rs
crates/{core,adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If
crates/coreorcrates/adaptivechanged, run the full validation matrix across Rust, Python, Go, and Node.js.
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rs
**/*.{rs,py,go,js,ts}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If a language surface changed, always run that language's test target even when Rust core did not change.
**/*.{rs,py,go,js,ts}: When observability configuration or lifecycle is exposed, keep FFI and Python, Go, and Node.js binding-native config objects and subscriber/exporter methods aligned in logical knobs and semantics.
Require every OpenTelemetry endpoint to have a type and nonblank destination; resolveheader_envvalues at activation and reject missing, blank, or duplicate headers.
Concatenate layered ATOF sink, ATIF storage, and OpenTelemetry endpoint lists with higher-precedence entries first.
Preserve correct handling of mark events, start/end events, orphan cases, and span or trajectory fields derived from intended event data.
Run affected Rust tests andjust test-rustwhen event fields change; runjust test-python,just test-go, andjust test-nodewhen binding-native configuration or lifecycle changes.
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rs
crates/core/src/api/{tool,llm,shared,scope}.rs
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Wire the new middleware chain into the appropriate lifecycle owner and pipeline stage: tool and LLM execution paths use
tool.rsorllm.rs; shared mark and scope event sanitization usesshared.rsand is called fromscope.rs.
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/api/llm.rs
crates/core/src/api/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Preserve the documented pipeline order: conditional guardrails, request intercepts, request sanitization, execution intercepts, and response sanitization for tool and LLM execution; specialized sanitization, event creation, and dispatch for mark and scope events.
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/api/llm.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.
Files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.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/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}
⚙️ CodeRabbit configuration file
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.
Files:
crates/core/tests/unit/shared_tests.rs
🧠 Learnings (1)
📚 Learning: 2026-07-28T20:07:29.880Z
Learnt from: willkill07
Repo: NVIDIA/NeMo-Relay PR: 571
File: crates/core/src/api/runtime/state.rs:996-1020
Timestamp: 2026-07-28T20:07:29.880Z
Learning: In NeMo Relay (RELAY-509), sanitizer callback failures must be treated as intentional fail-open behavior. When an event/tool (request/response) or LLM (request/response) sanitizer callback fails, the sanitizer chain should retain and publish the last valid event/payload snapshot (rather than dropping/invalidating the data) and log the failure including callback context (e.g., which sanitizer/callback failed and relevant identifiers). Apply this consistently across all sanitizer chains mentioned in the RELAY-509 documentation/migration guide.
Applied to files:
crates/core/src/api/tool.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/src/api/llm.rs
🔇 Additional comments (6)
crates/core/src/api/shared.rs (1)
209-222: LGTM!Also applies to: 224-238
crates/core/tests/unit/shared_tests.rs (1)
93-103: LGTM!Also applies to: 105-119, 121-136
crates/core/src/api/llm.rs (2)
37-39: LGTM!Also applies to: 1011-1011, 1247-1249, 1520-1520, 1726-1726
1080-1080: 🎯 Functional CorrectnessNo issue found. All production callers set
response_codec_errors_fataltofalse, so the fatal codec-error path is unreachable.> Likely an incorrect or invalid review comment.crates/core/src/api/tool.rs (1)
20-22: LGTM!Also applies to: 633-635, 793-793, 809-809
crates/core/src/stream.rs (1)
47-50: LGTM!Also applies to: 188-190, 201-218, 450-462
14a153c to
f5932f0
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
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/api/llm.rs`:
- Around line 1247-1249: Update the managed lifecycle tests
dropping_pending_llm_execution_closes_the_managed_lifecycle in
crates/core/src/api/llm.rs:1247-1249 and
dropping_pending_tool_execution_closes_the_managed_lifecycle in
crates/core/src/api/tool.rs:633-635 to assert that each cancellation End event
includes otel.status_code set to "ERROR" and error.type set to "_OTHER", while
preserving the existing Start and End event assertions.
In `@crates/core/src/api/shared.rs`:
- Around line 225-230: The metadata_with_otel_error_type helper must preserve a
caller-provided error.type: insert the derived error_type only when that key is
absent, while retaining the existing fallback behavior otherwise. In
crates/core/tests/unit/shared_tests.rs lines 123-154, extend the helper tests
with metadata containing an explicit error.type and assert that the explicit
value remains unchanged.
🪄 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: 618bdad1-863f-4bf0-83b8-b45821d5ee89
📒 Files selected for processing (21)
crates/core/src/api/llm.rscrates/core/src/api/shared.rscrates/core/src/api/tool.rscrates/core/src/error.rscrates/core/src/stream.rscrates/core/tests/coverage/error_tests.rscrates/core/tests/integration/stream_tests.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/unit/observability/otel_tests.rscrates/core/tests/unit/shared_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/node/src/api/mod.rscrates/node/src/callback_factory.rscrates/node/src/promise_call.rscrates/node/tests/llm_tests.mjscrates/node/tests/scope_tests.mjscrates/node/tests/tools_tests.mjspython/nemo_relay/integrations/langchain/callbacks.pypython/nemo_relay/scope.pypython/tests/integrations/langchain_tests/test_callbacks.pypython/tests/test_scope.py
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
- GitHub Check: Check / Run
- GitHub Check: Preview docs
🧰 Additional context used
📓 Path-based instructions (26)
crates/node/**/*.{js,mjs,cjs,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use
camelCasefor Node.js public APIs.
Files:
crates/node/tests/llm_tests.mjscrates/node/tests/tools_tests.mjscrates/node/tests/scope_tests.mjs
**/*.{rs,py,js,mjs,cjs,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{rs,py,js,mjs,cjs,ts,tsx}: UseJson = serde_json::Valuein Rust-facing runtime APIs where the existing code expects JSON payloads.
UseResult<T>withFlowErrorin core runtime paths, and keep errors explicit and binding-appropriate at the wrapper layer.
Keep async behavior on the existing tokio-based model; bindings should preserve callback and future lifetimes rather than blocking or hiding async work unexpectedly.
Files:
crates/node/tests/llm_tests.mjspython/tests/integrations/langchain_tests/test_callbacks.pycrates/node/tests/tools_tests.mjspython/nemo_relay/integrations/langchain/callbacks.pycrates/core/tests/unit/observability/otel_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/error.rscrates/node/tests/scope_tests.mjscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/src/api/shared.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/integration/stream_tests.rscrates/node/src/callback_factory.rscrates/node/src/api/mod.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rspython/nemo_relay/scope.pycrates/node/src/promise_call.rs
**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
**/*: Format changed files with the language-native formatter before the final lint/test pass.
If dynamic plugin behavior changed, usemaintain-dynamic-pluginsand include the native SDK, worker protocol, Python SDK, docs, packaging, and Codecov surfaces in the validation plan.
If code changes alter APIs, bindings, commands, paths, packaging behavior, observability/adaptive semantics, or documented best practices, update any dependent maintainer or consumer skills in the same branch.
During iteration, preferuv run pre-commit run --files <changed files...>.
Before review or handoff, runuv run pre-commit run --all-files.
Files:
crates/node/tests/llm_tests.mjspython/tests/integrations/langchain_tests/test_callbacks.pycrates/node/tests/tools_tests.mjspython/nemo_relay/integrations/langchain/callbacks.pycrates/core/tests/unit/observability/otel_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/error.rscrates/node/tests/scope_tests.mjscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/src/api/shared.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/integration/stream_tests.rscrates/node/src/callback_factory.rscrates/node/src/api/mod.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rspython/nemo_relay/scope.pycrates/node/src/promise_call.rs
crates/{python,ffi,node}/**/*
⚙️ CodeRabbit configuration file
crates/{python,ffi,node}/**/*: Treat binding changes as public API changes. Check for parity with the other language bindings, FFI ownership/lifetime safety,
callback error propagation, stable type conversion, and consistent async/stream semantics.
Flag changes that update one binding without corresponding tests or documentation for the same surface elsewhere.
Files:
crates/node/tests/llm_tests.mjscrates/node/tests/tools_tests.mjscrates/node/tests/scope_tests.mjscrates/node/src/callback_factory.rscrates/node/src/api/mod.rscrates/node/src/promise_call.rs
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}
⚙️ CodeRabbit configuration file
{crates/**/tests/**,python/tests/**,go/nemo_relay/**/*_test.go}: Tests should cover the behavior promised by the changed API surface, including error paths and cross-request isolation where relevant.
Prefer assertions on lifecycle events, scope stacks, middleware ordering, and binding parity over shallow smoke tests.
Files:
crates/node/tests/llm_tests.mjspython/tests/integrations/langchain_tests/test_callbacks.pycrates/node/tests/tools_tests.mjscrates/core/tests/unit/observability/otel_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/node/tests/scope_tests.mjscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/tests/unit/llm_api_tests.rscrates/core/tests/integration/stream_tests.rscrates/core/tests/unit/shared_tests.rs
**/*.{rs,py}
📄 CodeRabbit inference engine (AGENTS.md)
Follow binding naming conventions in Rust and Python: use
snake_case.
Files:
python/tests/integrations/langchain_tests/test_callbacks.pypython/nemo_relay/integrations/langchain/callbacks.pycrates/core/tests/unit/observability/otel_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/error.rscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/src/api/shared.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/integration/stream_tests.rscrates/node/src/callback_factory.rscrates/node/src/api/mod.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rspython/nemo_relay/scope.pycrates/node/src/promise_call.rs
**/*.py
📄 CodeRabbit inference engine (CONTRIBUTING.md)
**/*.py: When changing the Python wrapper package, tests, or docs tooling, lint with Ruff (E,F,W,I), format with Ruff formatter (120-character lines, double quotes), and passtytype checking.
Add the SPDX license header to all Python source files using the#comment form.
Files:
python/tests/integrations/langchain_tests/test_callbacks.pypython/nemo_relay/integrations/langchain/callbacks.pypython/tests/test_scope.pypython/nemo_relay/scope.py
**/*.{rs,py,go,js,ts,c,h}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Use language-appropriate naming conventions: Rust
snake_case, C FFI exports prefixednemo_relay_, GoPascalCase, Node.jscamelCase, and Pythonsnake_case.
Files:
python/tests/integrations/langchain_tests/test_callbacks.pypython/nemo_relay/integrations/langchain/callbacks.pycrates/core/tests/unit/observability/otel_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/error.rscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/src/api/shared.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/integration/stream_tests.rscrates/node/src/callback_factory.rscrates/node/src/api/mod.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rspython/nemo_relay/scope.pycrates/node/src/promise_call.rs
{crates/**/src/**/*.rs,python/**/*.py}
📄 CodeRabbit inference engine (.agents/skills/maintain-dynamic-plugins/SKILL.md)
Do not add tests under
src; Rust tests belong in cratetests/trees, and Python SDK tests belong underpython/tests.
Files:
python/tests/integrations/langchain_tests/test_callbacks.pypython/nemo_relay/integrations/langchain/callbacks.pycrates/core/src/error.rspython/tests/test_scope.pycrates/core/src/api/shared.rscrates/node/src/callback_factory.rscrates/node/src/api/mod.rscrates/core/src/stream.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rspython/nemo_relay/scope.pycrates/node/src/promise_call.rs
python/tests/**/*.py
📄 CodeRabbit inference engine (.agents/skills/test-python-binding/SKILL.md)
python/tests/**/*.py: Pytest is used to run tests.
Do not add@pytest.mark.asyncioto any test; async tests are automatically detected and run by the async runner.
Do not add a-> Nonereturn type annotation to test functions.
When mocking a class, do not define a new class; useunittest.mock.MagicMockorunittest.mock.AsyncMock, with thespecconstructor argument when necessary.
Name mocked classes with themockprefix, notfake.
Prefer pytest fixtures over helper methods.
Do not repeat fixtures; if a fixture is needed in multiple test files, place it in aconftest.pyfile.
When creating a fixture, use@pytest.fixture(name="<fixture_name>"[, scope="<scope>"])and define the fixture function asdef <fixture_name>_fixture() -> <return_type>:; only specifyscopewhen it is notfunction.
Preferpytest.mark.parametrizeover creating individual tests for different input types.
Files:
python/tests/integrations/langchain_tests/test_callbacks.pypython/tests/test_scope.py
**/*.{rs,py,go,js,ts}
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If a language surface changed, always run that language's test target even when Rust core did not change.
**/*.{rs,py,go,js,ts}: When observability configuration or lifecycle is exposed, keep FFI and Python, Go, and Node.js binding-native config objects and subscriber/exporter methods aligned in logical knobs and semantics.
Require every OpenTelemetry endpoint to have a type and nonblank destination; resolveheader_envvalues at activation and reject missing, blank, or duplicate headers.
Concatenate layered ATOF sink, ATIF storage, and OpenTelemetry endpoint lists with higher-precedence entries first.
Preserve correct handling of mark events, start/end events, orphan cases, and span or trajectory fields derived from intended event data.
Run affected Rust tests andjust test-rustwhen event fields change; runjust test-python,just test-go, andjust test-nodewhen binding-native configuration or lifecycle changes.
Files:
python/tests/integrations/langchain_tests/test_callbacks.pypython/nemo_relay/integrations/langchain/callbacks.pycrates/core/tests/unit/observability/otel_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/error.rscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/src/api/shared.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/integration/stream_tests.rscrates/node/src/callback_factory.rscrates/node/src/api/mod.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rspython/nemo_relay/scope.pycrates/node/src/promise_call.rs
**/*.{rs,py,js,ts,tsx,go,java,kt,swift}
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Add tests covering registration and duplicate names, deregistration and missing names, priority ordering, callback failure policy, scope-local inheritance and cleanup, event payload semantics, immutable mark and scope fields, and parity across affected bindings.
Files:
python/tests/integrations/langchain_tests/test_callbacks.pypython/nemo_relay/integrations/langchain/callbacks.pycrates/core/tests/unit/observability/otel_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/error.rscrates/core/tests/coverage/error_tests.rspython/tests/test_scope.pycrates/core/src/api/shared.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/integration/stream_tests.rscrates/node/src/callback_factory.rscrates/node/src/api/mod.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rspython/nemo_relay/scope.pycrates/node/src/promise_call.rs
**/*.{md,mdx,py,go,js,ts}
📄 CodeRabbit inference engine (.agents/skills/maintain-observability/SKILL.md)
Examples and documentation must use each exporter's documented flush/deregister order before shutdown.
Files:
python/tests/integrations/langchain_tests/test_callbacks.pypython/nemo_relay/integrations/langchain/callbacks.pypython/tests/test_scope.pypython/nemo_relay/scope.py
python/nemo_relay/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Python wrapper modules live under
python/nemo_relay/, and the native extension is built fromcrates/pythonwithmaturin.
Files:
python/nemo_relay/integrations/langchain/callbacks.pypython/nemo_relay/scope.py
{crates/python/src/py_api/mod.rs,python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go,crates/node/src/api/**/*.rs}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Update the language-native bindings for every exposed surface in Python, Go, and Node.js.
Files:
python/nemo_relay/integrations/langchain/callbacks.pycrates/node/src/api/mod.rspython/nemo_relay/scope.py
{python/nemo_relay/**/*.py,python/nemo_relay/**/*.pyi,go/nemo_relay/**/*.go}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Update language wrapper helpers such as Python wrapper modules, Python type stubs, and Go shorthand packages when the new behavior belongs in those helper layers.
Files:
python/nemo_relay/integrations/langchain/callbacks.pypython/nemo_relay/scope.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/integrations/langchain/callbacks.pypython/nemo_relay/scope.py
**/*.rs
📄 CodeRabbit inference engine (.agents/skills/prepare-pr/SKILL.md)
**/*.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 workWhen changing the core Rust runtime or Rust-facing API surface, format Rust code with
cargo fmt(rustfmt defaults), keepcargo clippy -- -D warningsclean, and satisfycargo deny checkperdeny.toml.
**/*.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.
For Rust changes headed for review, runcargo fmt --allandcargo clippy --workspace --all-targets -- -D warningseven if relying on pre-commit.
Files:
crates/core/tests/unit/observability/otel_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/error.rscrates/core/tests/coverage/error_tests.rscrates/core/src/api/shared.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/integration/stream_tests.rscrates/node/src/callback_factory.rscrates/node/src/api/mod.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rscrates/node/src/promise_call.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/tests/unit/observability/otel_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/error.rscrates/core/tests/coverage/error_tests.rscrates/core/src/api/shared.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/integration/stream_tests.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rscrates/core/src/api/tool.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
Files:
crates/core/tests/unit/observability/otel_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/error.rscrates/core/tests/coverage/error_tests.rscrates/core/src/api/shared.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/integration/stream_tests.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rs
**/*.{rs,go,js,ts}
📄 CodeRabbit inference engine (CONTRIBUTING.md)
Add the SPDX license header to all Rust, Go, JavaScript, and TypeScript source files using the corresponding
//comment form.
Files:
crates/core/tests/unit/observability/otel_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/error.rscrates/core/tests/coverage/error_tests.rscrates/core/src/api/shared.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/integration/stream_tests.rscrates/node/src/callback_factory.rscrates/node/src/api/mod.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rscrates/node/src/promise_call.rs
crates/{core,adaptive}/**/*
📄 CodeRabbit inference engine (.agents/skills/validate-change/SKILL.md)
If
crates/coreorcrates/adaptivechanged, run the full validation matrix across Rust, Python, Go, and Node.js.
Files:
crates/core/tests/unit/observability/otel_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/error.rscrates/core/tests/coverage/error_tests.rscrates/core/src/api/shared.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/integration/stream_tests.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rscrates/core/src/api/tool.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/otel_tests.rscrates/core/tests/unit/tool_api_tests.rscrates/core/src/error.rscrates/core/tests/coverage/error_tests.rscrates/core/src/api/shared.rscrates/core/tests/unit/llm_api_tests.rscrates/core/tests/integration/stream_tests.rscrates/core/src/stream.rscrates/core/tests/unit/shared_tests.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rs
crates/core/src/{api/**/*.rs,api/runtime/**/*.rs,codec/**/*.rs,json.rs}
📄 CodeRabbit inference engine (.agents/skills/add-binding-feature/SKILL.md)
Implement the new or changed public runtime behavior first in the Rust core, especially under
crates/core/src/api/and related core modules such ascrates/core/src/api/runtime/,crates/core/src/codec/, andcrates/core/src/json.rs.
Files:
crates/core/src/api/shared.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rs
crates/core/src/api/{tool,llm,shared,scope}.rs
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Wire the new middleware chain into the appropriate lifecycle owner and pipeline stage: tool and LLM execution paths use
tool.rsorllm.rs; shared mark and scope event sanitization usesshared.rsand is called fromscope.rs.
Files:
crates/core/src/api/shared.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rs
crates/core/src/api/**/*.rs
📄 CodeRabbit inference engine (.agents/skills/add-middleware/SKILL.md)
Preserve the documented pipeline order: conditional guardrails, request intercepts, request sanitization, execution intercepts, and response sanitization for tool and LLM execution; specialized sanitization, event creation, and dispatch for mark and scope events.
Files:
crates/core/src/api/shared.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rs
🧠 Learnings (2)
📚 Learning: 2026-07-28T20:07:29.880Z
Learnt from: willkill07
Repo: NVIDIA/NeMo-Relay PR: 571
File: crates/core/src/api/runtime/state.rs:996-1020
Timestamp: 2026-07-28T20:07:29.880Z
Learning: In NeMo Relay (RELAY-509), sanitizer callback failures must be treated as intentional fail-open behavior. When an event/tool (request/response) or LLM (request/response) sanitizer callback fails, the sanitizer chain should retain and publish the last valid event/payload snapshot (rather than dropping/invalidating the data) and log the failure including callback context (e.g., which sanitizer/callback failed and relevant identifiers). Apply this consistently across all sanitizer chains mentioned in the RELAY-509 documentation/migration guide.
Applied to files:
crates/core/src/error.rscrates/core/src/api/shared.rscrates/core/src/stream.rscrates/core/src/api/llm.rscrates/core/src/api/tool.rs
📚 Learning: 2026-07-28T23:57:11.641Z
Learnt from: willkill07
Repo: NVIDIA/NeMo-Relay PR: 570
File: crates/node/src/api/mod.rs:3265-3282
Timestamp: 2026-07-28T23:57:11.641Z
Learning: In the Node.js binding, `flushSubscribers()` is Promise-based/async and must be awaited. Any session-close or teardown path (e.g., the OpenClaw live smoke session-close flow) must await `flushSubscribers()` before continuing to live ATIF export assertions and before teardown, so queued subscriber delivery fully completes and tests/assertions observe the final state.
Applied to files:
crates/node/src/api/mod.rs
🪛 Ruff (0.16.0)
python/tests/test_scope.py
[warning] 189-189: Avoid specifying long messages outside the exception class
(TRY003)
🔇 Additional comments (19)
crates/core/tests/unit/observability/otel_tests.rs (2)
12-14: LGTM!Also applies to: 376-426, 1461-1485
376-426: 📐 Maintainability & Code QualityConfirm the required core validation before handoff.
This change is under
crates/core. Confirmjust test-rust,cargo fmt --all,cargo clippy --workspace --all-targets -- -D warnings,validate-change, the Python, Go, and Node.js test targets, anduv run pre-commit run --all-filescompleted. The PR objectives note a local Go validation limitation; verify the Go check in CI.As per coding guidelines, changes under
crates/corerequire the listed Rust checks and the full language matrix.Source: Coding guidelines
crates/node/src/promise_call.rs (1)
123-155: LGTM!Also applies to: 338-340, 353-357, 474-476
crates/node/tests/llm_tests.mjs (1)
324-324: LGTM!crates/node/tests/scope_tests.mjs (1)
252-266: LGTM!Also applies to: 276-282
crates/node/tests/tools_tests.mjs (1)
418-418: LGTM!crates/node/src/callback_factory.rs (1)
103-149: 📐 Maintainability & Code QualityRun the required binding validation in separate commands.
The combined validation timed out before producing results. Run each command separately, including
cargo deny checkfor the Rust-facing API changes.python/nemo_relay/scope.py (1)
19-19: LGTM!Also applies to: 44-108, 306-335
python/nemo_relay/integrations/langchain/callbacks.py (1)
15-15: LGTM!Also applies to: 99-103
python/tests/test_scope.py (1)
6-15: LGTM!Also applies to: 106-192
python/tests/integrations/langchain_tests/test_callbacks.py (1)
136-140: LGTM!crates/core/src/error.rs (1)
137-229: LGTM!crates/core/tests/coverage/error_tests.rs (1)
57-133: LGTM!crates/core/src/api/llm.rs (1)
37-39: LGTM!Also applies to: 1520-1520, 1726-1726
crates/core/src/api/tool.rs (1)
20-21: LGTM!Also applies to: 809-809
crates/core/src/stream.rs (1)
47-49: LGTM!Also applies to: 188-190, 217-225, 456-464
crates/core/tests/unit/llm_api_tests.rs (1)
1691-1693: LGTM!Also applies to: 1723-1723, 1821-1821, 1849-1851, 1883-1886, 1900-1900
crates/core/tests/unit/tool_api_tests.rs (1)
72-76: LGTM!Also applies to: 106-109
crates/core/tests/integration/stream_tests.rs (1)
466-466: LGTM!
Signed-off-by: Yuchen Zhang <yuchenz@nvidia.com>
Signed-off-by: Yuchen Zhang <yuchenz@nvidia.com>
Signed-off-by: Yuchen Zhang <yuchenz@nvidia.com>
This reverts commit ef92dad. Signed-off-by: Yuchen Zhang <yuchenz@nvidia.com>
Signed-off-by: Yuchen Zhang <yuchenz@nvidia.com>
Signed-off-by: Yuchen Zhang <yuchenz@nvidia.com>
Signed-off-by: Yuchen Zhang <yuchenz@nvidia.com>
Signed-off-by: Yuchen Zhang <yuchenz@nvidia.com>
Signed-off-by: Yuchen Zhang <yuchenz@nvidia.com>
Signed-off-by: Yuchen Zhang <yuchenz@nvidia.com>
47fc055 to
e0c8bec
Compare
Signed-off-by: Yuchen Zhang <yuchenz@nvidia.com>
|
/merge |
Overview
Populate OpenTelemetry
error.typefor failed managed LLM, tool, and stream executions by mapping Relay's structuredFlowErrorvalues instead of leaving the GenAI projection on_OTHER. The fix deliberately does not infer language exception classes from error messages.Details
FlowErrorvariants and upstream failure classes to boundedsnake_caseOpenTelemetry error types.FlowError::Internalasinternal_errorwithout scraping exception names from message strings.error.typemetadata.error.typeinstead of falling back to_OTHER._OTHERwhere no structuredFlowErroris available, such as cancellation/drop paths.FlowErrormapping and theinternal_errorlimitation for external application and callback exceptions.Validation:
cargo fmt --all --checkcargo clippy --workspace --all-targets -- -D warningsFlowError, managed LLM/tool/stream, metadata, and GenAI projection testsjust docs— passed with zero errors; the unauthenticated redirect check was skippedjust test-python— 614 passed on the final rebased treejust test-rust— all workspace unit and integration test binaries passed; the recipe ends on an unrelated existing doctest failure wherescope_stack.rsreferences the unexportednemo_relay::Resultjust test-nodeis locally blocked by Node 23 (the repository requires Node 24) and sandboxed collector ports; the affected LLM/tool suites passjust test-gowas not run because the Go toolchain is not installed locallyuv run pre-commit run --all-files— every available hook passed; only unavailable local tools (cargo-deny,go, andgofmt) failedWhere should the reviewer start?
Start with
FlowError::otel_error_typeincrates/core/src/error.rs, then reviewmetadata_with_otel_errorincrates/core/src/api/shared.rsand the GenAI projection regression incrates/core/tests/unit/observability/otel_tests.rs.Related Issues: (use one of the action keywords Closes / Fixes / Resolves / Relates to)