Skip to content

feat: implement nemo_guardrails remote backend#144

Open
afourniernv wants to merge 6 commits into
NVIDIA:mainfrom
afourniernv:afournier/nmf-131-remote-backend
Open

feat: implement nemo_guardrails remote backend#144
afourniernv wants to merge 6 commits into
NVIDIA:mainfrom
afourniernv:afournier/nmf-131-remote-backend

Conversation

@afourniernv
Copy link
Copy Markdown
Contributor

@afourniernv afourniernv commented May 21, 2026

Overview

Adds the first real built-in nemo_guardrails remote backend for NeMo Flow core.

This PR moves beyond the contract-only surface and implements the first shippable remote slice:

  • built-in plugin auto-registration in core

  • remote backend activation for mode = remote

  • non-streaming and streaming LLM execution through the Guardrails server

  • managed tool_input and tool_output execution checks through the same remote backend

  • request-default pass-through for remote Guardrails request semantics

  • focused runtime validation and coverage for transport, malformed responses, tool rewrites, and error handling

  • I confirm this contribution is my own work, or I have the right to submit it under this project's license.

  • I searched existing issues and open pull requests, and this does not duplicate existing work.

Details

  • auto-register the built-in nemo_guardrails plugin through ensure_builtin_plugins_registered()
  • add a dedicated default core feature guardrails-remote for the remote backend dependency path
  • implement the remote Guardrails runtime in crates/core/src/plugins/nemo_guardrails/plugin_component.rs
  • support the native remote server contract for codec = "openai_chat"
  • support both non-streaming and streaming LLM execution
  • support remote request defaults pass-through:
    • context
    • thread_id
    • state
    • rails
    • llm_params
    • llm_output
    • output_vars
    • log
  • support managed tool_input and tool_output execution checks via the remote backend
  • emit coarse backend-level nemo_guardrails.remote.* marks for both LLM and managed tool remote checks
  • add focused unit coverage for:
    • built-in registration
    • remote config validation
    • transport and malformed-response lanes
    • non-streaming and streaming remote execution
    • managed tool blocking and rewrite behavior
    • tool-only config isolation from LLM execution
    • context/state/thread propagation on managed tool checks

Intentional PR2 boundary:

  • native remote support is openai_chat only
  • local backend is still not implemented
  • this stays core-only; binding surface enablement is deferred

Validation:

  • cargo test -p nemo-flow nemo_guardrails --lib --tests

Targeted live smoke against a local Guardrails server covered:

  • allowed and blocked non-streaming requests
  • streaming requests
  • managed tool_input blocked path
  • managed tool_output blocked path

Notes:

  • uv run pre-commit run --all-files still reports an unrelated repo-environment failure in ty for unresolved deepagents integration imports
  • unrelated package-lock.json churn was restored and is not part of this PR

Where should the reviewer start?

Start in crates/core/src/plugins/nemo_guardrails/plugin_component.rs.

The most important design decision in this PR is that the built-in plugin now implements a real remote execution backend while keeping the remote contract honest:

  • native remote support is OpenAI chat-completions shaped
  • LLM and managed tool execution are both supported through the core runtime
  • broader non-chat codec parity and the local Python runtime remain out of scope for this slice

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

  • Relates to #NMF-131
  • Relates to #NMF-148

Summary by CodeRabbit

  • New Features

    • Optional remote NeMo Guardrails backend added and enabled by default via feature flag.
    • New request-default options: thread_id and state.
  • Validation

    • Stronger validation for remote mode, request-default fields (thread_id length, state shape), and codec/IO requirements.
  • Tests

    • Replaced prior tests with a comprehensive suite covering remote backend, streaming/non-streaming flows, tool interception, and failure modes.

Review Change Stack

@copy-pr-bot
Copy link
Copy Markdown

copy-pr-bot Bot commented May 21, 2026

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 7aa072f9-dfb2-4f39-8cb7-00442a87010a

📥 Commits

Reviewing files that changed from the base of the PR and between 3c2276c and 60999ac.

📒 Files selected for processing (3)
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (12)
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.rs: Use cargo fmt for Rust code formatting (rustfmt defaults)
Use cargo clippy -- -D warnings for Rust linting, treating all warnings as errors
Use Rust snake_case naming convention for Rust code
Run just test-rust for Rust test suite

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

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

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

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

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

**/*.rs: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly work

**/*.rs: If any Rust code changed, always run just test-rust
If any Rust code changed, also run cargo fmt --all
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

Files:

  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
**/*.{rs,go,js,ts,jsx,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header with format: // SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 in Rust, Go, JavaScript, and TypeScript files

Files:

  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
**/{Cargo.toml,**/*.rs}

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

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

Files:

  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.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/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
{crates/core,crates/adaptive}/**/*

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

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

Files:

  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.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/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
crates/core/**/*.rs

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

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

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

Files:

  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
crates/{core,adaptive}/**

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

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

Files:

  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
**/*.{rs,py,js,ts,tsx,jsx,go,sh,bash,yml,yaml,toml,json,md,mjs,cjs}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

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

Files:

  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
{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:

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

⚙️ CodeRabbit configuration file

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

Files:

  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
🔇 Additional comments (11)
crates/core/src/plugins/nemo_guardrails/component.rs (2)

990-1002: LGTM!


990-1002: Please confirm required Rust validation commands were run for this change.

I don’t see execution evidence in the provided context for the required Rust checks. Please share results for:

  • cargo fmt --all
  • cargo clippy --workspace --all-targets -- -D warnings
  • just test-rust

As per coding guidelines: “Any Rust change must run just test-rust”, “Any Rust change must run cargo fmt --all”, and “Any Rust change must run cargo clippy --workspace --all-targets -- -D warnings”.

crates/core/src/plugins/nemo_guardrails/remote.rs (2)

181-181: LGTM!

Also applies to: 305-305, 618-618, 733-739


679-697: LGTM!

crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs (7)

41-42: LGTM!

Also applies to: 197-201


1148-1152: LGTM!

Also applies to: 1485-1489


1261-1262: LGTM!

Also applies to: 1356-1357


1781-1787: LGTM!

Also applies to: 1954-1960


2326-2352: LGTM!


761-762: LGTM!


955-955: LGTM!

Also applies to: 1073-1073, 1160-1160, 1778-1778, 1879-1879, 1951-1951, 2427-2427


Walkthrough

Adds a feature-gated remote backend for NeMo Guardrails: new guardrails-remote feature, module/schema updates (thread/state), register-time backend dispatch, validation rules, a reqwest-based runtime (non-stream + SSE streaming), remote tool pre/post checks with rewriting, and extensive tests.

Changes

Remote NeMo Guardrails Backend

Layer / File(s) Summary
Feature and dependency configuration
crates/core/Cargo.toml
guardrails-remote feature added and included in default to gate reqwest and rustls.
Builtin plugin registration refactor
crates/core/src/plugin.rs
Wraps builtin component registration in a local register_builtins closure passed to BUILTIN_PLUGIN_REGISTRATION.get_or_init(...).
Module export and config schema edits
crates/core/src/plugins/nemo_guardrails/mod.rs, crates/core/src/plugins/nemo_guardrails/component.rs
Rename public submodule (plugin_componentcomponent); conditionally import/stub remote module; add RequestDefaultsConfig.thread_id: Option<String> and state: Option<Json>; expose fields in editor/known-fields; update test include path.
Registration dispatch and validation rules
crates/core/src/plugins/nemo_guardrails/component.rs
register now parses config and dispatches to register_nemo_guardrails_backend; register_nemo_guardrails_backend routes remoteregister_remote_backend, returns explicit error for local; adds validate_remote_backend_support (requires codec="openai_chat" when remote LLM surfaces enabled) and extends validate_request_defaults (thread_id non-empty/min length 16; state must be object containing only events and/or state or empty).
Remote backend runtime and execution paths
crates/core/src/plugins/nemo_guardrails/remote.rs
Adds RemoteBackendRuntime (endpoint, headers, rustls provider, reqwest client), implements non-streaming POST handling and streaming SSE decoding into LlmJsonStream, assembles guardrails-enabled request payloads, emits start/end/error marks (with HTTP status redaction), implements remote tool input/output checks with JSON rewrite/validation, and provides wasm/feature-disabled fallback registration.
Comprehensive plugin component test suite
crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
Replaces prior test file with extensive tests and harness covering schema/editor surface, config validation and diagnostics, lifecycle/registration semantics, remote non-streaming and streaming success/error and robustness paths, transport failures, tool preflight and rewriting rules, ordering, and tool-only interception behavior.

Sequence Diagram

sequenceDiagram
  participant Plugin as NeMo Guardrails Plugin
  participant Runtime as RemoteBackendRuntime
  participant Remote as Remote Endpoint
  participant Tool as Tool Execution
  participant Events as EventEmitter

  Plugin->>Runtime: register (remote mode config)
  Runtime->>Runtime: build reqwest client
  Plugin->>Runtime: execute LLM request
  Runtime->>Events: emit nemo_guardrails.remote.start
  Runtime->>Runtime: build request body with guardrails + context/thread/state
  Runtime->>Remote: POST /v1/chat/completions (stream=false|true)
  alt HTTP Success (non-stream)
    Remote-->>Runtime: JSON response
    Runtime->>Events: emit nemo_guardrails.remote.end
    Runtime-->>Plugin: return parsed JSON
  else Streaming SSE
    Remote-->>Runtime: SSE chunks
    Runtime->>Plugin: forward LlmJsonStream chunks
    Runtime->>Events: emit nemo_guardrails.remote.end (on completion)
  else HTTP/transport error
    Remote-->>Runtime: error/timeout/status
    Runtime->>Events: emit nemo_guardrails.remote.error
    Runtime-->>Plugin: return error
  end

  Plugin->>Runtime: intercept tool execution
  Runtime->>Remote: POST tool_input check (stream=false)
  Remote-->>Runtime: guardrails.log.activated_rails
  alt blocking rail found
    Runtime->>Events: emit tool_error
    Runtime-->>Tool: reject execution
  else pass or rewrite
    Runtime-->>Tool: execute with original/rewritten arguments
    Tool-->>Runtime: result
    Runtime->>Remote: POST tool_output check
    Remote-->>Runtime: guardrails.log
    Runtime-->>Plugin: return original/rewritten result or reject if blocked
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 64.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Title follows Conventional Commits format with proper type, scope, and concise imperative summary under 72 characters.
Description check ✅ Passed Description includes all required template sections: Overview with checkboxes, Details with comprehensive change summary, Where should the reviewer start, and Related Issues with action keywords.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

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

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

@github-actions github-actions Bot added size:XL PR is extra large Feature a new feature lang:rust PR changes/introduces Rust code size:XXL PR is very large and removed size:XL PR is extra large size:XXL PR is very large labels May 21, 2026
@afourniernv afourniernv marked this pull request as ready for review May 22, 2026 13:14
@afourniernv afourniernv requested a review from a team as a code owner May 22, 2026 13:14
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

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

Inline comments:
In `@crates/core/src/plugins/nemo_guardrails/component.rs`:
- Around line 956-968: The length check uses raw thread_id.len() while the
emptiness check uses thread_id.trim().is_empty(), causing inconsistent
validation; update the logic in component.rs around request_defaults.thread_id
(the block that calls push_policy_diag with policy.unsupported_value and
NEMO_GUARDRAILS_PLUGIN_KIND) to operate on a trimmed value (e.g., compute let
thread_id_trimmed = thread_id.trim() and use thread_id_trimmed.is_empty() and
thread_id_trimmed.len() or thread_id_trimmed.chars().count() for Unicode-aware
length) so whitespace padding is handled consistently (or alternatively add
explicit whitespace validation if padded IDs should be rejected).
- Around line 20-22: Gate the remote module import and usage behind a
feature/target cfg: change the unconditional mod remote/import of
register_remote_backend to something like #[cfg(feature = "remote")] #[path =
"remote.rs"] mod remote; and #[cfg(feature = "remote")] use
remote::register_remote_backend; then add a fallback stub for
register_remote_backend or inside register_nemo_guardrails_backend (e.g.,
#[cfg(not(feature = "remote"))] pub fn register_remote_backend(...) -> Result<_,
_> or have register_nemo_guardrails_backend return a clear Err when running on
unsupported targets like wasm32) so builds without the "remote" feature or on
wasm32 do not try to pull in reqwest; ensure the stub provides a clear
compile-time or runtime message about the missing feature/unsupported target.
🪄 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: 8eb2a87e-24a6-4818-b0bf-f4bcc6337f1e

📥 Commits

Reviewing files that changed from the base of the PR and between acafd6f and ca5c813.

📒 Files selected for processing (7)
  • crates/core/Cargo.toml
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/plugin_component_tests.rs
💤 Files with no reviewable changes (1)
  • crates/core/tests/unit/plugins/nemo_guardrails/plugin_component_tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (16)
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.rs: Use cargo fmt for Rust code formatting (rustfmt defaults)
Use cargo clippy -- -D warnings for Rust linting, treating all warnings as errors
Use Rust snake_case naming convention for Rust code
Run just test-rust for Rust test suite

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

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

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

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

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

**/*.rs: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly work

**/*.rs: If any Rust code changed, always run just test-rust
If any Rust code changed, also run cargo fmt --all
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

Files:

  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
**/*.{rs,go,js,ts,jsx,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header with format: // SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 in Rust, Go, JavaScript, and TypeScript files

Files:

  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
**/{Cargo.toml,**/*.rs}

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

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

Files:

  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/Cargo.toml
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.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/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
{crates/core,crates/adaptive}/**/*

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

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

Files:

  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/Cargo.toml
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.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/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/Cargo.toml
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
crates/core/**/*.rs

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

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

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

Files:

  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
crates/{core,adaptive}/**

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

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

Files:

  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/Cargo.toml
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
**/*.{rs,py,js,ts,tsx,jsx,go,sh,bash,yml,yaml,toml,json,md,mjs,cjs}

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/Cargo.toml
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

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

Files:

  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
**/*.{py,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header with format: # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 in Python and TOML files

Files:

  • crates/core/Cargo.toml
**/Cargo.toml

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

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

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

Files:

  • crates/core/Cargo.toml
**/*.{py,txt,toml,cfg,yaml,yml}

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

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

Files:

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

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

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

Files:

  • crates/core/Cargo.toml
{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:

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

⚙️ CodeRabbit configuration file

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

Files:

  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
🔇 Additional comments (29)
crates/core/src/plugin.rs (1)

765-769: LGTM!

crates/core/src/plugins/nemo_guardrails/mod.rs (1)

14-14: LGTM!

crates/core/src/plugins/nemo_guardrails/component.rs (8)

189-194: LGTM!


320-321: LGTM!


362-372: LGTM!


434-447: LGTM!


527-528: LGTM!


902-926: LGTM!


969-992: LGTM!


1246-1247: LGTM!

crates/core/Cargo.toml (1)

17-22: ⚡ Quick win

No wasm32 build break: remote.rs already gates guardrails-remote deps

crates/core/src/plugins/nemo_guardrails/remote.rs only pulls in/uses reqwest and rustls under #[cfg(all(not(target_arch = "wasm32"), feature = "guardrails-remote"))], and it provides a wasm32 (and/or non-feature) register_remote_backend fallback under #[cfg(any(target_arch = "wasm32", not(feature = "guardrails-remote")))]. So crates/core/src/plugins/nemo_guardrails/component.rs can keep its unconditional mod remote; / use remote::register_remote_backend; without additional gating.

crates/core/src/plugins/nemo_guardrails/remote.rs (8)

1-57: LGTM!


59-99: LGTM!


101-221: LGTM!


223-403: LGTM!


405-452: LGTM!


454-520: LGTM!


530-715: LGTM!


718-941: LGTM!

crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs (10)

1-50: LGTM!


52-91: LGTM!


93-222: LGTM!


224-337: LGTM!


339-430: LGTM!


432-848: LGTM!


850-1171: LGTM!


1173-1683: LGTM!


1685-2209: LGTM!


2211-2465: LGTM!

Comment thread crates/core/src/plugins/nemo_guardrails/component.rs
Comment thread crates/core/src/plugins/nemo_guardrails/component.rs Outdated
Signed-off-by: Alex Fournier <afournier@nvidia.com>
Signed-off-by: Alex Fournier <afournier@nvidia.com>
Signed-off-by: Alex Fournier <afournier@nvidia.com>
Signed-off-by: Alex Fournier <afournier@nvidia.com>
Signed-off-by: Alex Fournier <afournier@nvidia.com>
@afourniernv afourniernv force-pushed the afournier/nmf-131-remote-backend branch from 8f2e3ae to 3c2276c Compare May 22, 2026 13:43
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 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/plugins/nemo_guardrails/component.rs`:
- Around line 985-999: The current validation for request_defaults.state only
ensures it contains 'events' or 'state' but doesn't reject extra keys; update
the check in the request_defaults.state handling so you validate that the
object's keys are a subset of the allowed set {'events','state'} and
push_policy_diag when any other key is present. Concretely, in the same block
that currently references request_defaults.state and calls push_policy_diag with
policy.unsupported_value, add logic to iterate the object's keys (or compute the
set difference) and if there are any keys besides "events" or "state" call
push_policy_diag(diagnostics, policy.unsupported_value,
"nemo_guardrails.unsupported_value",
Some(NEMO_GUARDRAILS_PLUGIN_KIND.to_string()),
Some("request_defaults.state".to_string()), "request_defaults.state must be
empty or contain only 'events' and/or 'state'".to_string()).

In `@crates/core/src/plugins/nemo_guardrails/remote.rs`:
- Around line 173-186: The code currently includes raw remote response bodies in
observability marks and error messages (seen where self.emit_mark calls pass
payload.clone() into remote_mark_data and where FlowError::Internal interpolates
the payload); instead, sanitize or omit the body before exporting by replacing
payload.clone() with a safe representation (e.g., None, a fixed string like
"<redacted>", or a truncated/hashed summary produced by a helper like
redact_payload(payload)) and ensure the FlowError message does not embed
sensitive contents (use status and a redacted summary instead); apply the same
change to the other occurrences mentioned (the remote_mark_data calls and
FlowError::Internal usages at the other locations).
- Around line 679-708: The code builds a rails map that always sets "tool_input"
and "tool_output" to false, causing tool-only checks to run under the wrong rail
family; update the rails construction in the RemoteCheckKind branch handling
(the rails variable created when matching RemoteCheckKind::Input/Output) to set
"tool_input" and "tool_output" according to the intended check type (e.g.,
enable tool_input for tool-input checks and tool_output for tool-output checks)
instead of hardcoding them false, then keep inserting rails into options and
preserving the existing request_defaults/log/guardrails insertion logic (see
symbols: RemoteCheckKind, rails, options, request_defaults, log, guardrails).

In `@crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs`:
- Around line 1-5: The PR lacks full Rust/core validation evidence — run the
required checks for changes under crates/core (including the unit tests in
tests/unit/plugins/nemo_guardrails/component_tests.rs): execute just test-rust,
cargo fmt --all, and cargo clippy --workspace --all-targets -- -D warnings, then
run the full language matrix for crates/core (all supported Rust toolchain
versions) and attach the resulting logs/screenshots to the PR; ensure the
artifacts explicitly reference the component_tests.rs run and note any fixes
made if formatting or clippy failures are found.
- Line 946: The test currently blocks on request_rx.recv().unwrap(), which can
hang; replace the blocking recv call with a bounded wait using
request_rx.recv_timeout(Duration::from_secs(...)) and handle the Err case to
fail the test with a clear timeout message (reference the request_rx and
captured variables). If the same test or helper also awaits stream.next().await
in a loop, wrap that await with tokio::time::timeout(Duration::from_secs(...),
stream.next()).await and convert the timeout result into a test failure message
so the test fails deterministically instead of hanging.
🪄 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: ffe36d84-5071-415c-a3a7-103f8e4b9fe0

📥 Commits

Reviewing files that changed from the base of the PR and between 8f2e3ae and 3c2276c.

📒 Files selected for processing (7)
  • crates/core/Cargo.toml
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/plugin_component_tests.rs
💤 Files with no reviewable changes (1)
  • crates/core/tests/unit/plugins/nemo_guardrails/plugin_component_tests.rs
📜 Review details
🧰 Additional context used
📓 Path-based instructions (16)
**/*.{py,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header with format: # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 in Python and TOML files

Files:

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

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

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

Files:

  • crates/core/Cargo.toml
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
**/Cargo.toml

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

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

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

Files:

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

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

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

Files:

  • crates/core/Cargo.toml
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
**/*.{rs,toml}

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

Update Rust crate names and module prefixes during coordinated rename operations

Files:

  • crates/core/Cargo.toml
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
**/*.{py,txt,toml,cfg,yaml,yml}

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

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

Files:

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

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

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

Files:

  • crates/core/Cargo.toml
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
{docs/**,README.md,**/Cargo.toml,**/package.json,**/*.md}

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

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

Files:

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

📄 CodeRabbit inference engine (AGENTS.md)

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

Files:

  • crates/core/Cargo.toml
  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
**/*.rs

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.rs: Use cargo fmt for Rust code formatting (rustfmt defaults)
Use cargo clippy -- -D warnings for Rust linting, treating all warnings as errors
Use Rust snake_case naming convention for Rust code
Run just test-rust for Rust test suite

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

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

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

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

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

**/*.rs: Run cargo fmt --all to format all Rust code
Run cargo clippy --workspace --all-targets -- -D warnings to enforce all clippy lints as errors

**/*.rs: Run cargo fmt --all when Rust files changed as part of WebAssembly work
Run cargo clippy --workspace --all-targets -- -D warnings when Rust files changed as part of WebAssembly work

**/*.rs: If any Rust code changed, always run just test-rust
If any Rust code changed, also run cargo fmt --all
If any Rust code changed, also run cargo clippy --workspace --all-targets -- -D warnings
Run Rust formatting with cargo fmt --all
Run Rust linting with cargo clippy --workspace --all-targets -- -D warnings

Files:

  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
**/*.{rs,go,js,ts,jsx,tsx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Include SPDX license header with format: // SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 in Rust, Go, JavaScript, and TypeScript files

Files:

  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.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/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
crates/core/**/*.rs

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

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

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

Files:

  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
crates/{core,adaptive}/**/*.rs

⚙️ CodeRabbit configuration file

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

Files:

  • crates/core/src/plugin.rs
  • crates/core/src/plugins/nemo_guardrails/mod.rs
  • crates/core/src/plugins/nemo_guardrails/component.rs
  • crates/core/src/plugins/nemo_guardrails/remote.rs
  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
{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:

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

⚙️ CodeRabbit configuration file

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

Files:

  • crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs
🔇 Additional comments (2)
crates/core/Cargo.toml (1)

17-22: Run the required validation matrix before merging.

The PR notes only mention cargo test -p nemo-flow nemo_guardrails --lib --tests, but this change set touches crates/core Rust code and crate features. Please verify the required Rust checks (just test-rust, cargo fmt --all, cargo clippy --workspace --all-targets -- -D warnings) and the broader crates/core validation (validate-change plus the full Rust/Python/Go/Node.js/WebAssembly matrix) were run on this branch.

As per coding guidelines, "**/*.rs: Any Rust change must run just test-rust", "Any Rust change must run cargo fmt --all", "`Any Rust change must run `cargo clippy --workspace --all-targets -- -D warnings", "crates/core/**/*.rs: If the change touched crates/core or shared runtime semantics, also use validate-change for broader validation", and "crates/{core,adaptive}/**: If crates/coreorcrates/adaptive changed, run the full matrix across Rust, Python, Go, Node.js, and WebAssembly."

crates/core/src/plugin.rs (1)

765-768: Guard nemo_guardrails built-in registration when guardrails-remote is off.
In crates/core/src/plugin.rs (lines 765-768), register_builtins unconditionally calls crate::plugins::nemo_guardrails::component::register_nemo_guardrails_component(). If that component (or its dependencies like reqwest/rustls) is gated behind guardrails-remote without a no-op/stub for the disabled case, this will break compilation. Ensure there’s either a stub/no-op implementation when the feature is off, or wrap the call (or provide a feature-gated alternative) to keep built-in initialization feature-compatible.

Comment thread crates/core/src/plugins/nemo_guardrails/component.rs Outdated
Comment thread crates/core/src/plugins/nemo_guardrails/remote.rs
Comment thread crates/core/src/plugins/nemo_guardrails/remote.rs
Comment on lines +1 to +5
// SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

//! Unit tests for the planned NeMo Guardrails plugin component contract.
#![allow(clippy::await_holding_lock)]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Run the required Rust/core validation matrix before merge.

The provided validation evidence only shows a targeted cargo test invocation. For this crates/core Rust change, the required formatting/lint/test commands and full language matrix are not evidenced.

As per coding guidelines, “If any Rust code changed, always run just test-rust… also run cargo fmt --all… also run cargo clippy --workspace --all-targets -- -D warnings” and “Changes to crates/core or crates/adaptive must run the full language matrix.”

🤖 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/tests/unit/plugins/nemo_guardrails/component_tests.rs` around
lines 1 - 5, The PR lacks full Rust/core validation evidence — run the required
checks for changes under crates/core (including the unit tests in
tests/unit/plugins/nemo_guardrails/component_tests.rs): execute just test-rust,
cargo fmt --all, and cargo clippy --workspace --all-targets -- -D warnings, then
run the full language matrix for crates/core (all supported Rust toolchain
versions) and attach the resulting logs/screenshots to the PR; ensure the
artifacts explicitly reference the component_tests.rs run and note any fixes
made if formatting or clippy failures are found.

Comment thread crates/core/tests/unit/plugins/nemo_guardrails/component_tests.rs Outdated
Signed-off-by: Alex Fournier <afournier@nvidia.com>
@afourniernv
Copy link
Copy Markdown
Contributor Author

@willkill07 @dagardner-nv live tested + no cargo blast radius. Did have to add some minimal deps. ready for review.

Copy link
Copy Markdown
Member

@willkill07 willkill07 left a comment

Choose a reason for hiding this comment

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

First brief pass. I'll have a more complete pass later.

Comment on lines +3 to +4

#[cfg(all(not(target_arch = "wasm32"), feature = "guardrails-remote"))]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If you have this at the top of the file, I don't believe you need it on every single include:

#![cfg(all(not(target_arch = "wasm32"), feature = "guardrails-remote"))]

Comment on lines +20 to +22
#[cfg(all(feature = "guardrails-remote", not(target_arch = "wasm32")))]
#[path = "remote.rs"]
mod remote;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Actually, since you have this, I don't think you need all of the cfg entries in remote.rs


#[cfg(all(not(target_arch = "wasm32"), feature = "guardrails-remote"))]
impl RemoteBackendRuntime {
fn new(config: &NeMoGuardrailsConfig, remote: &RemoteBackendConfig) -> PluginResult<Self> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Doesn't NeMoGuardrailsConfig already hold the optional RemoteBackendConfig ?

Shouldn't we just access that?

FlowError::Internal("LLM request content is not a JSON object".to_string())
})?;
body.insert("stream".to_string(), Json::Bool(stream));
if let Some(guardrails) = self.build_guardrails_config() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should not have to build the guardrails config with each outgoing request. Recommendation: hoist all logic as part of Runtime initialization

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This file appears to be doing more than just the component contract. Maybe split remote tests into their own file.

@willkill07 willkill07 added this to the 0.3 milestone May 22, 2026
@willkill07
Copy link
Copy Markdown
Member

/ok to test 60999ac

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature a new feature lang:rust PR changes/introduces Rust code size:XL PR is extra large

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants