Skip to content

feat(tools): add blocked tools policy - #56

Merged
rapids-bot[bot] merged 7 commits into
NVIDIA:mainfrom
AnuradhaKaruppiah:ak-blocked-tools
Jul 15, 2026
Merged

feat(tools): add blocked tools policy#56
rapids-bot[bot] merged 7 commits into
NVIDIA:mainfrom
AnuradhaKaruppiah:ak-blocked-tools

Conversation

@AnuradhaKaruppiah

@AnuradhaKaruppiah AnuradhaKaruppiah commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Overview

Adds first-class blocked tool policy across Fabric config, SDK authoring, run-plan routing, and adapters that can enforce it.

Canonical config shape:

tools:
  blocked:
    - browser
    - shell

Configuration note

The adapter-level harness.settings.disallowed_tools setting has been dropped. Configure the deny-list only through the typed, normalized tools.blocked field; the Claude adapter maps it internally to the Claude SDK's disallowed_tools option.

Adapter mappings:

  • Hermes maps blocked names to disabled toolsets.
  • Claude maps blocked names to disallowed_tools.
  • DeepAgents enforces blocked names through middleware for the main agent and subagents.
  • Adapters without tools support route the policy as unsupported.

Unsupported harness handling

An adapter that cannot enforce blocked tools must omit tools from its descriptor's config.accepts. Core preserves the configured policy and routes the tools capability to capability_plan.unsupported so the mismatch is explicit.

Blocked-tool policy must be handled fail-closed: planning and doctor diagnostics should identify the unsupported adapter capability, and invocation must not silently ignore the deny-list. The user must remove tools.blocked or select an adapter that declares and implements tools support.

This PR is stacked on #54.

Where should the reviewer start?

  • crates/fabric-core/src/config.rs
  • python/src/nemo_fabric/models.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • Adapter tests for Hermes, Claude, and DeepAgents

Validation

  • cargo test -p fabric-core
  • Focused Python adapter/SDK tests for blocked tools
  • ruff check on touched Python files
  • cargo fmt --check
  • git diff --check

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

  • Closes FABRIC-74

  • 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.

Summary by CodeRabbit

  • New Features

    • Added a portable tools.blocked configuration for disabling named tools and toolsets.
    • Claude, Deep Agents, and Hermes now enforce blocked-tool settings consistently, including delegated agents where supported.
    • Added typed configuration support for NeMo Relay, telemetry providers, and tool policies.
    • Added FabricConfig.block_tools() for programmatically blocking tools.
    • Unsupported tool policies now produce clear validation errors before runtime execution.
  • Documentation

    • Updated configuration guides and API references for tools, Relay, telemetry, and related schemas.

Signed-off-by: Anuradha Karuppiah <26330987+AnuradhaKaruppiah@users.noreply.github.com>
@linear

linear Bot commented Jul 13, 2026

Copy link
Copy Markdown

@copy-pr-bot

copy-pr-bot Bot commented Jul 13, 2026

Copy link
Copy Markdown

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

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This change introduces a typed tools.blocked policy, Relay and provider-based telemetry configuration, normalized capability planning, early unsupported-policy errors, and adapter-specific blocked-tool enforcement for Claude, Deep Agents, and Hermes.

Changes

Tools policy and Relay integration

Layer / File(s) Summary
Configuration and SDK contracts
schemas/*, python/src/nemo_fabric/models.py, python/src/nemo_fabric/types.py
Adds typed blocked-tools, Relay, and provider-based telemetry configuration contracts and serialization behavior.
Rust capability planning and runtime validation
crates/fabric-core/src/config.rs, crates/fabric-core/src/runtime.rs, crates/fabric-core/src/doctor.rs
Normalizes blocked tools into capability plans, routes unsupported policies, and rejects unsupported enforcement before runtime execution.
Adapter enforcement
adapters/common/*, adapters/claude/*, adapters/deepagents/*, adapters/hermes/*
Maps blocked tools to Claude deny-lists, Deep Agents middleware, and Hermes disabled toolsets.
Tests and documentation
tests/*, README.md, docs/reference/*
Updates contract, adapter, end-to-end, and generated API documentation coverage for the new configuration shapes and behavior.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Config
  participant CapabilityPlanner
  participant Adapter
  participant Runtime
  Config->>CapabilityPlanner: tools.blocked
  CapabilityPlanner->>Adapter: tools.blocked route
  Adapter->>Runtime: native enforcement or unsupported route
  Runtime->>Runtime: validate blocked-tools support
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.94% 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
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.
Title check ✅ Passed The title follows Conventional Commits and accurately summarizes the blocked tools policy change.
Description check ✅ Passed The description matches the required template and includes overview, reviewer start point, related issue, validation, and checklist items.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@AnuradhaKaruppiah
AnuradhaKaruppiah changed the base branch from main to pull-request/55 July 13, 2026 03:34

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

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

⚠️ Outside diff range comments (2)
adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (1)

214-229: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Treat an empty tools object as unset
config.tools can serialize to {} when ToolsConfig.blocked is empty, and this branch currently raises on that valid no-policy state. Return None for an empty dict before the type check.

🤖 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 `@adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py` around
lines 214 - 229, Update _allowed_tool_names so an empty config.tools dictionary
is treated as unset and returns None before the type validation. Preserve the
existing blocked-dictionary handling, list/string normalization, and
AdapterConfigError behavior for other invalid shapes.
python/src/nemo_fabric/types.py (1)

1143-1153: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Keep Relay artifact attribution bound to Relay.

With relay_enabled=True and telemetry_providers=["native", "relay"], this labels a reference with provider="native" while its URI is relay_output_dir. Prefer Relay whenever Relay produced the artifact, and add a mixed-provider regression test.

Proposed attribution fix
         if "relay_enabled" in data:
             providers = metadata.get("telemetry_providers")
-            provider = (
-                providers[0] if isinstance(providers, list) and providers and isinstance(providers[0], str) else "relay"
-            )
+            provider = "relay" if data["relay_enabled"] is True else (
+                providers[0]
+                if isinstance(providers, list) and providers and isinstance(providers[0], str)
+                else "relay"
+            )

As per path instructions, Python SDK results must retain parity with the native extension.

🤖 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 `@python/src/nemo_fabric/types.py` around lines 1143 - 1153, Update the
provider selection in the trace result construction around
metadata.get("telemetry_providers") so relay_enabled=True attributes
Relay-produced artifacts to "relay", even when "native" appears first in the
provider list; preserve the existing fallback for non-Relay cases and add a
mixed-provider regression test covering ["native", "relay"] and relay_output_dir
attribution.

Source: Path instructions

🤖 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 `@adapters/claude/src/nemo_fabric_adapters/claude/adapter.py`:
- Around line 243-249: Update _disallowed_tools to validate
settings.get("disallowed_tools") with _string_list(..., name="disallowed_tools")
before passing it to common_utils.merge_unique with
common_utils.blocked_tools(payload). Preserve the existing merge behavior while
ensuring malformed values raise claude_invalid_configuration instead of being
coerced.

In `@adapters/deepagents/README.md`:
- Around line 134-141: Revise the Native telemetry bullet in the README to add a
grammatical connector between “provider config” and “OpenTelemetry/OpenInference
exporter,” while preserving its meaning that the configured exporter sends spans
directly to the collector without relay artifacts.

In `@adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py`:
- Around line 270-297: Extract the duplicated AgentMiddleware construction used
by allowed_tools_middleware and blocked_tools_middleware into a shared factory
parameterized by the tool-membership predicate and rejection-message behavior.
Update both public middleware factories to supply their respective predicate and
message while preserving their existing async/sync handler delegation and
ToolMessage responses.

In `@examples/code_review_agent/config.py`:
- Around line 269-286: The relay and observability setup in the current
configuration flow contains repetitive runtime type-narrowing assertions that
are only needed for static typing. Simplify the handling around relay,
observability, and their atif/atof fields by using a small typed helper or
appropriate casts, while preserving the existing with_relay-created
configuration behavior and output-directory assignments.

In `@python/src/nemo_fabric/types.py`:
- Around line 378-385: Update the ToolsConfig constructor to reject blocked
values that are str or bytes before iterating, matching from_mapping()
validation. Preserve acceptance of valid string sequences and ensure scalar
inputs cannot be serialized as per-character tool names.

In `@tests/_utils/utils.py`:
- Around line 47-49: Update the telemetry assertion in the result-validation
helper so missing telemetry is handled explicitly rather than silently skipped.
Assert that telemetry is either absent from result or contains relay_enabled set
to False, preserving valid no-provider behavior while rejecting any enabled
relay value.

In `@tests/adapters/test_adapaters_common_hermes.py`:
- Around line 105-116: Merge
test_validate_hermes_telemetry_provider_rejects_native and
test_validate_hermes_telemetry_provider_rejects_mixed_native_and_relay into a
single pytest.mark.parametrize test, parameterizing the differing providers and
relay_enabled payload values while preserving the shared ValueError assertion
and message.

In `@tests/adapters/test_codex_cli.py`:
- Around line 560-561: Update the test around codex_payload and child_env to
assert that FABRIC_UNRELATED_SECRET is absent from child_env, while retaining
the assertion that CODEX_EXPLICIT is forwarded. Ensure the test verifies both
exclusion of ambient secrets and inclusion of explicitly configured environment
variables.

---

Outside diff comments:
In `@adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py`:
- Around line 214-229: Update _allowed_tool_names so an empty config.tools
dictionary is treated as unset and returns None before the type validation.
Preserve the existing blocked-dictionary handling, list/string normalization,
and AdapterConfigError behavior for other invalid shapes.

In `@python/src/nemo_fabric/types.py`:
- Around line 1143-1153: Update the provider selection in the trace result
construction around metadata.get("telemetry_providers") so relay_enabled=True
attributes Relay-produced artifacts to "relay", even when "native" appears first
in the provider list; preserve the existing fallback for non-Relay cases and add
a mixed-provider regression test covering ["native", "relay"] and
relay_output_dir attribution.
🪄 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: cf4dbfe4-d6af-451b-a728-a870067bc6f9

📥 Commits

Reviewing files that changed from the base of the PR and between c27f32b and 31f9c95.

⛔ Files ignored due to path filters (2)
  • adapters/deepagents/uv.lock is excluded by !**/*.lock
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (110)
  • ATTRIBUTIONS-Python.md
  • README.md
  • adapters/claude/README.md
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/hermes.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/deepagents/README.md
  • adapters/deepagents/pyproject.toml
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/hermes-cli/README.md
  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
  • adapters/hermes-sdk/README.md
  • adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py
  • crates/fabric-core/src/config.rs
  • crates/fabric-core/src/lib.rs
  • crates/fabric-core/src/runtime.rs
  • docs/reference/api/python-library-reference/index.md
  • docs/reference/api/python-library-reference/nemo_fabric.models.md
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitykind.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitytarget.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatifstorageconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointfieldnamepolicy.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointtransport.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofmode.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayotlptransport.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayunsupportedbehavior.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-telemetryprovider.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-load-adapter-descriptor.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-load-fabric-document.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-effective-config-from-config.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-effective-config-with-profiles.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-effective-config.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan-from-config.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan-from-effective-config.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan-with-profiles.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-validate-agent-directory.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-fabricconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayatifconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayatofconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayatofendpointconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relaycomponentconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayconfigpolicy.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayobservabilityconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayotlpconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-telemetryconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-telemetryplan.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-telemetryproviderconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/doctor/enum-doctorstatus.mdx
  • docs/reference/api/rust-library-reference/fabric-core/doctor/fn-doctor-plan.mdx
  • docs/reference/api/rust-library-reference/fabric-core/doctor/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/doctor/struct-doctorcheck.mdx
  • docs/reference/api/rust-library-reference/fabric-core/doctor/struct-doctorreport.mdx
  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
  • docs/reference/api/rust-library-reference/fabric-core/error/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/error/type-result.mdx
  • docs/reference/api/rust-library-reference/fabric-core/fn-version.mdx
  • docs/reference/api/rust-library-reference/fabric-core/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/runtime/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/schema/index.mdx
  • docs/sdk/python.mdx
  • examples/code_review_agent/config.py
  • examples/harbor/README.md
  • examples/harbor/demo/task/environment/fabric/configs/codex.yaml
  • examples/harbor/demo/task/environment/fabric/configs/hermes-relay.yaml
  • examples/harbor/demo/task/environment/fabric/configs/hermes.yaml
  • examples/harbor/demo/task/environment/fabric/configs/smoke.yaml
  • pyproject.toml
  • python/src/nemo_fabric/__init__.py
  • python/src/nemo_fabric/models.py
  • python/src/nemo_fabric/types.py
  • schemas/adapter-invocation.schema.json
  • schemas/agent.schema.json
  • schemas/effective-config.schema.json
  • schemas/profile.schema.json
  • schemas/run-plan.schema.json
  • tests/_utils/utils.py
  • tests/adapters/test_adapaters_common_hermes.py
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_codex_cli.py
  • tests/adapters/test_deepagents.py
  • tests/adapters/test_hermes_cli.py
  • tests/adapters/test_hermes_sdk_adapter.py
  • tests/e2e/test_cli.py
  • tests/fixtures/file-config-agent/agent.yaml
  • tests/fixtures/file-config-agent/profiles/codex-cli.yaml
  • tests/fixtures/file-config-agent/profiles/env-local.yaml
  • tests/fixtures/file-config-agent/profiles/env-opensandbox.yaml
  • tests/fixtures/file-config-agent/profiles/hermes-cli.yaml
  • tests/fixtures/file-config-agent/profiles/hermes-sdk.yaml
  • tests/fixtures/file-config-agent/profiles/mcp-github.yaml
  • tests/fixtures/file-config-agent/profiles/native-otel.yaml
  • tests/fixtures/file-config-agent/profiles/relay-openinference.yaml
  • tests/fixtures/file-config-agent/profiles/relay-otel.yaml
  • tests/fixtures/file-config-agent/profiles/relay.yaml
  • tests/fixtures/hermes-cli-agent/agent.yaml
  • tests/fixtures/hermes-cli-agent/profiles/env-local.yaml
  • tests/fixtures/hermes-shim-agent/agent.yaml
  • tests/fixtures/hermes-shim-agent/profiles/env-local.yaml
  • tests/fixtures/hermes-shim-agent/profiles/harbor-swebench-django-13741.yaml
  • tests/fixtures/hermes-shim-agent/profiles/mcp-github.yaml
  • tests/fixtures/hermes-shim-agent/profiles/swebench-shim.yaml
  • tests/integrations/test_harbor_runner.py
  • tests/python/test_code_review_example.py
  • tests/python/test_native_sdk.py
  • tests/python/test_sdk_contract.py
  • tests/python/test_typed_config.py
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: Test (x86_64)
  • GitHub Check: Pre-commit
  • GitHub Check: Test (arm64)
🧰 Additional context used
📓 Path-based instructions (8)
**

⚙️ CodeRabbit configuration file

**:

Contributing to NeMo Fabric

Thank you for your interest in contributing to NeMo Fabric. This guide covers
the development workflow, coding standards, and pull request process.

Development Setup

This section collects the setup steps needed before building, testing, or
contributing changes.

Package Installation

NeMo Fabric is not currently available on PyPI. To consume the Python packages,
build wheels from a source checkout:

just wheels
uv pip install --find-links dist "nemo-fabric[runtime]"

Adapters are distributed as optional extras. For example, install the Hermes
SDK adapter with:

uv pip install --find-links dist "nemo-fabric[adapters-hermes-sdk]"

Refer to the installation guide for the
complete list of adapters and installation options.

Source Development

Install these tools before you start:

  • Rust (stable toolchain) -- install with rustup
  • Python >= 3.11
  • uv -- follow the uv installation guide
  • just >= 1.50.0 -- cargo install just --locked

Clone the repository, create a virtual environment, and build the Rust and
Python packages:

git clone https://github.com/NVIDIA/NeMo-Fabric.git
cd NeMo-Fabric

uv venv --seed .venv --python 3.13
source .venv/bin/activate
uv sync --all-groups --all-extras
just no_uv=true build-all

Verify the checkout by running the test suites described in
Testing Requirements.

Release Tagging

Versioned release tags must use raw Rust-compatible SemVer without a leading
v.

  • Use 0.1.0 for stable releases.
  • Use 0.1.0-rc.1 for prereleases.
  • Do not create tags such as v0.1.0 or v0.1.0-rc.1.

This keeps release tags aligned with Cargo package versions and lets...

Files:

  • docs/reference/api/rust-library-reference/fabric-core/fn-version.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan-from-config.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-validate-agent-directory.mdx
  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
  • adapters/hermes-sdk/README.md
  • tests/fixtures/hermes-cli-agent/profiles/env-local.yaml
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-effective-config.mdx
  • docs/reference/api/rust-library-reference/fabric-core/doctor/enum-doctorstatus.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitytarget.mdx
  • tests/fixtures/file-config-agent/profiles/env-local.yaml
  • docs/reference/api/rust-library-reference/fabric-core/doctor/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/doctor/struct-doctorcheck.mdx
  • docs/reference/api/rust-library-reference/fabric-core/doctor/struct-doctorreport.mdx
  • docs/reference/api/rust-library-reference/fabric-core/schema/index.mdx
  • tests/fixtures/file-config-agent/profiles/codex-cli.yaml
  • docs/reference/api/rust-library-reference/fabric-core/runtime/index.mdx
  • adapters/hermes-cli/README.md
  • adapters/deepagents/pyproject.toml
  • examples/harbor/demo/task/environment/fabric/configs/codex.yaml
  • docs/reference/api/rust-library-reference/fabric-core/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/error/index.mdx
  • tests/fixtures/hermes-shim-agent/profiles/env-local.yaml
  • tests/fixtures/hermes-shim-agent/profiles/harbor-swebench-django-13741.yaml
  • tests/fixtures/file-config-agent/profiles/hermes-sdk.yaml
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan.mdx
  • docs/reference/api/rust-library-reference/fabric-core/error/type-result.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-load-adapter-descriptor.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitykind.mdx
  • tests/_utils/utils.py
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan-from-effective-config.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-effective-config-from-config.mdx
  • tests/fixtures/file-config-agent/profiles/relay-openinference.yaml
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-effective-config-with-profiles.mdx
  • crates/fabric-core/src/lib.rs
  • tests/fixtures/file-config-agent/profiles/native-otel.yaml
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayatofendpointconfig.mdx
  • README.md
  • docs/reference/api/rust-library-reference/fabric-core/doctor/fn-doctor-plan.mdx
  • tests/fixtures/file-config-agent/profiles/env-opensandbox.yaml
  • tests/adapters/test_hermes_sdk_adapter.py
  • tests/adapters/test_hermes_cli.py
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-load-fabric-document.mdx
  • tests/fixtures/file-config-agent/profiles/hermes-cli.yaml
  • tests/fixtures/hermes-cli-agent/agent.yaml
  • examples/harbor/demo/task/environment/fabric/configs/hermes.yaml
  • tests/fixtures/hermes-shim-agent/profiles/mcp-github.yaml
  • pyproject.toml
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relaycomponentconfig.mdx
  • adapters/claude/README.md
  • tests/fixtures/file-config-agent/profiles/relay.yaml
  • examples/harbor/demo/task/environment/fabric/configs/smoke.yaml
  • tests/fixtures/file-config-agent/agent.yaml
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-telemetryproviderconfig.mdx
  • ATTRIBUTIONS-Python.md
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofmode.mdx
  • tests/fixtures/file-config-agent/profiles/relay-otel.yaml
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-telemetryplan.mdx
  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan-with-profiles.mdx
  • tests/fixtures/hermes-shim-agent/agent.yaml
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-fabricconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-telemetryprovider.mdx
  • schemas/profile.schema.json
  • tests/fixtures/hermes-shim-agent/profiles/swebench-shim.yaml
  • examples/harbor/demo/task/environment/fabric/configs/hermes-relay.yaml
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointtransport.mdx
  • tests/e2e/test_cli.py
  • adapters/deepagents/README.md
  • examples/harbor/README.md
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayotlptransport.mdx
  • python/src/nemo_fabric/__init__.py
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointfieldnamepolicy.mdx
  • tests/python/test_native_sdk.py
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-telemetryconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayotlpconfig.mdx
  • adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py
  • docs/sdk/python.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayconfigpolicy.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayatifconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayobservabilityconfig.mdx
  • docs/reference/api/python-library-reference/index.md
  • docs/reference/api/rust-library-reference/fabric-core/config/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayatofconfig.mdx
  • tests/python/test_code_review_example.py
  • crates/fabric-core/src/runtime.rs
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatifstorageconfig.mdx
  • tests/adapters/test_claude_adapter.py
  • tests/fixtures/file-config-agent/profiles/mcp-github.yaml
  • tests/python/test_typed_config.py
  • adapters/common/src/nemo_fabric_adapters/common/hermes.py
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • tests/adapters/test_adapaters_common_hermes.py
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayunsupportedbehavior.mdx
  • examples/code_review_agent/config.py
  • tests/adapters/test_deepagents.py
  • docs/reference/api/python-library-reference/nemo_fabric.models.md
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • schemas/adapter-invocation.schema.json
  • schemas/effective-config.schema.json
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
  • tests/integrations/test_harbor_runner.py
  • schemas/agent.schema.json
  • schemas/run-plan.schema.json
  • tests/python/test_sdk_contract.py
  • tests/adapters/test_codex_cli.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • python/src/nemo_fabric/models.py
  • python/src/nemo_fabric/types.py
  • crates/fabric-core/src/config.rs
{docs/**,README.md,AGENTS.md}

⚙️ CodeRabbit configuration file

{docs/**,README.md,AGENTS.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency with generated schemas.

Files:

  • docs/reference/api/rust-library-reference/fabric-core/fn-version.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan-from-config.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-validate-agent-directory.mdx
  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-effective-config.mdx
  • docs/reference/api/rust-library-reference/fabric-core/doctor/enum-doctorstatus.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitytarget.mdx
  • docs/reference/api/rust-library-reference/fabric-core/doctor/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/doctor/struct-doctorcheck.mdx
  • docs/reference/api/rust-library-reference/fabric-core/doctor/struct-doctorreport.mdx
  • docs/reference/api/rust-library-reference/fabric-core/schema/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/runtime/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/error/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan.mdx
  • docs/reference/api/rust-library-reference/fabric-core/error/type-result.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-load-adapter-descriptor.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitykind.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan-from-effective-config.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-effective-config-from-config.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-effective-config-with-profiles.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayatofendpointconfig.mdx
  • README.md
  • docs/reference/api/rust-library-reference/fabric-core/doctor/fn-doctor-plan.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-load-fabric-document.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relaycomponentconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-telemetryproviderconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofmode.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-telemetryplan.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan-with-profiles.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-fabricconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-telemetryprovider.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointtransport.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayotlptransport.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointfieldnamepolicy.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-telemetryconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayotlpconfig.mdx
  • docs/sdk/python.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayconfigpolicy.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayatifconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayobservabilityconfig.mdx
  • docs/reference/api/python-library-reference/index.md
  • docs/reference/api/rust-library-reference/fabric-core/config/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-relayatofconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatifstorageconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayunsupportedbehavior.mdx
  • docs/reference/api/python-library-reference/nemo_fabric.models.md
{adapters/**,examples/**}

⚙️ CodeRabbit configuration file

{adapters/**,examples/**}: Review adapter and example changes for command correctness, config/schema consistency, artifact handling, and compatibility with the public Fabric contracts.

Files:

  • adapters/hermes-sdk/README.md
  • adapters/hermes-cli/README.md
  • adapters/deepagents/pyproject.toml
  • examples/harbor/demo/task/environment/fabric/configs/codex.yaml
  • examples/harbor/demo/task/environment/fabric/configs/hermes.yaml
  • adapters/claude/README.md
  • examples/harbor/demo/task/environment/fabric/configs/smoke.yaml
  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
  • examples/harbor/demo/task/environment/fabric/configs/hermes-relay.yaml
  • adapters/deepagents/README.md
  • examples/harbor/README.md
  • adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/hermes.py
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • examples/code_review_agent/config.py
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
{tests/**,python/tests/**}

⚙️ CodeRabbit configuration file

{tests/**,python/tests/**}: Tests should cover the behavior promised by the changed API surface, including error paths, lifecycle cleanup, and SDK/native parity where relevant.

Files:

  • tests/fixtures/hermes-cli-agent/profiles/env-local.yaml
  • tests/fixtures/file-config-agent/profiles/env-local.yaml
  • tests/fixtures/file-config-agent/profiles/codex-cli.yaml
  • tests/fixtures/hermes-shim-agent/profiles/env-local.yaml
  • tests/fixtures/hermes-shim-agent/profiles/harbor-swebench-django-13741.yaml
  • tests/fixtures/file-config-agent/profiles/hermes-sdk.yaml
  • tests/_utils/utils.py
  • tests/fixtures/file-config-agent/profiles/relay-openinference.yaml
  • tests/fixtures/file-config-agent/profiles/native-otel.yaml
  • tests/fixtures/file-config-agent/profiles/env-opensandbox.yaml
  • tests/adapters/test_hermes_sdk_adapter.py
  • tests/adapters/test_hermes_cli.py
  • tests/fixtures/file-config-agent/profiles/hermes-cli.yaml
  • tests/fixtures/hermes-cli-agent/agent.yaml
  • tests/fixtures/hermes-shim-agent/profiles/mcp-github.yaml
  • tests/fixtures/file-config-agent/profiles/relay.yaml
  • tests/fixtures/file-config-agent/agent.yaml
  • tests/fixtures/file-config-agent/profiles/relay-otel.yaml
  • tests/fixtures/hermes-shim-agent/agent.yaml
  • tests/fixtures/hermes-shim-agent/profiles/swebench-shim.yaml
  • tests/e2e/test_cli.py
  • tests/python/test_native_sdk.py
  • tests/python/test_code_review_example.py
  • tests/adapters/test_claude_adapter.py
  • tests/fixtures/file-config-agent/profiles/mcp-github.yaml
  • tests/python/test_typed_config.py
  • tests/adapters/test_adapaters_common_hermes.py
  • tests/adapters/test_deepagents.py
  • tests/integrations/test_harbor_runner.py
  • tests/python/test_sdk_contract.py
  • tests/adapters/test_codex_cli.py
tests/**/*.py

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

tests/**/*.py: Use pytest to run Python tests.
Do not add @pytest.mark.asyncio to test functions; async tests are detected and run automatically.
Do not add -> None return type annotations to test functions.
When mocking a class, do not define a new class; use unittest.mock.MagicMock or unittest.mock.AsyncMock, adding spec when needed.
Name mocked classes with a mock prefix, not fake.
Prefer pytest fixtures over helper methods.
Do not duplicate fixtures across test files; if a fixture is needed in multiple test files, define it in conftest.py.
When creating a fixture, use @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) and define the function as <fixture_name>_fixture() -> <return_type>; only pass scope when it is not function.
Prefer pytest.mark.parametrize over creating separate tests for different input types.
If a fixture is needed for a test but does not return a value, or its value is unused, use @pytest.mark.usefixtures.
When modifying environment variables in a test, use os.environ; tests/conftest.py provides an autouse restore_environ_fixture that restores environment variables after each test, so monkeypatch.setenv is unnecessary.

Files:

  • tests/_utils/utils.py
  • tests/adapters/test_hermes_sdk_adapter.py
  • tests/adapters/test_hermes_cli.py
  • tests/e2e/test_cli.py
  • tests/python/test_native_sdk.py
  • tests/python/test_code_review_example.py
  • tests/adapters/test_claude_adapter.py
  • tests/python/test_typed_config.py
  • tests/adapters/test_adapaters_common_hermes.py
  • tests/adapters/test_deepagents.py
  • tests/integrations/test_harbor_runner.py
  • tests/python/test_sdk_contract.py
  • tests/adapters/test_codex_cli.py
crates/fabric-core/src/**/*.rs

⚙️ CodeRabbit configuration file

crates/fabric-core/src/**/*.rs: Review the Rust core for runtime lifecycle correctness, handle validation, capability routing accuracy, schema stability, and error semantics.
Public API changes should match committed schemas, tests, and documentation.

Files:

  • crates/fabric-core/src/lib.rs
  • crates/fabric-core/src/runtime.rs
  • crates/fabric-core/src/config.rs
schemas/**/*

⚙️ CodeRabbit configuration file

schemas/**/*: Schemas are generated public contract snapshots. Check that schema diffs correspond to intentional Rust type changes and are covered by core tests.

Files:

  • schemas/profile.schema.json
  • schemas/adapter-invocation.schema.json
  • schemas/effective-config.schema.json
  • schemas/agent.schema.json
  • schemas/run-plan.schema.json
python/src/nemo_fabric/**/*

⚙️ CodeRabbit configuration file

python/src/nemo_fabric/**/*: Review Python SDK changes for typed API consistency, import-time dependency neutrality, async/session behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.

Files:

  • python/src/nemo_fabric/__init__.py
  • python/src/nemo_fabric/models.py
  • python/src/nemo_fabric/types.py
🧠 Learnings (2)
📚 Learning: 2026-07-09T22:28:51.689Z
Learnt from: AjayThorve
Repo: NVIDIA/NeMo-Fabric PR: 43
File: adapters/claude-sdk/src/nemo_fabric_adapters/claude_sdk/adapter.py:164-168
Timestamp: 2026-07-09T22:28:51.689Z
Learning: In the NeMo-Fabric adapters, treat path values used in Fabric adapter configuration (including logic like `_resolve_path` in adapter.py) as config-root-relative. Do not apply `Path.expanduser()` (or otherwise apply `~`/home or shell-style expansion), because it will make the resolved paths normalize inconsistently across adapters. Also, do not rely on or add any resolution behavior that uses `harness.settings.cwd` as an override point for these adapter paths—`harness.settings.cwd` is explicitly unsupported in this adapter context.

Applied to files:

  • adapters/hermes-cli/src/nemo_fabric_adapters/hermes_cli/adapter.py
  • adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py
📚 Learning: 2026-06-28T04:03:32.877Z
Learnt from: AjayThorve
Repo: NVIDIA/NeMo-Fabric PR: 26
File: python/tests/smoke_typed_config.py:163-177
Timestamp: 2026-06-28T04:03:32.877Z
Learning: In NVIDIA NeMo Fabric Python SDK serialization of `RuntimeCapabilities` (to satisfy the “parity contract” with Rust core and the CLI), do not emit metadata keys when the corresponding metadata is absent. Instead, omit those fields entirely so the produced JSON matches the Rust/CLI output (e.g., avoid `null`, empty objects, or placeholder metadata). During review, verify the serializer/builders follow this omission rule and that Python outputs/parity tests reflect the same shape.

Applied to files:

  • python/src/nemo_fabric/__init__.py
  • python/src/nemo_fabric/models.py
  • python/src/nemo_fabric/types.py
🧬 Code graph analysis (6)
adapters/claude/src/nemo_fabric_adapters/claude/adapter.py (1)
tests/adapters/test_claude_adapter.py (1)
  • build_options (131-131)
examples/code_review_agent/config.py (1)
tests/python/test_code_review_example.py (6)
  • with_relay_openinference (59-59)
  • with_native_otel (56-56)
  • with_relay_otel (60-60)
  • codex_cli_config (34-34)
  • with_relay (58-58)
  • base_config (31-31)
tests/adapters/test_deepagents.py (1)
adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (1)
  • awrap_tool_call (258-261)
adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (1)
tests/adapters/test_deepagents.py (5)
  • request (442-443)
  • handler (439-440)
  • _allowed_tool_names (482-482)
  • awrap_tool_call (445-445)
  • run_deepagents (203-203)
adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py (2)
tests/integrations/test_harbor_runner.py (2)
  • write_config_files (292-292)
  • build_command (293-293)
tests/adapters/test_codex_cli.py (7)
  • wait_for_relay_gateway (486-486)
  • write_config_files (159-159)
  • redact_command (518-518)
  • load_thread_id (598-598)
  • build_command (161-161)
  • toml_value (525-525)
  • run_codex (413-413)
tests/integrations/test_harbor_runner.py (1)
python/src/nemo_fabric/integrations/harbor/runner.py (2)
  • compose_config (27-59)
  • load_config (21-24)
🪛 ast-grep (0.44.1)
tests/python/test_sdk_contract.py

[info] 634-634: use jsonify instead of json.dumps for JSON output
Context: json.dumps(_plan()["effective_config"])
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 644-644: use jsonify instead of json.dumps for JSON output
Context: json.dumps(_plan())
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 648-648: use jsonify instead of json.dumps for JSON output
Context: json.dumps(_runtime())
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🪛 LanguageTool
docs/reference/api/rust-library-reference/fabric-core/config/struct-relayatofendpointconfig.mdx

[style] ~27-~27: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...## headers: BTreeMap<String, String> Endpoint headers. ### timeout_millis: u64 Re...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

docs/reference/api/rust-library-reference/fabric-core/config/struct-relayotlpconfig.mdx

[style] ~31-~31: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...## headers: BTreeMap<String, String> OTLP headers. ### `resource_attributes: BTr...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~35-~35: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ..._attributes: BTreeMap<String, String> OTLP resource attributes. ###service_name...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~39-~39: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ttributes. ### service_name: String OTLP service name. ### `service_namespace: ...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~43-~43: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...## service_namespace: Option<String> OTLP service namespace. ### `service_versio...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~47-~47: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... ### service_version: Option<String> OTLP service version. ### `instrumentation_...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)


[style] ~51-~51: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...instrumentation_scope: Option OTLP instrumentation scope. ###timeout_mi...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

docs/reference/api/rust-library-reference/fabric-core/config/struct-relayconfigpolicy.mdx

[style] ~27-~27: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...orted_value: RelayUnsupportedBehavior` Policy for unsupported values. ## Trait Imple...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🪛 markdownlint-cli2 (0.22.1)
docs/reference/api/python-library-reference/nemo_fabric.models.md

[warning] 611-611: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 671-671: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 731-731: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 791-791: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 851-851: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 911-911: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 971-971: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1031-1031: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1091-1091: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1151-1151: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1211-1211: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


[warning] 1271-1271: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🪛 Ruff (0.15.20)
adapters/common/src/nemo_fabric_adapters/common/hermes.py

[warning] 45-45: Avoid specifying long messages outside the exception class

(TRY003)

tests/adapters/test_deepagents.py

[warning] 465-465: Missing return type annotation for private function handler

Add return type annotation: str

(ANN202)


[warning] 468-468: Missing return type annotation for private function request

(ANN202)

adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py

[warning] 270-270: Dynamically typed expressions (typing.Any) are disallowed in blocked_tools_middleware

(ANN401)


[warning] 276-276: Dynamically typed expressions (typing.Any) are disallowed in request

(ANN401)


[warning] 276-276: Dynamically typed expressions (typing.Any) are disallowed in _blocked

(ANN401)


[warning] 285-285: Dynamically typed expressions (typing.Any) are disallowed in request

(ANN401)


[warning] 285-285: Dynamically typed expressions (typing.Any) are disallowed in handler

(ANN401)


[warning] 285-285: Dynamically typed expressions (typing.Any) are disallowed in awrap_tool_call

(ANN401)


[warning] 290-290: Dynamically typed expressions (typing.Any) are disallowed in request

(ANN401)


[warning] 290-290: Dynamically typed expressions (typing.Any) are disallowed in handler

(ANN401)


[warning] 290-290: Dynamically typed expressions (typing.Any) are disallowed in wrap_tool_call

(ANN401)


[warning] 494-494: Dynamically typed expressions (typing.Any) are disallowed in subagent

(ANN401)


[warning] 494-494: Dynamically typed expressions (typing.Any) are disallowed in _block_subagent

(ANN401)


[warning] 502-502: Too many statements (53 > 50)

(PLR0915)

adapters/codex-cli/src/nemo_fabric_adapters/codex_cli/adapter.py

[warning] 131-131: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 208-208: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 232-232: Prefer TypeError exception for invalid type

(TRY004)


[warning] 232-232: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 294-294: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 357-357: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 384-384: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 481-481: Avoid specifying long messages outside the exception class

(TRY003)

tests/python/test_sdk_contract.py

[warning] 651-651: Unused method argument: plan_json

(ARG002)

tests/adapters/test_codex_cli.py

[warning] 325-325: Unused function argument: tmp_path

(ARG001)


[error] 560-560: Possible hardcoded password assigned to: "FABRIC_UNRELATED_SECRET"

(S105)

adapters/common/src/nemo_fabric_adapters/common/utils.py

[warning] 156-156: Dynamically typed expressions (typing.Any) are disallowed in *values

(ANN401)

python/src/nemo_fabric/types.py

[warning] 107-107: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 394-394: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 509-509: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 515-515: Remove quotes from type annotation

Remove quotes

(UP037)


[warning] 523-523: Remove quotes from type annotation

Remove quotes

(UP037)


[warning] 534-534: Remove quotes from type annotation

Remove quotes

(UP037)


[warning] 547-547: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 757-757: Remove quotes from type annotation

Remove quotes

(UP037)

Comment thread adapters/claude/src/nemo_fabric_adapters/claude/adapter.py Outdated
Comment thread adapters/deepagents/README.md
Comment thread adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
Comment thread examples/code_review_agent/config.py
Comment thread python/src/nemo_fabric/types.py
Comment thread tests/_utils/utils.py
Comment thread tests/adapters/test_adapaters_common_hermes.py Outdated
Comment thread tests/adapters/test_codex_cli.py Outdated
@AnuradhaKaruppiah
AnuradhaKaruppiah changed the base branch from pull-request/55 to main July 13, 2026 03:38
Signed-off-by: Anuradha Karuppiah <26330987+AnuradhaKaruppiah@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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 `@adapters/claude/README.md`:
- Around line 40-42: Update the typed SDK example near the FabricConfig usage to
import and instantiate ToolsConfig with its blocked mapping instead of passing
tools as a list. Ensure the example uses the canonical typed FabricConfig API,
or remove the tools field if no blocked tools are required.

In `@docs/reference/api/python-library-reference/nemo_fabric.models.md`:
- Around line 1424-1425: Add a blank line after the ToolsConfig class heading
before its descriptive text, preserving the existing heading and documentation
content so the section conforms to MD022.

In `@tests/adapters/test_deepagents.py`:
- Around line 658-662: Strengthen the assertions in the test around the
configured main-agent and subagent middleware so they verify blocked-tool
behavior rather than merely non-empty lists. Inspect the blocked-tool
configuration or invoke each middleware gate to confirm write_file is rejected
while read_file remains allowed for both create_kwargs["middleware"] and
subagents[0]["middleware"].
- Around line 465-468: Annotate the local helper functions handler and request
with explicit return types to satisfy Ruff ANN202, using the appropriate type
for each helper’s returned value; leave the surrounding test function
unannotated and do not add -> None to it.
🪄 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: 68a3fdea-198e-4cfe-a066-f62fd380e1d1

📥 Commits

Reviewing files that changed from the base of the PR and between 31f9c95 and 30bf20c.

📒 Files selected for processing (30)
  • README.md
  • adapters/claude/README.md
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/hermes.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/deepagents/README.md
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/hermes-cli/README.md
  • adapters/hermes-sdk/README.md
  • adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py
  • crates/fabric-core/src/config.rs
  • docs/reference/api/python-library-reference/index.md
  • docs/reference/api/python-library-reference/nemo_fabric.models.md
  • docs/reference/api/python-library-reference/nemo_fabric.types.md
  • examples/code_review_agent/config.py
  • python/src/nemo_fabric/__init__.py
  • python/src/nemo_fabric/models.py
  • python/src/nemo_fabric/types.py
  • schemas/adapter-invocation.schema.json
  • schemas/agent.schema.json
  • schemas/effective-config.schema.json
  • schemas/profile.schema.json
  • schemas/run-plan.schema.json
  • tests/_utils/utils.py
  • tests/adapters/test_adapaters_common_hermes.py
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_codex_cli.py
  • tests/adapters/test_deepagents.py
  • tests/e2e/test_claude.py
  • tests/python/test_sdk_contract.py
💤 Files with no reviewable changes (1)
  • docs/reference/api/python-library-reference/nemo_fabric.types.md
📜 Review details
⏰ Context from checks skipped due to timeout. (2)
  • GitHub Check: Test (x86_64)
  • GitHub Check: Test (arm64)
🧰 Additional context used
📓 Path-based instructions (8)
tests/**/*.py

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

tests/**/*.py: Use pytest to run Python tests.
Do not add @pytest.mark.asyncio to test functions; async tests are detected and run automatically.
Do not add -> None return type annotations to test functions.
When mocking a class, do not define a new class; use unittest.mock.MagicMock or unittest.mock.AsyncMock, adding spec when needed.
Name mocked classes with a mock prefix, not fake.
Prefer pytest fixtures over helper methods.
Do not duplicate fixtures across test files; if a fixture is needed in multiple test files, define it in conftest.py.
When creating a fixture, use @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) and define the function as <fixture_name>_fixture() -> <return_type>; only pass scope when it is not function.
Prefer pytest.mark.parametrize over creating separate tests for different input types.
If a fixture is needed for a test but does not return a value, or its value is unused, use @pytest.mark.usefixtures.
When modifying environment variables in a test, use os.environ; tests/conftest.py provides an autouse restore_environ_fixture that restores environment variables after each test, so monkeypatch.setenv is unnecessary.

Files:

  • tests/_utils/utils.py
  • tests/e2e/test_claude.py
  • tests/adapters/test_deepagents.py
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_adapaters_common_hermes.py
  • tests/adapters/test_codex_cli.py
  • tests/python/test_sdk_contract.py
**

⚙️ CodeRabbit configuration file

**:

Contributing to NeMo Fabric

Thank you for your interest in contributing to NeMo Fabric. This guide covers
the development workflow, coding standards, and pull request process.

Development Setup

This section collects the setup steps needed before building, testing, or
contributing changes.

Package Installation

NeMo Fabric is not currently available on PyPI. To consume the Python packages,
build wheels from a source checkout:

just wheels
uv pip install --find-links dist "nemo-fabric[runtime]"

Adapters are distributed as optional extras. For example, install the Hermes
SDK adapter with:

uv pip install --find-links dist "nemo-fabric[adapters-hermes-sdk]"

Refer to the installation guide for the
complete list of adapters and installation options.

Source Development

Install these tools before you start:

  • Rust (stable toolchain) -- install with rustup
  • Python >= 3.11
  • uv -- follow the uv installation guide
  • just >= 1.50.0 -- cargo install just --locked

Clone the repository, create a virtual environment, and build the Rust and
Python packages:

git clone https://github.com/NVIDIA/NeMo-Fabric.git
cd NeMo-Fabric

uv venv --seed .venv --python 3.13
source .venv/bin/activate
uv sync --all-groups --all-extras
just no_uv=true build-all

Verify the checkout by running the test suites described in
Testing Requirements.

Release Tagging

Versioned release tags must use raw Rust-compatible SemVer without a leading
v.

  • Use 0.1.0 for stable releases.
  • Use 0.1.0-rc.1 for prereleases.
  • Do not create tags such as v0.1.0 or v0.1.0-rc.1.

This keeps release tags aligned with Cargo package versions and lets...

Files:

  • tests/_utils/utils.py
  • adapters/hermes-cli/README.md
  • adapters/claude/README.md
  • README.md
  • adapters/hermes-sdk/README.md
  • python/src/nemo_fabric/__init__.py
  • schemas/profile.schema.json
  • docs/reference/api/python-library-reference/index.md
  • adapters/deepagents/README.md
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • tests/e2e/test_claude.py
  • examples/code_review_agent/config.py
  • schemas/agent.schema.json
  • adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py
  • schemas/effective-config.schema.json
  • tests/adapters/test_deepagents.py
  • schemas/run-plan.schema.json
  • tests/adapters/test_claude_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/hermes.py
  • schemas/adapter-invocation.schema.json
  • python/src/nemo_fabric/models.py
  • tests/adapters/test_adapaters_common_hermes.py
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • tests/adapters/test_codex_cli.py
  • python/src/nemo_fabric/types.py
  • tests/python/test_sdk_contract.py
  • docs/reference/api/python-library-reference/nemo_fabric.models.md
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • crates/fabric-core/src/config.rs
{tests/**,python/tests/**}

⚙️ CodeRabbit configuration file

{tests/**,python/tests/**}: Tests should cover the behavior promised by the changed API surface, including error paths, lifecycle cleanup, and SDK/native parity where relevant.

Files:

  • tests/_utils/utils.py
  • tests/e2e/test_claude.py
  • tests/adapters/test_deepagents.py
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_adapaters_common_hermes.py
  • tests/adapters/test_codex_cli.py
  • tests/python/test_sdk_contract.py
{adapters/**,examples/**}

⚙️ CodeRabbit configuration file

{adapters/**,examples/**}: Review adapter and example changes for command correctness, config/schema consistency, artifact handling, and compatibility with the public Fabric contracts.

Files:

  • adapters/hermes-cli/README.md
  • adapters/claude/README.md
  • adapters/hermes-sdk/README.md
  • adapters/deepagents/README.md
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • examples/code_review_agent/config.py
  • adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/hermes.py
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
{docs/**,README.md,AGENTS.md}

⚙️ CodeRabbit configuration file

{docs/**,README.md,AGENTS.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency with generated schemas.

Files:

  • README.md
  • docs/reference/api/python-library-reference/index.md
  • docs/reference/api/python-library-reference/nemo_fabric.models.md
python/src/nemo_fabric/**/*

⚙️ CodeRabbit configuration file

python/src/nemo_fabric/**/*: Review Python SDK changes for typed API consistency, import-time dependency neutrality, async/session behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.

Files:

  • python/src/nemo_fabric/__init__.py
  • python/src/nemo_fabric/models.py
  • python/src/nemo_fabric/types.py
schemas/**/*

⚙️ CodeRabbit configuration file

schemas/**/*: Schemas are generated public contract snapshots. Check that schema diffs correspond to intentional Rust type changes and are covered by core tests.

Files:

  • schemas/profile.schema.json
  • schemas/agent.schema.json
  • schemas/effective-config.schema.json
  • schemas/run-plan.schema.json
  • schemas/adapter-invocation.schema.json
crates/fabric-core/src/**/*.rs

⚙️ CodeRabbit configuration file

crates/fabric-core/src/**/*.rs: Review the Rust core for runtime lifecycle correctness, handle validation, capability routing accuracy, schema stability, and error semantics.
Public API changes should match committed schemas, tests, and documentation.

Files:

  • crates/fabric-core/src/config.rs
🧠 Learnings (2)
📚 Learning: 2026-06-28T04:03:32.877Z
Learnt from: AjayThorve
Repo: NVIDIA/NeMo-Fabric PR: 26
File: python/tests/smoke_typed_config.py:163-177
Timestamp: 2026-06-28T04:03:32.877Z
Learning: In NVIDIA NeMo Fabric Python SDK serialization of `RuntimeCapabilities` (to satisfy the “parity contract” with Rust core and the CLI), do not emit metadata keys when the corresponding metadata is absent. Instead, omit those fields entirely so the produced JSON matches the Rust/CLI output (e.g., avoid `null`, empty objects, or placeholder metadata). During review, verify the serializer/builders follow this omission rule and that Python outputs/parity tests reflect the same shape.

Applied to files:

  • python/src/nemo_fabric/__init__.py
  • python/src/nemo_fabric/models.py
  • python/src/nemo_fabric/types.py
📚 Learning: 2026-07-09T22:28:51.689Z
Learnt from: AjayThorve
Repo: NVIDIA/NeMo-Fabric PR: 43
File: adapters/claude-sdk/src/nemo_fabric_adapters/claude_sdk/adapter.py:164-168
Timestamp: 2026-07-09T22:28:51.689Z
Learning: In the NeMo-Fabric adapters, treat path values used in Fabric adapter configuration (including logic like `_resolve_path` in adapter.py) as config-root-relative. Do not apply `Path.expanduser()` (or otherwise apply `~`/home or shell-style expansion), because it will make the resolved paths normalize inconsistently across adapters. Also, do not rely on or add any resolution behavior that uses `harness.settings.cwd` as an override point for these adapter paths—`harness.settings.cwd` is explicitly unsupported in this adapter context.

Applied to files:

  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
🧬 Code graph analysis (6)
tests/adapters/test_deepagents.py (1)
adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (1)
  • run_deepagents (491-577)
adapters/common/src/nemo_fabric_adapters/common/hermes.py (1)
adapters/common/src/nemo_fabric_adapters/common/utils.py (1)
  • settings_payload (103-105)
tests/adapters/test_adapaters_common_hermes.py (1)
adapters/common/src/nemo_fabric_adapters/common/utils.py (1)
  • relay_enabled (124-125)
python/src/nemo_fabric/types.py (1)
tests/python/test_sdk_contract.py (2)
  • _ResolvedFabricConfig (474-474)
  • from_mapping (79-79)
tests/python/test_sdk_contract.py (2)
python/src/nemo_fabric/types.py (2)
  • from_mapping (648-670)
  • to_mapping (868-875)
python/src/nemo_fabric/models.py (1)
  • to_mapping (426-432)
adapters/common/src/nemo_fabric_adapters/common/utils.py (1)
adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py (1)
  • tools_config (46-46)
🪛 markdownlint-cli2 (0.22.1)
docs/reference/api/python-library-reference/nemo_fabric.models.md

[warning] 1424-1424: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

🪛 Ruff (0.15.20)
tests/adapters/test_deepagents.py

[warning] 465-465: Missing return type annotation for private function handler

Add return type annotation: str

(ANN202)


[warning] 468-468: Missing return type annotation for private function request

(ANN202)

tests/adapters/test_adapaters_common_hermes.py

[warning] 111-111: Boolean-typed positional argument in function definition

(FBT001)

adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py

[warning] 236-236: Dynamically typed expressions (typing.Any) are disallowed in is_blocked

(ANN401)


[warning] 236-236: Dynamically typed expressions (typing.Any) are disallowed in message

(ANN401)


[warning] 236-236: Dynamically typed expressions (typing.Any) are disallowed in _tool_gate_middleware

(ANN401)


[warning] 240-240: Dynamically typed expressions (typing.Any) are disallowed in request

(ANN401)


[warning] 240-240: Dynamically typed expressions (typing.Any) are disallowed in _blocked

(ANN401)


[warning] 249-249: Dynamically typed expressions (typing.Any) are disallowed in request

(ANN401)


[warning] 249-249: Dynamically typed expressions (typing.Any) are disallowed in handler

(ANN401)


[warning] 249-249: Dynamically typed expressions (typing.Any) are disallowed in awrap_tool_call

(ANN401)


[warning] 254-254: Dynamically typed expressions (typing.Any) are disallowed in request

(ANN401)


[warning] 254-254: Dynamically typed expressions (typing.Any) are disallowed in handler

(ANN401)


[warning] 254-254: Dynamically typed expressions (typing.Any) are disallowed in wrap_tool_call

(ANN401)


[warning] 262-262: Dynamically typed expressions (typing.Any) are disallowed in allowed_tools_middleware

(ANN401)


[warning] 277-277: Dynamically typed expressions (typing.Any) are disallowed in blocked_tools_middleware

(ANN401)


[warning] 482-482: Dynamically typed expressions (typing.Any) are disallowed in subagent

(ANN401)


[warning] 482-482: Dynamically typed expressions (typing.Any) are disallowed in _block_subagent

(ANN401)

python/src/nemo_fabric/types.py

[warning] 387-387: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 398-398: Avoid specifying long messages outside the exception class

(TRY003)

adapters/common/src/nemo_fabric_adapters/common/utils.py

[warning] 156-156: Dynamically typed expressions (typing.Any) are disallowed in *values

(ANN401)

🔇 Additional comments (29)
tests/_utils/utils.py (1)

47-47: LGTM!

adapters/hermes-cli/README.md (1)

27-28: LGTM!

tests/adapters/test_codex_cli.py (1)

580-580: LGTM!

python/src/nemo_fabric/types.py (1)

372-415: LGTM!

Also applies to: 610-610, 625-625, 640-640, 691-700, 747-751

tests/python/test_sdk_contract.py (1)

48-50: LGTM!

Also applies to: 146-153, 191-213

docs/reference/api/python-library-reference/nemo_fabric.models.md (1)

1308-1347: LGTM!

Also applies to: 1393-1418, 1549-1568

README.md (1)

139-151: LGTM!

adapters/hermes-sdk/README.md (1)

25-26: LGTM!

adapters/common/src/nemo_fabric_adapters/common/hermes.py (1)

48-53: LGTM!

Also applies to: 66-78, 156-156

tests/adapters/test_adapaters_common_hermes.py (1)

105-113: LGTM!

Also applies to: 146-146, 168-168, 378-378

adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (1)

222-283: LGTM!

Also applies to: 423-441, 482-487

adapters/common/src/nemo_fabric_adapters/common/utils.py (1)

136-162: LGTM!

crates/fabric-core/src/config.rs (1)

55-55: LGTM!

Also applies to: 93-102, 418-426, 1593-1679, 1883-1915, 2030-2073, 2526-2566, 2577-2640

adapters/hermes-sdk/src/nemo_fabric_adapters/hermes_sdk/adapter.py (1)

181-195: 🔒 Security & Privacy

No issue here. tools.blocked is already written into the Hermes config via adapters/common/src/nemo_fabric_adapters/common/hermes.py, so dropping disabled_toolsets from AIAgent(...) only skips an optional constructor override.

			> Likely an incorrect or invalid review comment.
python/src/nemo_fabric/__init__.py (1)

38-38: LGTM!

Also applies to: 79-88, 103-105

adapters/deepagents/README.md (1)

55-57: LGTM!

Also applies to: 72-72, 134-141

tests/e2e/test_claude.py (1)

14-20: LGTM!

Also applies to: 95-98

examples/code_review_agent/config.py (1)

9-9: LGTM!

Also applies to: 18-18, 273-286

schemas/agent.schema.json (1)

915-928: LGTM!

Also applies to: 976-986, 1018-1025

schemas/adapter-invocation.schema.json (1)

111-115: LGTM!

Also applies to: 425-435, 467-474, 1420-1475, 1502-1528, 1543-1543

python/src/nemo_fabric/models.py (1)

397-417: LGTM!

Also applies to: 481-491, 539-540

schemas/profile.schema.json (1)

2-17: LGTM!

Also applies to: 67-74, 107-114

docs/reference/api/python-library-reference/index.md (1)

34-49: LGTM!

adapters/claude/src/nemo_fabric_adapters/claude/adapter.py (2)

14-30: LGTM!

Also applies to: 233-234, 243-249


346-347: 🔒 Security & Privacy

Verify deny-list precedence over allowed_tools.

build_options now passes user-configurable allowed_tools alongside blocked names in disallowed_tools. If the Claude SDK permits overlap or applies the allow-list first, tools.blocked could be bypassed. Reject overlaps, or confirm that disallowed_tools always wins, and add a regression test.

schemas/effective-config.schema.json (1)

131-141: LGTM!

Also applies to: 173-180, 349-919, 1001-1021, 1022-1034

schemas/run-plan.schema.json (1)

240-244: LGTM!

Also applies to: 554-564, 596-603, 795-1365, 1507-1512, 1527-1535, 1560-1560, 1579-1615, 1653-1653

tests/adapters/test_deepagents.py (1)

19-20: LGTM!

Also applies to: 135-136, 281-292, 312-318, 334-334, 494-497

tests/adapters/test_claude_adapter.py (1)

14-22: LGTM!

Also applies to: 129-130, 160-168

Comment thread adapters/claude/README.md Outdated
Comment thread docs/reference/api/python-library-reference/nemo_fabric.models.md
Comment thread tests/adapters/test_deepagents.py Outdated
Comment thread tests/adapters/test_deepagents.py Outdated
Signed-off-by: Anuradha Karuppiah <26330987+AnuradhaKaruppiah@users.noreply.github.com>

# Conflicts:
#	adapters/deepagents/README.md
#	crates/fabric-core/src/config.rs
#	crates/fabric-core/src/lib.rs
#	docs/reference/api/python-library-reference/index.md
#	docs/reference/api/python-library-reference/nemo_fabric.models.md
#	docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitykind.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitytarget.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatifstorageconfig.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointfieldnamepolicy.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointtransport.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofmode.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/enum-relayotlptransport.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/enum-relayunsupportedbehavior.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/fn-load-adapter-descriptor.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/fn-load-fabric-document.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-effective-config-from-config.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-effective-config-with-profiles.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-effective-config.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan-from-config.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan-from-effective-config.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan-with-profiles.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/fn-resolve-run-plan.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/fn-validate-agent-directory.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/index.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/struct-relayatifconfig.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/struct-relayatofconfig.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/struct-relayatofendpointconfig.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/struct-relaycomponentconfig.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/struct-relayconfig.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/struct-relayconfigpolicy.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/struct-relayobservabilityconfig.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/struct-relayotlpconfig.mdx
#	docs/reference/api/rust-library-reference/fabric-core/config/struct-telemetryproviderconfig.mdx
#	docs/reference/api/rust-library-reference/fabric-core/doctor/enum-doctorstatus.mdx
#	docs/reference/api/rust-library-reference/fabric-core/doctor/fn-doctor-plan.mdx
#	docs/reference/api/rust-library-reference/fabric-core/doctor/index.mdx
#	docs/reference/api/rust-library-reference/fabric-core/doctor/struct-doctorcheck.mdx
#	docs/reference/api/rust-library-reference/fabric-core/doctor/struct-doctorreport.mdx
#	docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
#	docs/reference/api/rust-library-reference/fabric-core/error/index.mdx
#	docs/reference/api/rust-library-reference/fabric-core/error/type-result.mdx
#	docs/reference/api/rust-library-reference/fabric-core/fn-version.mdx
#	docs/reference/api/rust-library-reference/fabric-core/runtime/index.mdx
#	docs/reference/api/rust-library-reference/fabric-core/schema/index.mdx
#	examples/code_review_agent/config.py
#	python/src/nemo_fabric/__init__.py
#	python/src/nemo_fabric/models.py
#	python/src/nemo_fabric/types.py
#	schemas/adapter-invocation.schema.json
#	schemas/agent.schema.json
#	schemas/effective-config.schema.json
#	schemas/run-plan.schema.json
#	tests/_utils/utils.py
#	tests/adapters/test_adapaters_common_hermes.py
#	tests/python/test_sdk_contract.py

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (4)
crates/fabric-core/src/config.rs (1)

1607-1619: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve policy-presence semantics for tools_configured.

tools: { blocked: [] } provides a tool policy, but this change reports capability_plan.tools_configured == false. Keep the top-level flag based on config.tools.is_some(); target routing may still remain disabled when the deny-list is empty. Otherwise consumers cannot distinguish an omitted policy from an explicitly empty one.

As per path instructions, capability_plan.tools_configured indicates whether tool config was provided.

Also applies to: 1690-1693, 2708-2772

🤖 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/fabric-core/src/config.rs` around lines 1607 - 1619, Update the
tools_configured assignment in the capability-plan construction to use
config.tools.is_some(), preserving true for an explicitly provided empty blocked
list while remaining false when tools is omitted. Keep the existing
blocked_tools-based checks for target routing and native/unsupported handling
unchanged, including the related logic in the capability-plan paths around
tools_configured.

Source: Path instructions

python/src/nemo_fabric/models.py (1)

417-417: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Remove the raw dict fallback from tools
FabricBaseModel(extra="allow") already preserves unknown ToolsConfig fields, so ToolsConfig | dict[str, Any] | None only bypasses validation for known keys like blocked and can leak malformed configs into to_mapping(). Make both tools fields ToolsConfig | None.

🤖 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 `@python/src/nemo_fabric/models.py` at line 417, Update both tools field
declarations in the relevant model definitions to use ToolsConfig | None,
removing the raw dict[str, Any] fallback. Preserve the existing optional
behavior and rely on FabricBaseModel extra-field handling for unknown
ToolsConfig fields so known fields remain validated before to_mapping().

Source: Path instructions

adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (1)

408-429: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Propagate blocked-tool middleware to delegated subagents (adapter.py:422-428)
blocked_tools_middleware(blocked) is attached only to the parent agent here, and _block_subagent() rewrites only explicit dict entries. The built-in task subagent has its own middleware stack, so blocked tools can still be reached through delegation unless that path is gated too.

🤖 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 `@adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py` around
lines 408 - 429, Update the blocked-tools handling in the adapter configuration
flow to propagate the blocked middleware to the built-in task/delegated subagent
path, not only the parent middleware and explicit dictionary subagents. Extend
or reuse _block_subagent so every delegated subagent receives the same blocked
set while preserving existing behavior for parent middleware and non-subagent
configuration values.
tests/adapters/test_claude_adapter.py (1)

152-159: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Cover the rest of the options contract here (tests/adapters/test_claude_adapter.py:152) — assert options.allowed_tools == ["Read"], and add a duplicate in blocked if this test should also pin the order-preserving dedup behavior of disallowed_tools.

🤖 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 `@tests/adapters/test_claude_adapter.py` around lines 152 - 159, Extend
test_build_options_maps_blocked_tools_to_disallowed_tools to assert
options.allowed_tools equals ["Read"] alongside the existing disallowed-tools
assertions. Add a duplicate blocked tool only if this test is intended to verify
order-preserving deduplication, and assert the resulting disallowed_tools
contains each tool once in its original order.
🤖 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 `@schemas/run-plan.schema.json`:
- Around line 193-199: Update the Rust type/schema source defining telemetry
providers so the generated schema restricts telemetry.providers keys to the
TelemetryProvider enum values relay and native instead of allowing arbitrary
keys. Regenerate schemas/run-plan.schema.json from that intentional type change,
preserving AdapterTelemetryProviderSupport as the value schema and ensuring core
deserialization accepts every schema-valid provider.

In `@tests/adapters/test_adapaters_common_hermes.py`:
- Around line 105-116: Consolidate
test_validate_hermes_telemetry_provider_rejects_native and
test_validate_hermes_telemetry_provider_rejects_mixed_native_and_relay into one
pytest.mark.parametrize test, parameterizing the differing telemetry_plan
payloads while preserving the shared ValueError match assertion.

---

Outside diff comments:
In `@adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py`:
- Around line 408-429: Update the blocked-tools handling in the adapter
configuration flow to propagate the blocked middleware to the built-in
task/delegated subagent path, not only the parent middleware and explicit
dictionary subagents. Extend or reuse _block_subagent so every delegated
subagent receives the same blocked set while preserving existing behavior for
parent middleware and non-subagent configuration values.

In `@crates/fabric-core/src/config.rs`:
- Around line 1607-1619: Update the tools_configured assignment in the
capability-plan construction to use config.tools.is_some(), preserving true for
an explicitly provided empty blocked list while remaining false when tools is
omitted. Keep the existing blocked_tools-based checks for target routing and
native/unsupported handling unchanged, including the related logic in the
capability-plan paths around tools_configured.

In `@python/src/nemo_fabric/models.py`:
- Line 417: Update both tools field declarations in the relevant model
definitions to use ToolsConfig | None, removing the raw dict[str, Any] fallback.
Preserve the existing optional behavior and rely on FabricBaseModel extra-field
handling for unknown ToolsConfig fields so known fields remain validated before
to_mapping().

In `@tests/adapters/test_claude_adapter.py`:
- Around line 152-159: Extend
test_build_options_maps_blocked_tools_to_disallowed_tools to assert
options.allowed_tools equals ["Read"] alongside the existing disallowed-tools
assertions. Add a duplicate blocked tool only if this test is intended to verify
order-preserving deduplication, and assert the resulting disallowed_tools
contains each tool once in its original order.
🪄 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: 2f990cab-e9df-4985-b18b-8812de0ce66a

📥 Commits

Reviewing files that changed from the base of the PR and between 30bf20c and 6853d16.

📒 Files selected for processing (28)
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/deepagents/README.md
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/hermes-cli/README.md
  • adapters/hermes-sdk/README.md
  • crates/fabric-core/src/config.rs
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitykind.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitytarget.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatifstorageconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointfieldnamepolicy.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointtransport.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofmode.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayotlptransport.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayunsupportedbehavior.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-capabilityplan.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-fabricconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-toolsconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-toolsplan.mdx
  • python/src/nemo_fabric/models.py
  • python/src/nemo_fabric/types.py
  • schemas/run-plan.schema.json
  • tests/adapters/test_adapaters_common_hermes.py
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_deepagents.py
  • tests/e2e/test_claude.py
  • tests/python/test_sdk_contract.py
📜 Review details
⚠️ CI failures not shown inline (10)

GitHub Actions: Python / Build wheels (x86_64): feat(tools): add blocked tools policy

Conclusion: failure

View job details

##[group]Run bail() {
 �[36;1mbail() {�[0m
 �[36;1m  printf '::error::install-action: %s\n' "$*"�[0m

GitHub Actions: Python / Test (arm64): feat(tools): add blocked tools policy

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mjust test-python�[0m
 shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
 env:
   CARGO_INCREMENTAL: 0
   CARGO_PROFILE_DEV_DEBUG: 0
   CARGO_TERM_COLOR: always
   RUST_BACKTRACE: short
   RUSTFLAGS: -D warnings
   CARGO_UNSTABLE_SPARSE_REGISTRY: true
   CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
   UV_PYTHON_INSTALL_DIR: /home/runner/work/_temp/uv-python-dir
   UV_CACHE_DIR: /home/runner/work/_temp/setup-uv-cache
   CACHE_ON_FAILURE: false
 ##[endgroup]
 Resolved 193 packages in 2ms
 Checked 162 packages in 1ms
 ============================= test session starts ==============================
 platform linux -- Python 3.12.3, pytest-9.1.1, pluggy-1.6.0
 rootdir: /home/runner/work/NeMo-Fabric/NeMo-Fabric
 configfile: pyproject.toml
 plugins: cov-7.1.0, asyncio-1.4.0, langsmith-0.10.1, anyio-4.14.0
 asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=session, asyncio_default_test_loop_scope=function
 collected 305 items
 tests/adapters/test_adapaters_common_hermes.py ......................... [  8%]
 ......                                                                   [ 10%]
 tests/adapters/test_adapaters_common_utils.py .....................      [ 17%]
 tests/adapters/test_claude_adapter.py ...........................        [ 25%]
 tests/adapters/test_codex_cli.py .................F.................     [ 37%]
 tests/adapters/test_deepagents.py ................................       [ 47%]
 tests/adapters/test_hermes_cli.py ...                                    [ 48%]
 tests/adapters/test_hermes_cli_preflight.py ..                           [ 49%]
 tests/adapters/test_hermes_sdk_adapter.py ..                             [ 50%]
 tests/docs/test_python_api_docs.py ....                                  [ 51%]
 tests/e2e/test_claude.py .s                                              [ 52%]
 tests/e2e/test_cli.py .                                                  [...

GitHub Actions: Python / Test (x86_64): feat(tools): add blocked tools policy

Conclusion: failure

View job details

##[group]Run set -euo pipefail
 �[36;1mset -euo pipefail�[0m
 �[36;1mjust test-python�[0m
 shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
 env:
   CARGO_INCREMENTAL: 0
   CARGO_PROFILE_DEV_DEBUG: 0
   CARGO_TERM_COLOR: always
   RUST_BACKTRACE: short
   RUSTFLAGS: -D warnings
   CARGO_UNSTABLE_SPARSE_REGISTRY: true
   CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
   UV_PYTHON_INSTALL_DIR: /home/runner/work/_temp/uv-python-dir
   UV_CACHE_DIR: /home/runner/work/_temp/setup-uv-cache
   CACHE_ON_FAILURE: false
 ##[endgroup]
 Resolved 193 packages in 3ms
 Checked 162 packages in 2ms
 ============================= test session starts ==============================
 platform linux -- Python 3.12.3, pytest-9.1.1, pluggy-1.6.0
 rootdir: /home/runner/work/NeMo-Fabric/NeMo-Fabric
 configfile: pyproject.toml
 plugins: asyncio-1.4.0, anyio-4.14.0, cov-7.1.0, langsmith-0.10.1
 asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=session, asyncio_default_test_loop_scope=function
 collected 305 items
 tests/adapters/test_adapaters_common_hermes.py ......................... [  8%]
 ......                                                                   [ 10%]
 tests/adapters/test_adapaters_common_utils.py .....................      [ 17%]
 tests/adapters/test_claude_adapter.py ...........................        [ 25%]
 tests/adapters/test_codex_cli.py .................F.................     [ 37%]
 tests/adapters/test_deepagents.py ................................       [ 47%]
 tests/adapters/test_hermes_cli.py ...                                    [ 48%]
 tests/adapters/test_hermes_cli_preflight.py ..                           [ 49%]
 tests/adapters/test_hermes_sdk_adapter.py ..                             [ 50%]
 tests/docs/test_python_api_docs.py ....                                  [ 51%]
 tests/e2e/test_claude.py .s                                              [ 52%]
 tests/e2e/test_cli.py .                                                  [...

GitHub Actions: Python / Test (arm64): feat(tools): add blocked tools policy

Conclusion: failure

View job details

##[group]Run bail() {
 �[36;1mbail() {�[0m
 �[36;1m  printf '::error::install-action: %s\n' "$*"�[0m

GitHub Actions: Python / 2_Test (x86_64).txt: feat(tools): add blocked tools policy

Conclusion: failure

View job details

##[group]Run bail() {
 �[36;1mbail() {�[0m
 �[36;1m  printf '::error::install-action: %s\n' "$*"�[0m

GitHub Actions: Python / Build wheels (arm64): feat(tools): add blocked tools policy

Conclusion: failure

View job details

##[group]Run bail() {
 �[36;1mbail() {�[0m
 �[36;1m  printf '::error::install-action: %s\n' "$*"�[0m

GitHub Actions: Python / 1_Test (arm64).txt: feat(tools): add blocked tools policy

Conclusion: failure

View job details

##[group]Run bail() {
 �[36;1mbail() {�[0m
 �[36;1m  printf '::error::install-action: %s\n' "$*"�[0m

GitHub Actions: Python / Test (x86_64): feat(tools): add blocked tools policy

Conclusion: failure

View job details

##[group]Run bail() {
 �[36;1mbail() {�[0m
 �[36;1m  printf '::error::install-action: %s\n' "$*"�[0m

GitHub Actions: Python / 3_Build wheels (arm64).txt: feat(tools): add blocked tools policy

Conclusion: failure

View job details

##[group]Run bail() {
 �[36;1mbail() {�[0m
 �[36;1m  printf '::error::install-action: %s\n' "$*"�[0m

GitHub Actions: Python / 0_Build wheels (x86_64).txt: feat(tools): add blocked tools policy

Conclusion: failure

View job details

##[group]Run bail() {
 �[36;1mbail() {�[0m
 �[36;1m  printf '::error::install-action: %s\n' "$*"�[0m
🧰 Additional context used
📓 Path-based instructions (7)
{adapters/**,examples/**}

⚙️ CodeRabbit configuration file

{adapters/**,examples/**}: Review adapter and example changes for command correctness, config/schema consistency, artifact handling, and compatibility with the public Fabric contracts.

Files:

  • adapters/hermes-sdk/README.md
  • adapters/hermes-cli/README.md
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/deepagents/README.md
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
{docs/**,README.md,AGENTS.md}

⚙️ CodeRabbit configuration file

{docs/**,README.md,AGENTS.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency with generated schemas.

Files:

  • docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitykind.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitytarget.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointfieldnamepolicy.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatifstorageconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayunsupportedbehavior.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-capabilityplan.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-toolsconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-toolsplan.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointtransport.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofmode.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-fabricconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayotlptransport.mdx
tests/**/*.py

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

tests/**/*.py: Use pytest to run Python tests.
Do not add @pytest.mark.asyncio to test functions; async tests are detected and run automatically.
Do not add -> None return type annotations to test functions.
When mocking a class, do not define a new class; use unittest.mock.MagicMock or unittest.mock.AsyncMock, adding spec when needed.
Name mocked classes with a mock prefix, not fake.
Prefer pytest fixtures over helper methods.
Do not duplicate fixtures across test files; if a fixture is needed in multiple test files, define it in conftest.py.
When creating a fixture, use @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) and define the function as <fixture_name>_fixture() -> <return_type>; only pass scope when it is not function.
Prefer pytest.mark.parametrize over creating separate tests for different input types.
If a fixture is needed for a test but does not return a value, or its value is unused, use @pytest.mark.usefixtures.
When modifying environment variables in a test, use os.environ; tests/conftest.py provides an autouse restore_environ_fixture that restores environment variables after each test, so monkeypatch.setenv is unnecessary.

Files:

  • tests/e2e/test_claude.py
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_adapaters_common_hermes.py
  • tests/adapters/test_deepagents.py
  • tests/python/test_sdk_contract.py
{tests/**,python/tests/**}

⚙️ CodeRabbit configuration file

{tests/**,python/tests/**}: Tests should cover the behavior promised by the changed API surface, including error paths, lifecycle cleanup, and SDK/native parity where relevant.

Files:

  • tests/e2e/test_claude.py
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_adapaters_common_hermes.py
  • tests/adapters/test_deepagents.py
  • tests/python/test_sdk_contract.py
schemas/**/*

⚙️ CodeRabbit configuration file

schemas/**/*: Schemas are generated public contract snapshots. Check that schema diffs correspond to intentional Rust type changes and are covered by core tests.

Files:

  • schemas/run-plan.schema.json
python/src/nemo_fabric/**/*

⚙️ CodeRabbit configuration file

python/src/nemo_fabric/**/*: Review Python SDK changes for typed API consistency, import-time dependency neutrality, async/session behavior, and parity with the native extension.
Stubs and runtime implementations should stay aligned.

Files:

  • python/src/nemo_fabric/models.py
  • python/src/nemo_fabric/types.py
crates/fabric-core/src/**/*.rs

⚙️ CodeRabbit configuration file

crates/fabric-core/src/**/*.rs: Review the Rust core for runtime lifecycle correctness, handle validation, capability routing accuracy, schema stability, and error semantics.
Public API changes should match committed schemas, tests, and documentation.

Files:

  • crates/fabric-core/src/config.rs
🧠 Learnings (2)
📚 Learning: 2026-07-09T22:28:51.689Z
Learnt from: AjayThorve
Repo: NVIDIA/NeMo-Fabric PR: 43
File: adapters/claude-sdk/src/nemo_fabric_adapters/claude_sdk/adapter.py:164-168
Timestamp: 2026-07-09T22:28:51.689Z
Learning: In the NeMo-Fabric adapters, treat path values used in Fabric adapter configuration (including logic like `_resolve_path` in adapter.py) as config-root-relative. Do not apply `Path.expanduser()` (or otherwise apply `~`/home or shell-style expansion), because it will make the resolved paths normalize inconsistently across adapters. Also, do not rely on or add any resolution behavior that uses `harness.settings.cwd` as an override point for these adapter paths—`harness.settings.cwd` is explicitly unsupported in this adapter context.

Applied to files:

  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
📚 Learning: 2026-06-28T04:03:32.877Z
Learnt from: AjayThorve
Repo: NVIDIA/NeMo-Fabric PR: 26
File: python/tests/smoke_typed_config.py:163-177
Timestamp: 2026-06-28T04:03:32.877Z
Learning: In NVIDIA NeMo Fabric Python SDK serialization of `RuntimeCapabilities` (to satisfy the “parity contract” with Rust core and the CLI), do not emit metadata keys when the corresponding metadata is absent. Instead, omit those fields entirely so the produced JSON matches the Rust/CLI output (e.g., avoid `null`, empty objects, or placeholder metadata). During review, verify the serializer/builders follow this omission rule and that Python outputs/parity tests reflect the same shape.

Applied to files:

  • python/src/nemo_fabric/models.py
  • python/src/nemo_fabric/types.py
🧬 Code graph analysis (4)
adapters/claude/src/nemo_fabric_adapters/claude/adapter.py (1)
adapters/common/src/nemo_fabric_adapters/common/utils.py (2)
  • load_payload (69-75)
  • capability_plan (131-132)
tests/adapters/test_adapaters_common_hermes.py (1)
adapters/common/src/nemo_fabric_adapters/common/hermes.py (1)
  • validate_hermes_telemetry_provider (43-46)
tests/python/test_sdk_contract.py (1)
python/src/nemo_fabric/types.py (1)
  • to_mapping (866-873)
python/src/nemo_fabric/types.py (1)
tests/python/test_sdk_contract.py (1)
  • _ToolsConfig (214-214)
🪛 Ruff (0.15.21)
adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py

[warning] 72-72: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 318-318: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 395-395: Dynamically typed expressions (typing.Any) are disallowed in model

(ANN401)

adapters/claude/src/nemo_fabric_adapters/claude/adapter.py

[warning] 538-538: Do not catch blind exception: Exception

(BLE001)

🔇 Additional comments (33)
python/src/nemo_fabric/models.py (1)

360-388: LGTM!

Also applies to: 400-400, 481-525

python/src/nemo_fabric/types.py (1)

372-410: LGTM!

Also applies to: 479-550, 594-642, 696-698, 745-775

schemas/run-plan.schema.json (1)

261-265: LGTM!

Also applies to: 616-624, 1611-1636

crates/fabric-core/src/config.rs (1)

55-55: LGTM!

Also applies to: 374-395, 432-432, 1323-1323, 1710-1764, 1921-1921, 1950-1950, 2066-2109, 2152-2154, 2184-2186, 2240-2242, 2290-2404, 2657-2687

docs/reference/api/rust-library-reference/fabric-core/config/struct-toolsconfig.mdx (1)

1-107: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/struct-toolsplan.mdx (1)

1-103: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitykind.mdx (1)

5-5: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitytarget.mdx (1)

5-5: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatifstorageconfig.mdx (1)

5-5: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointfieldnamepolicy.mdx (1)

5-5: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointtransport.mdx (1)

5-5: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/struct-fabricconfig.mdx (1)

12-12: LGTM!

Also applies to: 42-42, 58-61

docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofmode.mdx (1)

5-5: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/enum-relayotlptransport.mdx (1)

5-5: LGTM!

Also applies to: 21-124

docs/reference/api/rust-library-reference/fabric-core/config/enum-relayunsupportedbehavior.mdx (1)

5-5: LGTM!

Also applies to: 22-130

docs/reference/api/rust-library-reference/fabric-core/config/index.mdx (1)

53-54: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/struct-capabilityplan.mdx (1)

5-5: LGTM!

Also applies to: 12-20

adapters/deepagents/README.md (1)

55-57: 📐 Maintainability & Code Quality

Cross-check this "delegated subagents alike" guarantee against the general-purpose subagent case.

This documents tools.blocked as enforced across "delegated subagents alike," but the adapter's _block_subagent helper (per the change summary) only rewrites dict-form entries in the explicit subagents list. See the companion comment on adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (lines 408-429) regarding whether the built-in, auto-injected general-purpose subagent inherits the parent's blocking middleware. If it doesn't, this documentation overstates the guarantee for that path.

Also applies to: 68-73

adapters/claude/src/nemo_fabric_adapters/claude/adapter.py (2)

211-230: Blocked-dict short-circuit looks correct.

Returning None from _normalized_tools when tools is a dict with "blocked" correctly defers restriction to _disallowed_tools/disallowed_tools, matching the adapter-invocation schema's ToolsConfig shape and the PR's Claude mapping (blocked → disallowed_tools).


102-107: LGTM!

Also applies to: 187-208, 240-245, 263-263, 302-302, 375-378, 413-415, 485-493, 524-539

adapters/common/src/nemo_fabric_adapters/common/utils.py (1)

47-47: LGTM!

adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (2)

210-224: Blocked-dict short-circuit for _allowed_tool_names is consistent with the Claude adapter's equivalent logic.


69-73: LGTM!

Also applies to: 127-132, 315-320, 352-357, 362-367, 394-397, 441-445, 519-526

adapters/hermes-cli/README.md (1)

27-29: LGTM!

adapters/hermes-sdk/README.md (1)

25-27: LGTM!

tests/adapters/test_deepagents.py (3)

450-470: 🎯 Functional Correctness

Confirm blocked-tool middleware tests assert actual blocking, not just presence.

A prior review flagged that these tests (test_blocked_tools_middleware_blocks_configured_tools, test_subagents_are_gated_by_blocked_tools) risk passing even with unrelated middleware if they only check for non-empty middleware lists. These bodies weren't in the reviewed snippet, so please confirm the assertions actually invoke the gate (e.g., blocked tool call returns an error ToolMessage, allowed tool executes) for both the main agent and subagents[0]["middleware"].

#!/bin/bash
sed -n '440,475p;635,675p' tests/adapters/test_deepagents.py

Also applies to: 641-671


19-20: LGTM!

Also applies to: 135-136, 276-276, 304-304, 356-356, 372-372, 494-497, 761-761, 785-785


272-301: LGTM!

Also applies to: 304-344

tests/adapters/test_adapaters_common_hermes.py (1)

146-168: LGTM!

Also applies to: 378-378, 382-444, 447-448

tests/adapters/test_claude_adapter.py (1)

26-26: LGTM!

Also applies to: 121-122, 171-171, 303-303

tests/e2e/test_claude.py (1)

14-20: LGTM!

Also applies to: 51-51, 62-63, 86-93, 111-111

tests/python/test_sdk_contract.py (2)

890-900: LGTM!

Also applies to: 926-935


277-299: 🗄️ Data Integrity & Integration

No change needed: enable_relay() preserves omitted fields and only updates explicitly provided values.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (4)
crates/fabric-core/src/config.rs (1)

1607-1619: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve policy-presence semantics for tools_configured.

tools: { blocked: [] } provides a tool policy, but this change reports capability_plan.tools_configured == false. Keep the top-level flag based on config.tools.is_some(); target routing may still remain disabled when the deny-list is empty. Otherwise consumers cannot distinguish an omitted policy from an explicitly empty one.

As per path instructions, capability_plan.tools_configured indicates whether tool config was provided.

Also applies to: 1690-1693, 2708-2772

🤖 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/fabric-core/src/config.rs` around lines 1607 - 1619, Update the
tools_configured assignment in the capability-plan construction to use
config.tools.is_some(), preserving true for an explicitly provided empty blocked
list while remaining false when tools is omitted. Keep the existing
blocked_tools-based checks for target routing and native/unsupported handling
unchanged, including the related logic in the capability-plan paths around
tools_configured.

Source: Path instructions

python/src/nemo_fabric/models.py (1)

417-417: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Remove the raw dict fallback from tools
FabricBaseModel(extra="allow") already preserves unknown ToolsConfig fields, so ToolsConfig | dict[str, Any] | None only bypasses validation for known keys like blocked and can leak malformed configs into to_mapping(). Make both tools fields ToolsConfig | None.

🤖 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 `@python/src/nemo_fabric/models.py` at line 417, Update both tools field
declarations in the relevant model definitions to use ToolsConfig | None,
removing the raw dict[str, Any] fallback. Preserve the existing optional
behavior and rely on FabricBaseModel extra-field handling for unknown
ToolsConfig fields so known fields remain validated before to_mapping().

Source: Path instructions

adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (1)

408-429: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Propagate blocked-tool middleware to delegated subagents (adapter.py:422-428)
blocked_tools_middleware(blocked) is attached only to the parent agent here, and _block_subagent() rewrites only explicit dict entries. The built-in task subagent has its own middleware stack, so blocked tools can still be reached through delegation unless that path is gated too.

🤖 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 `@adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py` around
lines 408 - 429, Update the blocked-tools handling in the adapter configuration
flow to propagate the blocked middleware to the built-in task/delegated subagent
path, not only the parent middleware and explicit dictionary subagents. Extend
or reuse _block_subagent so every delegated subagent receives the same blocked
set while preserving existing behavior for parent middleware and non-subagent
configuration values.
tests/adapters/test_claude_adapter.py (1)

152-159: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Cover the rest of the options contract here (tests/adapters/test_claude_adapter.py:152) — assert options.allowed_tools == ["Read"], and add a duplicate in blocked if this test should also pin the order-preserving dedup behavior of disallowed_tools.

🤖 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 `@tests/adapters/test_claude_adapter.py` around lines 152 - 159, Extend
test_build_options_maps_blocked_tools_to_disallowed_tools to assert
options.allowed_tools equals ["Read"] alongside the existing disallowed-tools
assertions. Add a duplicate blocked tool only if this test is intended to verify
order-preserving deduplication, and assert the resulting disallowed_tools
contains each tool once in its original order.
🤖 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 `@schemas/run-plan.schema.json`:
- Around line 193-199: Update the Rust type/schema source defining telemetry
providers so the generated schema restricts telemetry.providers keys to the
TelemetryProvider enum values relay and native instead of allowing arbitrary
keys. Regenerate schemas/run-plan.schema.json from that intentional type change,
preserving AdapterTelemetryProviderSupport as the value schema and ensuring core
deserialization accepts every schema-valid provider.

In `@tests/adapters/test_adapaters_common_hermes.py`:
- Around line 105-116: Consolidate
test_validate_hermes_telemetry_provider_rejects_native and
test_validate_hermes_telemetry_provider_rejects_mixed_native_and_relay into one
pytest.mark.parametrize test, parameterizing the differing telemetry_plan
payloads while preserving the shared ValueError match assertion.

---

Outside diff comments:
In `@adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py`:
- Around line 408-429: Update the blocked-tools handling in the adapter
configuration flow to propagate the blocked middleware to the built-in
task/delegated subagent path, not only the parent middleware and explicit
dictionary subagents. Extend or reuse _block_subagent so every delegated
subagent receives the same blocked set while preserving existing behavior for
parent middleware and non-subagent configuration values.

In `@crates/fabric-core/src/config.rs`:
- Around line 1607-1619: Update the tools_configured assignment in the
capability-plan construction to use config.tools.is_some(), preserving true for
an explicitly provided empty blocked list while remaining false when tools is
omitted. Keep the existing blocked_tools-based checks for target routing and
native/unsupported handling unchanged, including the related logic in the
capability-plan paths around tools_configured.

In `@python/src/nemo_fabric/models.py`:
- Line 417: Update both tools field declarations in the relevant model
definitions to use ToolsConfig | None, removing the raw dict[str, Any] fallback.
Preserve the existing optional behavior and rely on FabricBaseModel extra-field
handling for unknown ToolsConfig fields so known fields remain validated before
to_mapping().

In `@tests/adapters/test_claude_adapter.py`:
- Around line 152-159: Extend
test_build_options_maps_blocked_tools_to_disallowed_tools to assert
options.allowed_tools equals ["Read"] alongside the existing disallowed-tools
assertions. Add a duplicate blocked tool only if this test is intended to verify
order-preserving deduplication, and assert the resulting disallowed_tools
contains each tool once in its original order.
🪄 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: 2f990cab-e9df-4985-b18b-8812de0ce66a

📥 Commits

Reviewing files that changed from the base of the PR and between 30bf20c and 6853d16.

📒 Files selected for processing (28)
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/deepagents/README.md
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/hermes-cli/README.md
  • adapters/hermes-sdk/README.md
  • crates/fabric-core/src/config.rs
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitykind.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitytarget.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatifstorageconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointfieldnamepolicy.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointtransport.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofmode.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayotlptransport.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/enum-relayunsupportedbehavior.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/index.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-capabilityplan.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-fabricconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-toolsconfig.mdx
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-toolsplan.mdx
  • python/src/nemo_fabric/models.py
  • python/src/nemo_fabric/types.py
  • schemas/run-plan.schema.json
  • tests/adapters/test_adapaters_common_hermes.py
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_deepagents.py
  • tests/e2e/test_claude.py
  • tests/python/test_sdk_contract.py
📜 Review details
🔇 Additional comments (33)
python/src/nemo_fabric/models.py (1)

360-388: LGTM!

Also applies to: 400-400, 481-525

python/src/nemo_fabric/types.py (1)

372-410: LGTM!

Also applies to: 479-550, 594-642, 696-698, 745-775

schemas/run-plan.schema.json (1)

261-265: LGTM!

Also applies to: 616-624, 1611-1636

crates/fabric-core/src/config.rs (1)

55-55: LGTM!

Also applies to: 374-395, 432-432, 1323-1323, 1710-1764, 1921-1921, 1950-1950, 2066-2109, 2152-2154, 2184-2186, 2240-2242, 2290-2404, 2657-2687

docs/reference/api/rust-library-reference/fabric-core/config/struct-toolsconfig.mdx (1)

1-107: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/struct-toolsplan.mdx (1)

1-103: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitykind.mdx (1)

5-5: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/enum-capabilitytarget.mdx (1)

5-5: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatifstorageconfig.mdx (1)

5-5: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointfieldnamepolicy.mdx (1)

5-5: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofendpointtransport.mdx (1)

5-5: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/struct-fabricconfig.mdx (1)

12-12: LGTM!

Also applies to: 42-42, 58-61

docs/reference/api/rust-library-reference/fabric-core/config/enum-relayatofmode.mdx (1)

5-5: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/enum-relayotlptransport.mdx (1)

5-5: LGTM!

Also applies to: 21-124

docs/reference/api/rust-library-reference/fabric-core/config/enum-relayunsupportedbehavior.mdx (1)

5-5: LGTM!

Also applies to: 22-130

docs/reference/api/rust-library-reference/fabric-core/config/index.mdx (1)

53-54: LGTM!

docs/reference/api/rust-library-reference/fabric-core/config/struct-capabilityplan.mdx (1)

5-5: LGTM!

Also applies to: 12-20

adapters/deepagents/README.md (1)

55-57: 📐 Maintainability & Code Quality

Cross-check this "delegated subagents alike" guarantee against the general-purpose subagent case.

This documents tools.blocked as enforced across "delegated subagents alike," but the adapter's _block_subagent helper (per the change summary) only rewrites dict-form entries in the explicit subagents list. See the companion comment on adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (lines 408-429) regarding whether the built-in, auto-injected general-purpose subagent inherits the parent's blocking middleware. If it doesn't, this documentation overstates the guarantee for that path.

Also applies to: 68-73

adapters/claude/src/nemo_fabric_adapters/claude/adapter.py (2)

211-230: Blocked-dict short-circuit looks correct.

Returning None from _normalized_tools when tools is a dict with "blocked" correctly defers restriction to _disallowed_tools/disallowed_tools, matching the adapter-invocation schema's ToolsConfig shape and the PR's Claude mapping (blocked → disallowed_tools).


102-107: LGTM!

Also applies to: 187-208, 240-245, 263-263, 302-302, 375-378, 413-415, 485-493, 524-539

adapters/common/src/nemo_fabric_adapters/common/utils.py (1)

47-47: LGTM!

adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (2)

210-224: Blocked-dict short-circuit for _allowed_tool_names is consistent with the Claude adapter's equivalent logic.


69-73: LGTM!

Also applies to: 127-132, 315-320, 352-357, 362-367, 394-397, 441-445, 519-526

adapters/hermes-cli/README.md (1)

27-29: LGTM!

adapters/hermes-sdk/README.md (1)

25-27: LGTM!

tests/adapters/test_deepagents.py (3)

450-470: 🎯 Functional Correctness

Confirm blocked-tool middleware tests assert actual blocking, not just presence.

A prior review flagged that these tests (test_blocked_tools_middleware_blocks_configured_tools, test_subagents_are_gated_by_blocked_tools) risk passing even with unrelated middleware if they only check for non-empty middleware lists. These bodies weren't in the reviewed snippet, so please confirm the assertions actually invoke the gate (e.g., blocked tool call returns an error ToolMessage, allowed tool executes) for both the main agent and subagents[0]["middleware"].

#!/bin/bash
sed -n '440,475p;635,675p' tests/adapters/test_deepagents.py

Also applies to: 641-671


19-20: LGTM!

Also applies to: 135-136, 276-276, 304-304, 356-356, 372-372, 494-497, 761-761, 785-785


272-301: LGTM!

Also applies to: 304-344

tests/adapters/test_adapaters_common_hermes.py (1)

146-168: LGTM!

Also applies to: 378-378, 382-444, 447-448

tests/adapters/test_claude_adapter.py (1)

26-26: LGTM!

Also applies to: 121-122, 171-171, 303-303

tests/e2e/test_claude.py (1)

14-20: LGTM!

Also applies to: 51-51, 62-63, 86-93, 111-111

tests/python/test_sdk_contract.py (2)

890-900: LGTM!

Also applies to: 926-935


277-299: 🗄️ Data Integrity & Integration

No change needed: enable_relay() preserves omitted fields and only updates explicitly provided values.

🛑 Comments failed to post (2)
schemas/run-plan.schema.json (1)

193-199: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Constrain telemetry provider keys in the public schema.

This schema accepts arbitrary telemetry.providers keys, but core deserialization rejects providers outside relay and native. A schema-valid adapter descriptor can therefore fail at runtime. Generate a schema that restricts provider names to the Rust TelemetryProvider enum.

As per path instructions, generated schemas are public contract snapshots and must correspond to intentional Rust type changes.

🤖 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 `@schemas/run-plan.schema.json` around lines 193 - 199, Update the Rust
type/schema source defining telemetry providers so the generated schema
restricts telemetry.providers keys to the TelemetryProvider enum values relay
and native instead of allowing arbitrary keys. Regenerate
schemas/run-plan.schema.json from that intentional type change, preserving
AdapterTelemetryProviderSupport as the value schema and ensuring core
deserialization accepts every schema-valid provider.

Source: Path instructions

tests/adapters/test_adapaters_common_hermes.py (1)

105-116: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Re-merge these reject tests into one parametrize.

This duplicates a previously flagged (and reportedly addressed) issue: test_validate_hermes_telemetry_provider_rejects_native and test_validate_hermes_telemetry_provider_rejects_mixed_native_and_relay differ only by the providers/relay_enabled payload and assert the identical error.

♻️ Proposed consolidation
-def test_validate_hermes_telemetry_provider_rejects_native():
-    payload = {"telemetry_plan": {"providers": ["native"], "relay_enabled": False}}
-
-    with pytest.raises(ValueError, match="only relay telemetry is supported for Hermes"):
-        hermes_common.validate_hermes_telemetry_provider(payload)
-
-
-def test_validate_hermes_telemetry_provider_rejects_mixed_native_and_relay():
-    payload = {"telemetry_plan": {"providers": ["relay", "native"], "relay_enabled": True}}
-
-    with pytest.raises(ValueError, match="only relay telemetry is supported for Hermes"):
-        hermes_common.validate_hermes_telemetry_provider(payload)
+@pytest.mark.parametrize(
+    ("providers", "relay_enabled"),
+    [(["native"], False), (["relay", "native"], True)],
+)
+def test_validate_hermes_telemetry_provider_rejects_native(providers, relay_enabled):
+    payload = {"telemetry_plan": {"providers": providers, "relay_enabled": relay_enabled}}
+
+    with pytest.raises(ValueError, match="only relay telemetry is supported for Hermes"):
+        hermes_common.validate_hermes_telemetry_provider(payload)

As per coding guidelines, "Prefer pytest.mark.parametrize over creating separate tests for different input types."

🤖 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 `@tests/adapters/test_adapaters_common_hermes.py` around lines 105 - 116,
Consolidate test_validate_hermes_telemetry_provider_rejects_native and
test_validate_hermes_telemetry_provider_rejects_mixed_native_and_relay into one
pytest.mark.parametrize test, parameterizing the differing telemetry_plan
payloads while preserving the shared ValueError match assertion.

Source: Coding guidelines

Signed-off-by: Anuradha Karuppiah <26330987+AnuradhaKaruppiah@users.noreply.github.com>
@AnuradhaKaruppiah
AnuradhaKaruppiah marked this pull request as ready for review July 13, 2026 22:45
@AnuradhaKaruppiah
AnuradhaKaruppiah requested a review from a team as a code owner July 13, 2026 22:45

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

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

⚠️ Outside diff range comments (2)
tests/adapters/test_deepagents.py (2)

410-427: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate handler/request helper pattern across two tests.

The same closures are redefined in both test_blocked_tools_middleware_blocks_configured_tools and test_subagents_are_gated_by_blocked_tools. Consider hoisting these into a shared conftest.py fixture (e.g., a tool_call_request_factory) per the guideline to prefer fixtures over helper methods and avoid duplication.

As per coding guidelines, "Prefer pytest fixtures over helper methods" and "Do not duplicate fixtures across test files; if a fixture is needed in multiple test files, define it in conftest.py."

Also applies to: 576-605

🤖 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 `@tests/adapters/test_deepagents.py` around lines 410 - 427, Extract the
duplicated handler and request helper closures from
test_blocked_tools_middleware_blocks_configured_tools and
test_subagents_are_gated_by_blocked_tools into shared pytest fixtures in
conftest.py, such as a tool_call_request_factory fixture. Update both tests to
use the fixtures while preserving their existing blocked and allowed tool
assertions.

Source: Coding guidelines


685-685: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Restore coverage for invalid tools mappings. ToolsConfig still accepts mapping input, and _ToolsConfig.from_mapping() rejects bad blocked shapes; the existing SDK contract test only covers the scalar case, not {"blocked": "browser"}. Keep this path covered here or add a contract test next to the typed config.

🤖 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 `@tests/adapters/test_deepagents.py` at line 685, Extend
test_bad_mcp_transport_is_normalized_failure or add a nearby typed-config
contract test to cover ToolsConfig mapping input with {"blocked": "browser"}.
Assert that _ToolsConfig.from_mapping() rejects the invalid blocked shape, while
preserving the existing scalar invalid-tools coverage.

Source: Path instructions

🤖 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 `@adapters/deepagents/README.md`:
- Around line 84-86: Update the preflight failure list in the README sentence to
include the article “a” before “passthrough option,” preserving the existing
parallel list structure and surrounding wording.

In `@tests/adapters/test_deepagents.py`:
- Around line 416-420: Update the local handler and request helpers, including
the duplicate pair, to remove typing.Any: annotate request’s return value with
types.SimpleNamespace and annotate handler’s request parameter with the
appropriate types.SimpleNamespace type matching the constructed and consumed
object.
- Line 577: Remove the unused fake_sdks parameter from
test_subagents_are_gated_by_blocked_tools, or replace it with
`@pytest.mark.usefixtures`("fake_sdks") if the fixture’s side effects are
required; preserve the test’s existing behavior.

---

Outside diff comments:
In `@tests/adapters/test_deepagents.py`:
- Around line 410-427: Extract the duplicated handler and request helper
closures from test_blocked_tools_middleware_blocks_configured_tools and
test_subagents_are_gated_by_blocked_tools into shared pytest fixtures in
conftest.py, such as a tool_call_request_factory fixture. Update both tests to
use the fixtures while preserving their existing blocked and allowed tool
assertions.
- Line 685: Extend test_bad_mcp_transport_is_normalized_failure or add a nearby
typed-config contract test to cover ToolsConfig mapping input with {"blocked":
"browser"}. Assert that _ToolsConfig.from_mapping() rejects the invalid blocked
shape, while preserving the existing scalar invalid-tools coverage.
🪄 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: 18e6064e-684c-4395-8a21-5bf35ca816b3

📥 Commits

Reviewing files that changed from the base of the PR and between 6853d16 and 7c7db88.

📒 Files selected for processing (12)
  • adapters/claude/README.md
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • adapters/deepagents/README.md
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • crates/fabric-core/src/doctor.rs
  • crates/fabric-core/src/error.rs
  • crates/fabric-core/src/runtime.rs
  • docs/reference/api/python-library-reference/nemo_fabric.models.md
  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
  • scripts/generate_api_docs.sh
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_deepagents.py
💤 Files with no reviewable changes (1)
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: Pre-commit
  • GitHub Check: Test (x86_64)
  • GitHub Check: Test (arm64)
🧰 Additional context used
📓 Path-based instructions (5)
{adapters/**,examples/**}

⚙️ CodeRabbit configuration file

{adapters/**,examples/**}: Review adapter and example changes for command correctness, config/schema consistency, artifact handling, and compatibility with the public Fabric contracts.

Files:

  • adapters/claude/README.md
  • adapters/deepagents/README.md
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
crates/fabric-core/src/**/*.rs

⚙️ CodeRabbit configuration file

crates/fabric-core/src/**/*.rs: Review the Rust core for runtime lifecycle correctness, handle validation, capability routing accuracy, schema stability, and error semantics.
Public API changes should match committed schemas, tests, and documentation.

Files:

  • crates/fabric-core/src/error.rs
  • crates/fabric-core/src/doctor.rs
  • crates/fabric-core/src/runtime.rs
{docs/**,README.md,AGENTS.md}

⚙️ CodeRabbit configuration file

{docs/**,README.md,AGENTS.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency with generated schemas.

Files:

  • docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx
  • docs/reference/api/python-library-reference/nemo_fabric.models.md
tests/**/*.py

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

tests/**/*.py: Use pytest to run Python tests.
Do not add @pytest.mark.asyncio to test functions; async tests are detected and run automatically.
Do not add -> None return type annotations to test functions.
When mocking a class, do not define a new class; use unittest.mock.MagicMock or unittest.mock.AsyncMock, adding spec when needed.
Name mocked classes with a mock prefix, not fake.
Prefer pytest fixtures over helper methods.
Do not duplicate fixtures across test files; if a fixture is needed in multiple test files, define it in conftest.py.
When creating a fixture, use @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) and define the function as <fixture_name>_fixture() -> <return_type>; only pass scope when it is not function.
Prefer pytest.mark.parametrize over creating separate tests for different input types.
If a fixture is needed for a test but does not return a value, or its value is unused, use @pytest.mark.usefixtures.
When modifying environment variables in a test, use os.environ; tests/conftest.py provides an autouse restore_environ_fixture that restores environment variables after each test, so monkeypatch.setenv is unnecessary.

Files:

  • tests/adapters/test_deepagents.py
  • tests/adapters/test_claude_adapter.py
{tests/**,python/tests/**}

⚙️ CodeRabbit configuration file

{tests/**,python/tests/**}: Tests should cover the behavior promised by the changed API surface, including error paths, lifecycle cleanup, and SDK/native parity where relevant.

Files:

  • tests/adapters/test_deepagents.py
  • tests/adapters/test_claude_adapter.py
🧠 Learnings (1)
📚 Learning: 2026-07-09T22:28:51.689Z
Learnt from: AjayThorve
Repo: NVIDIA/NeMo-Fabric PR: 43
File: adapters/claude-sdk/src/nemo_fabric_adapters/claude_sdk/adapter.py:164-168
Timestamp: 2026-07-09T22:28:51.689Z
Learning: In the NeMo-Fabric adapters, treat path values used in Fabric adapter configuration (including logic like `_resolve_path` in adapter.py) as config-root-relative. Do not apply `Path.expanduser()` (or otherwise apply `~`/home or shell-style expansion), because it will make the resolved paths normalize inconsistently across adapters. Also, do not rely on or add any resolution behavior that uses `harness.settings.cwd` as an override point for these adapter paths—`harness.settings.cwd` is explicitly unsupported in this adapter context.

Applied to files:

  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
🧬 Code graph analysis (5)
crates/fabric-core/src/doctor.rs (1)
crates/fabric-core/src/config.rs (6)
  • RunPlan (1837-1869)
  • CapabilityTarget (1996-2003)
  • AdapterKind (493-502)
  • CapabilityRoute (1970-1979)
  • resolve_run_plan (1183-1186)
  • CapabilityKind (1984-1991)
crates/fabric-core/src/runtime.rs (1)
crates/fabric-core/src/config.rs (5)
  • RunPlan (1837-1869)
  • CapabilityPlan (1919-1944)
  • CapabilityTarget (1996-2003)
  • resolve_run_plan (1183-1186)
  • CapabilityKind (1984-1991)
tests/adapters/test_deepagents.py (1)
adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (2)
  • build_agent_kwargs (364-386)
  • awrap_tool_call (228-231)
adapters/claude/src/nemo_fabric_adapters/claude/adapter.py (1)
python/src/nemo_fabric/types.py (2)
  • tools (691-694)
  • tools (697-698)
tests/adapters/test_claude_adapter.py (1)
python/src/nemo_fabric/types.py (2)
  • tools (691-694)
  • tools (697-698)
🪛 Ruff (0.15.21)
tests/adapters/test_deepagents.py

[warning] 416-416: Dynamically typed expressions (typing.Any) are disallowed in _request

(ANN401)


[warning] 419-419: Dynamically typed expressions (typing.Any) are disallowed in request

(ANN401)


[warning] 577-577: Unused function argument: fake_sdks

(ARG001)


[warning] 594-594: Dynamically typed expressions (typing.Any) are disallowed in _request

(ANN401)


[warning] 597-597: Dynamically typed expressions (typing.Any) are disallowed in request

(ANN401)

🔇 Additional comments (13)
docs/reference/api/python-library-reference/nemo_fabric.models.md (2)

1424-1426: Blank line after the ToolsConfig heading is now present, resolving the previously flagged MD022 violation.


1550-1558: LGTM!

scripts/generate_api_docs.sh (1)

42-43: LGTM!

adapters/deepagents/README.md (1)

55-57: LGTM!

Also applies to: 72-73

adapters/claude/src/nemo_fabric_adapters/claude/adapter.py (2)

14-30: LGTM!

Also applies to: 106-106, 188-188, 241-241, 280-280, 353-356, 391-393, 463-470, 510-517


303-305: 🎯 Functional Correctness

Confirm no broader consumer still relies on ClaudeAgentOptions.tools. The local adapter no longer references _normalized_tools, but any SDK code that expects tools to carry capability-plan-derived values still needs a repo-wide check.

tests/adapters/test_claude_adapter.py (2)

90-90: Fixture and assertions correctly reflect the tools.blocked deny-list shift (options.tools is None, disallowed_tools merges blocked + settings-level entries). Coverage for the new _disallowed_tools merge behavior looks adequate for the changed API surface.

As per path instructions, {tests/**,python/tests/**} should cover behavior promised by the changed API surface — this is satisfied here.

Also applies to: 122-130, 152-160


14-26: LGTM!

Also applies to: 171-171, 186-194, 285-285

adapters/claude/README.md (1)

40-42: LGTM!

Also applies to: 84-84, 108-108

crates/fabric-core/src/error.rs (1)

112-119: LGTM!

docs/reference/api/rust-library-reference/fabric-core/error/enum-fabricerror.mdx (1)

12-12: LGTM!

Also applies to: 202-217

crates/fabric-core/src/doctor.rs (1)

189-196: LGTM!

Also applies to: 583-602

crates/fabric-core/src/runtime.rs (1)

410-421: LGTM!

Also applies to: 424-439, 441-452, 2053-2072

Comment thread adapters/deepagents/README.md
Comment thread tests/adapters/test_deepagents.py Outdated
Comment thread tests/adapters/test_deepagents.py Outdated

@AjayThorve AjayThorve left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Overall looks good, Two policy-enforcement issues should ideally be addressed before merge.

Comment thread adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py Outdated
Comment thread crates/fabric-core/src/config.rs Outdated
Signed-off-by: Anuradha Karuppiah <26330987+AnuradhaKaruppiah@users.noreply.github.com>
Signed-off-by: Anuradha Karuppiah <26330987+AnuradhaKaruppiah@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

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

⚠️ Outside diff range comments (1)
schemas/run-plan.schema.json (1)

261-264: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Require the normalized tools plan in CapabilityPlan.

default does not make a JSON Schema property required. A plan that omits tools can still validate, contradicting the contract that normalized plans always expose tools and use {} when no policy is configured. Add tools to CapabilityPlan.required and keep Rust serialization aligned.

As per path instructions, schemas must encode the first-class normalized capability_plan.tools field.

Also applies to: 1674-1674

🤖 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 `@schemas/run-plan.schema.json` around lines 261 - 264, Update the
CapabilityPlan schema’s required properties to include tools, while retaining
its default {} behavior for omitted policy configuration. Ensure the
corresponding Rust serialization model emits the normalized
capability_plan.tools field consistently with this required schema contract.

Source: Path instructions

🤖 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 `@adapters/claude/src/nemo_fabric_adapters/claude/adapter.py`:
- Around line 711-804: Reduce the PLR0912/PLR0915 complexity of run_claude by
extracting relay lifecycle logic into focused helpers, such as _start_relay for
gateway startup and _finalize_relay for gateway shutdown, plugin removal, and
cleanup-error construction. Keep query streaming, session persistence, relay
output wrapping, and cleanup-error merging behavior unchanged while moving the
corresponding branches out of run_claude.

In `@adapters/deepagents/README.md`:
- Around line 84-85: Update the preflight-failure description in the README to
identify the condition as “an invalid or unsupported passthrough option,”
preserving the existing references to missing credentials, the absent package,
and invalid MCP servers.

In `@adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py`:
- Around line 414-445: Narrow the _gated_subagents subagents parameter from Any
to list[Any] | None, matching its existing None-or-list validation and
preserving the AdapterConfigError behavior for other runtime values.

In `@README.md`:
- Line 84: Update the README installation instruction to format the package
extra “nemo-fabric[hermes]” as inline code, while leaving the surrounding
wording unchanged.

In `@tests/adapters/test_hermes_adapter.py`:
- Around line 355-470: Add a regression test covering overlapping tool
configuration, with a name present in both tools.blocked and
settings.enabled_toolsets (and, where applicable, disabled_toolsets). In the
adapter.run_hermes test flow, assert the blocked tool is removed from the
enabled_toolsets passed to AIAgent or otherwise cannot execute, preserving
fail-closed behavior.

---

Outside diff comments:
In `@schemas/run-plan.schema.json`:
- Around line 261-264: Update the CapabilityPlan schema’s required properties to
include tools, while retaining its default {} behavior for omitted policy
configuration. Ensure the corresponding Rust serialization model emits the
normalized capability_plan.tools field consistently with this required schema
contract.
🪄 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: 73272b4d-8569-4ca5-bf4a-2ceb3c08f1e4

📥 Commits

Reviewing files that changed from the base of the PR and between 7c7db88 and 4a59a66.

📒 Files selected for processing (21)
  • README.md
  • adapters/claude/README.md
  • adapters/claude/fabric-adapter.json
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/deepagents/README.md
  • adapters/deepagents/fabric-adapter.json
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/hermes/README.md
  • adapters/hermes/fabric-adapter.json
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • crates/fabric-core/src/config.rs
  • crates/fabric-core/src/doctor.rs
  • crates/fabric-core/src/runtime.rs
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
  • schemas/adapter-descriptor.schema.json
  • schemas/run-plan.schema.json
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_deepagents.py
  • tests/adapters/test_hermes_adapter.py
  • tests/e2e/test_claude.py
📜 Review details
🧰 Additional context used
📓 Path-based instructions (33)
**/*.{md,mdx,html}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Changes affecting public behavior, adapters, examples, or workspace structure must update the corresponding documentation; public API changes require updated SDK or API reference documentation.

Files:

  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
  • adapters/hermes/README.md
  • README.md
  • adapters/claude/README.md
  • adapters/deepagents/README.md
**/*.{md,mdx}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

For docs site changes, run just docs to regenerate Python and Rust API references and validate Fern configuration.

**/*.{md,mdx}: Prioritize factual accuracy in NeMo Fabric documentation and keep commands, package names, APIs, file paths, repository layout, entry points, support claims, examples, and procedures aligned with current repository behavior.
Update relevant entry-point documentation when public behavior changes, including README.md, docs/index.yml, package or crate READMEs, and adapter or integration READMEs.
Use {/* ... */} delimiters for top-of-file SPDX comments in MDX files, not HTML comment delimiters.
Capitalize NVIDIA correctly and use consistent current repository terminology, product names, APIs, and feature names.
Format commands, code, expressions, file names, paths, and filenames as inline code where appropriate.
Use title case for technical-documentation headings.
Introduce code blocks, tables, and lists with complete lead-in sentences.
Use descriptive link text instead of raw URLs or generic labels such as here.
Write procedures as short, imperative, parallel, easy-to-scan steps; prefer active voice, present tense, plain English, and concise sentences.
Use after instead of once when expressing temporal sequence, and use can instead of may when describing possibility rather than permission.
Use unambiguous date formats and avoid ordinal dates in body text.
When reviewing documentation, report findings in severity order under Must fix, Should fix, and Nice to have, with file paths, line references, explanations, and concrete rewrites or directions.

Files:

  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
  • adapters/hermes/README.md
  • README.md
  • adapters/claude/README.md
  • adapters/deepagents/README.md
**/*

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*: All source files must include the specified SPDX copyright and Apache-2.0 license header using the comment syntax appropriate to the file type.
Release tags must use raw Rust-compatible SemVer without a leading v, such as 0.1.0 or 0.1.0-rc.1.

**/*: Before implementing, explicitly state assumptions, surface ambiguity and tradeoffs, present multiple interpretations when relevant, and ask for clarification rather than silently deciding or proceeding when requirements are unclear.
Prefer the minimum code needed to solve the requested problem: avoid speculative features, unnecessary abstractions, unrequested flexibility, and handling of impossible scenarios; simplify overcomplicated solutions.
When editing existing code, make surgical changes only: do not modify unrelated code, comments, formatting, or pre-existing dead code; match the existing style, and remove only unused imports, variables, or functions introduced by your changes.
Define verifiable success criteria for each task, such as writing regression tests for bugs and invalid-input tests for validation, then verify the implementation against those criteria. For multi-step work, state a brief plan with a verification check for each step.

**/*: Keep pull request branch scope coherent and reviewable.
Run relevant tests under validate-change before opening or updating a pull request.
Format changed files with the language-native formatter.
Update documentation and examples for public behavior changes.
Update dependent maintainer or consumer guidance when code changes affect APIs, bindings, commands, paths, packaging guidance, or best practices.
Use Conventional Commit style for pull request titles: <type>: <concise imperative summary>, choosing the type from the actual change surface. Use fix only for user-facing or runtime product-code bug fixes.
A pull request body must include #### Overview, #### Details, #### Validation, #### Where should the reviewer start?, and `#### Related ...

Files:

  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
  • adapters/hermes/README.md
  • adapters/hermes/fabric-adapter.json
  • README.md
  • adapters/claude/README.md
  • adapters/claude/fabric-adapter.json
  • adapters/deepagents/fabric-adapter.json
  • schemas/adapter-descriptor.schema.json
  • adapters/deepagents/README.md
  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • crates/fabric-core/src/doctor.rs
  • crates/fabric-core/src/runtime.rs
  • schemas/run-plan.schema.json
  • tests/e2e/test_claude.py
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • tests/adapters/test_claude_adapter.py
  • crates/fabric-core/src/config.rs
  • tests/adapters/test_deepagents.py
**/*.mdx

📄 CodeRabbit inference engine (CONTRIBUTING.md)

MDX files must use the specified SPDX header in a JSX comment.

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

Files:

  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
{README.md,docs/**/*.{md,mdx,yml},examples/**/*.{md,mdx,yml}}

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

Keep package names, repository references, and build commands current in documentation and examples.

Files:

  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
  • README.md
{docs/**/*.{md,mdx,yml},examples/**/*.{md,mdx,yml}}

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

Update relevant getting-started, reference, adapter, and example documentation when the corresponding examples or adapters change.

Files:

  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
docs/**/*.{md,mdx,yml}

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

Run just docs when the documentation site changes.

Files:

  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
{docs/**/*,.github/workflows/ci_python.yml,.github/workflows/ci_rust.yml,justfile}

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

Use the current install, import, build, test, clean, and documentation commands consistently in documentation, examples, CI workflows, and just recipes.

Files:

  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
{docs/**/*,.github/workflows/ci_python.yml,.github/workflows/ci_rust.yml}

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

Reflect public packaging changes in release-facing documentation and examples.

Files:

  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
**/*.{md,mdx,rst}

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

**/*.{md,mdx,rst}: For NeMo Fabric documentation, verify technical claims against the current repository, public API, or documented command before reviewing style.
Always spell NVIDIA in all caps; do not use Nvidia, nvidia, or NV.
Format commands, code elements, expressions, package names, file names, and paths as inline code.
Use descriptive link text; avoid raw URLs and weak anchors such as here or read more.
Use title case consistently for technical documentation headings.
Introduce code blocks, lists, tables, and images with complete sentences.
Write procedures as imperative, parallel steps; split long procedures into smaller tasks.
Prefer active voice, present tense, short sentences, contractions, and plain English while preserving necessary technical precision.
Use can for possibility and reserve may for permission.
Use after for temporal relationships instead of once, and prefer refer to over see when directing readers to another resource.
Avoid culture-specific idioms, unnecessary Latinisms, jokes, and marketing exaggeration in technical documentation.
Spell out months in body text, avoid ordinal dates, and use clear time zones.
Spell out whole numbers from zero through nine unless they are technical values, parameters, versions, or UI values; use numerals for 10 or greater and commas in thousands.
Do not add trademark symbols to learning-oriented documentation unless the source, platform, or legal guidance explicitly requires them.
Do not replace precise technical terms with simpler words when doing so would lose precision.
Do not flag passive voice when the actor is unknown or the action is the important part.
Do not rewrite API names, package names, command flags, or code literals for style.

**/*.{md,mdx,rst}: Use consistent title case for technical-document headings and table headers; avoid quotation marks, ampersands, and exclamation marks in headings, while preserving official product, event, research, and whitepaper title ...

Files:

  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
  • adapters/hermes/README.md
  • README.md
  • adapters/claude/README.md
  • adapters/deepagents/README.md
docs/**/*

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

For documentation or examples changes, run just docs when practical and verify documented commands against the current repository.

Files:

  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
{docs/**,README.md,AGENTS.md}

⚙️ CodeRabbit configuration file

{docs/**,README.md,AGENTS.md}: Review documentation for technical accuracy against the current API, command correctness, and consistency with generated schemas.

Files:

  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
  • README.md
**/README.md

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update an adapter or example README.md when that adapter or example surface changes.

Files:

  • adapters/hermes/README.md
  • README.md
  • adapters/claude/README.md
  • adapters/deepagents/README.md
**/*.{html,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

HTML and Markdown files must use the specified SPDX header in an HTML comment.

Files:

  • adapters/hermes/README.md
  • README.md
  • adapters/claude/README.md
  • adapters/deepagents/README.md
**/*.{md,rst}

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

Update documentation and examples in the same branch as the public API change.

Verify README and documentation entry points, package names, paths, examples, and public commands remain current after changes.

Files:

  • adapters/hermes/README.md
  • README.md
  • adapters/claude/README.md
  • adapters/deepagents/README.md
**/*.{md,rst,txt,adoc}

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

**/*.{md,rst,txt,adoc}: For technical documentation, use professional, active, conversational, engaging, precise, and plain-English prose. Prefer active voice, present tense, short sentences, and scannable paragraphs. Avoid casual or imprecise language, swearing, threats, insults, jokes, puns, culture-specific idioms, marketing exaggeration, and unsupported third-party comparisons.
Use can for possibility and reserve may for permission; use after for temporal order; use refer to for cross-references; prefer short direct sentences and specific verbs; avoid unnecessary please in technical documentation.
Prefer active voice when the actor matters. Passive voice is acceptable when the actor is unknown or irrelevant, when the action or result is the focus, or in programmer documentation.
Use natural contractions in conversational technical prose, but do not force them in formal legal copy, API references, or generated text.
Prefer simpler English over Latinisms: use for example or such as instead of e.g., and so on instead of etc., that is instead of i.e., compared to instead of vs., and by, through, or using instead of via. Use industry-standard terms such as in silico, in vitro, and in vivo when appropriate, and italicize them in running text.
Use that without commas for essential clauses, and which with commas for nonessential clauses.
Format dates and times clearly: spell out months in body text; use forms such as June 12, 2025; avoid numeric or ordinal dates; capitalize days; use 12-hour time when appropriate; include a space before a.m. or p.m.; use ET and PT for needed time zones; avoid 24/7; and prefer from 12:30 to 1:00 p.m. for prose ranges.
Format numbers consistently: spell out zero through nine in body text, use numerals for 10 or greater and for technical values, use commas in thousands, do not begin a sentence with a numeral, spell out ordinals, and use numerals consistently within a category wh...

Files:

  • adapters/hermes/README.md
  • README.md
  • adapters/claude/README.md
  • adapters/deepagents/README.md
{adapters/**,examples/**}

⚙️ CodeRabbit configuration file

{adapters/**,examples/**}: Review adapter and example changes for command correctness, config/schema consistency, artifact handling, and compatibility with the public Fabric contracts.

Files:

  • adapters/hermes/README.md
  • adapters/hermes/fabric-adapter.json
  • adapters/claude/README.md
  • adapters/claude/fabric-adapter.json
  • adapters/deepagents/fabric-adapter.json
  • adapters/deepagents/README.md
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
**/*.{json,jsonc}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Public contract changes must keep checked-in JSON Schema snapshots synchronized.

Files:

  • adapters/hermes/fabric-adapter.json
  • adapters/claude/fabric-adapter.json
  • adapters/deepagents/fabric-adapter.json
  • schemas/adapter-descriptor.schema.json
  • schemas/run-plan.schema.json
**/*.{rs,py,pyi,json,yaml,yml}

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

Determine and update every affected public surface, including the CLI, PyO3 bindings, Python SDK, type stubs, schemas, and adapter contract, so they remain in parity.

Files:

  • adapters/hermes/fabric-adapter.json
  • adapters/claude/fabric-adapter.json
  • adapters/deepagents/fabric-adapter.json
  • schemas/adapter-descriptor.schema.json
  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • crates/fabric-core/src/doctor.rs
  • crates/fabric-core/src/runtime.rs
  • schemas/run-plan.schema.json
  • tests/e2e/test_claude.py
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • tests/adapters/test_claude_adapter.py
  • crates/fabric-core/src/config.rs
  • tests/adapters/test_deepagents.py
README.md

📄 CodeRabbit inference engine (CONTRIBUTING.md)

The root README.md must reflect the current workspace, supported adapters, and top-level documentation.

Update README.md when a small Fabric bug fix changes public behavior.

Files:

  • README.md
{README.md,docs/index.yml}

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

Update README.md or docs/index.yml when documentation entry points or example reading paths change.

Files:

  • README.md
schemas/**/*

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

When public configuration types change, ensure schema snapshot tests pass through just test-rust and review generated schema diffs.

Files:

  • schemas/adapter-descriptor.schema.json
  • schemas/run-plan.schema.json

⚙️ CodeRabbit configuration file

schemas/**/*: Schemas are generated public contract snapshots. Check that schema diffs correspond to intentional Rust type changes and are covered by core tests.

Files:

  • schemas/adapter-descriptor.schema.json
  • schemas/run-plan.schema.json
**/*.py

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.py: Python public APIs must use type annotations, and native Python binding declarations must remain synchronized with their Rust implementations.
Python files must begin with the specified # SPDX copyright and Apache-2.0 license header.

Files:

  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • tests/e2e/test_claude.py
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_deepagents.py
**/*.{rs,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{rs,py}: Use snake_case for Rust and Python functions and variables; use PascalCase for Rust types and Python classes.
Run tests for every language surface affected by a change. Changes touching the Rust core or public schemas require both Rust and Python test suites.
Public contract changes must keep native Python binding declarations synchronized with their Rust implementations.

Files:

  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • crates/fabric-core/src/doctor.rs
  • crates/fabric-core/src/runtime.rs
  • tests/e2e/test_claude.py
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • tests/adapters/test_claude_adapter.py
  • crates/fabric-core/src/config.rs
  • tests/adapters/test_deepagents.py
tests/**/*.py

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

tests/**/*.py: Use Pytest to run Python tests.
Do not add @pytest.mark.asyncio to tests; async tests are automatically detected by the async runner.
Do not add -> None return annotations to test functions.
When mocking a class, use unittest.mock.MagicMock or AsyncMock, supplying spec when necessary; do not define a new mock class.
Prefix mocked class names with mock, not fake.
Prefer pytest fixtures over helper methods.
Define shared fixtures in conftest.py rather than repeating them across test files.
Define fixtures using @pytest.fixture(name="<fixture_name>"[, scope="<scope>"]) and a <fixture_name>_fixture function; specify scope only when it is not function.
Prefer pytest.mark.parametrize over separate tests for different input types.
Use @pytest.mark.usefixtures when a fixture is needed but its return value is unused.
Use os.environ to modify environment variables in tests; do not use monkeypatch.setenv, because the autouse restore_environ_fixture in tests/conftest.py restores the environment after each test.
Avoid defensive programming in tests; access expected data directly so missing data raises a clear error instead of being silently tolerated.
Run focused tests with uv run pytest -k "<pattern>" and all tests with uv run pytest.

Files:

  • tests/adapters/test_hermes_adapter.py
  • tests/e2e/test_claude.py
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_deepagents.py
**/*.{py,pyi}

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

When Python code or a Python-facing adapter changes, run just test-python.

Files:

  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • tests/e2e/test_claude.py
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_deepagents.py
**/*.{rs,py,pyi,toml}

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

When the PyO3 bridge or package metadata changes, run just build-python and cargo check -p fabric-python --locked.

Files:

  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • crates/fabric-core/src/doctor.rs
  • crates/fabric-core/src/runtime.rs
  • tests/e2e/test_claude.py
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • tests/adapters/test_claude_adapter.py
  • crates/fabric-core/src/config.rs
  • tests/adapters/test_deepagents.py
tests/adapters/**/*

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

When an adapter or integration changes, run its focused tests under tests/adapters, followed by just test-python.

Files:

  • tests/adapters/test_hermes_adapter.py
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_deepagents.py
{tests/**,python/tests/**}

⚙️ CodeRabbit configuration file

{tests/**,python/tests/**}: Tests should cover the behavior promised by the changed API surface, including error paths, lifecycle cleanup, and SDK/native parity where relevant.

Files:

  • tests/adapters/test_hermes_adapter.py
  • tests/e2e/test_claude.py
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_deepagents.py
**/*.{rs,toml}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

**/*.{rs,toml}: Rust code must be formatted with cargo fmt --all; formatting can be checked with cargo fmt --all -- --check, and Rust workspaces must compile with cargo check --workspace --locked.
Rust files must begin with the specified // SPDX copyright and Apache-2.0 license header.

When Rust code or Rust project configuration changes, run cargo fmt --all -- --check and just test-rust.

Files:

  • crates/fabric-core/src/doctor.rs
  • crates/fabric-core/src/runtime.rs
  • crates/fabric-core/src/config.rs
**/*.rs

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

Implement new runtime or binding behavior in the shared Rust core first.

For any Rust change, run just test-rust and cargo fmt --all -- --check.

Run cargo check --workspace --locked after version changes.

Files:

  • crates/fabric-core/src/doctor.rs
  • crates/fabric-core/src/runtime.rs
  • crates/fabric-core/src/config.rs
crates/fabric-core/**/*

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

For changes under crates/fabric-core, run both the Rust and Python test suites.

When crates/fabric-core changes in a way exposed through Python, run both the Rust and Python test suites.

Files:

  • crates/fabric-core/src/doctor.rs
  • crates/fabric-core/src/runtime.rs
  • crates/fabric-core/src/config.rs
crates/fabric-core/src/**/*.rs

⚙️ CodeRabbit configuration file

crates/fabric-core/src/**/*.rs: Review the Rust core for runtime lifecycle correctness, handle validation, capability routing accuracy, schema stability, and error semantics.
Public API changes should match committed schemas, tests, and documentation.

Files:

  • crates/fabric-core/src/doctor.rs
  • crates/fabric-core/src/runtime.rs
  • crates/fabric-core/src/config.rs
🧠 Learnings (2)
📚 Learning: 2026-06-29T22:34:52.407Z
Learnt from: AjayThorve
Repo: NVIDIA/NeMo-Fabric PR: 27
File: adapters/codex-cli/fabric-adapter.json:13-15
Timestamp: 2026-06-29T22:34:52.407Z
Learning: In NeMo-Fabric adapter manifest files (e.g., `*/fabric-adapter.json`), keep `config.accepts` limited to the top-level Fabric capability sections that `resolve_capability_plan` consumes (such as `models`, `tools`, `mcp`, `skills`, `telemetry`). Do not add adapter-owned `harness.settings` keys to `config.accepts`; `harness.settings` should remain adapter-owned and be passed through unchanged.

Applied to files:

  • adapters/hermes/fabric-adapter.json
  • adapters/claude/fabric-adapter.json
  • adapters/deepagents/fabric-adapter.json
📚 Learning: 2026-07-09T22:28:51.689Z
Learnt from: AjayThorve
Repo: NVIDIA/NeMo-Fabric PR: 43
File: adapters/claude-sdk/src/nemo_fabric_adapters/claude_sdk/adapter.py:164-168
Timestamp: 2026-07-09T22:28:51.689Z
Learning: In the NeMo-Fabric adapters, treat path values used in Fabric adapter configuration (including logic like `_resolve_path` in adapter.py) as config-root-relative. Do not apply `Path.expanduser()` (or otherwise apply `~`/home or shell-style expansion), because it will make the resolved paths normalize inconsistently across adapters. Also, do not rely on or add any resolution behavior that uses `harness.settings.cwd` as an override point for these adapter paths—`harness.settings.cwd` is explicitly unsupported in this adapter context.

Applied to files:

  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
🧬 Code graph analysis (5)
adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py (1)
adapters/common/src/nemo_fabric_adapters/common/utils.py (9)
  • settings_payload (106-108)
  • environment_payload (102-103)
  • normalize_list (178-185)
  • telemetry_providers (148-152)
  • merge_unique (188-194)
  • dump_yaml (201-207)
  • capability_plan (164-165)
  • blocked_tools (173-175)
  • relay_enabled (155-156)
crates/fabric-core/src/doctor.rs (1)
crates/fabric-core/src/config.rs (1)
  • resolve_run_plan (1183-1186)
adapters/claude/src/nemo_fabric_adapters/claude/adapter.py (3)
adapters/common/src/nemo_fabric_adapters/common/utils.py (6)
  • load_relay_plugin_config (210-234)
  • collect_relay_artifacts (422-440)
  • capability_plan (164-165)
  • config_root (66-67)
  • relay_enabled (155-156)
  • runtime_context (83-84)
adapters/common/src/nemo_fabric_adapters/common/relay_gateway.py (6)
  • RelayGatewayLaunch (31-38)
  • RelayGatewayError (26-27)
  • start_relay_gateway (132-178)
  • relay_cli_observability_version (63-83)
  • stop_relay_gateway (111-129)
  • resolve_relay_command (41-52)
adapters/common/src/nemo_fabric_adapters/common/relay_hooks.py (1)
  • render_relay_hooks (45-69)
tests/adapters/test_claude_adapter.py (2)
adapters/claude/src/nemo_fabric_adapters/claude/adapter.py (2)
  • AdapterConfigError (114-115)
  • run (808-816)
adapters/common/src/nemo_fabric_adapters/common/relay_gateway.py (2)
  • RelayGatewayLaunch (31-38)
  • RelayGatewayError (26-27)
tests/adapters/test_deepagents.py (1)
adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (2)
  • AdapterConfigError (55-56)
  • awrap_tool_call (228-231)
🪛 ast-grep (0.44.1)
adapters/claude/src/nemo_fabric_adapters/claude/adapter.py

[warning] 420-420: Do not make http calls without encryption
Context: f"http://{gateway_bind}"
Note: [CWE-319] Cleartext Transmission of Sensitive Information.

(requests-http)


[info] 342-350: use jsonify instead of json.dumps for JSON output
Context: json.dumps(
{
"name": "nemo-fabric-relay",
"description": "NeMo Relay hooks managed by NeMo Fabric",
"version": "1.0.0",
},
indent=2,
sort_keys=True,
)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 355-359: use jsonify instead of json.dumps for JSON output
Context: json.dumps(
relay_hooks.render_relay_hooks("claude", executable),
indent=2,
sort_keys=True,
)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

tests/adapters/test_claude_adapter.py

[info] 166-175: use jsonify instead of json.dumps for JSON output
Context: json.dumps(
{
"relay": {
"config": {
"atof": {"enabled": True},
"atif": {"enabled": True},
}
}
}
)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 597-597: use jsonify instead of json.dumps for JSON output
Context: json.dumps(output)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 654-654: use jsonify instead of json.dumps for JSON output
Context: json.dumps(output)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)


[info] 742-742: use jsonify instead of json.dumps for JSON output
Context: json.dumps(output)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🪛 Ruff (0.15.21)
tests/adapters/test_hermes_adapter.py

[warning] 136-136: Yoda condition detected

Rewrite as hermes_default == adapter.DEFAULT_MAX_ITERATIONS

(SIM300)


[warning] 388-388: Prefer dict over useless lambda

Replace with lambda with dict

(PIE807)


[warning] 390-390: Unused lambda argument: force

(ARG005)


[warning] 391-391: Unused lambda argument: args

(ARG005)


[warning] 391-391: Unused lambda argument: kwargs

(ARG005)

adapters/common/src/nemo_fabric_adapters/common/utils.py

[warning] 451-453: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 535-535: Consider moving this statement to an else block

(TRY300)


[warning] 537-537: Avoid specifying long messages outside the exception class

(TRY003)

adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py

[warning] 35-35: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 123-123: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 212-212: Avoid specifying long messages outside the exception class

(TRY003)

tests/e2e/test_claude.py

[warning] 169-169: Async functions should not use pathlib.Path methods, use trio.Path or anyio.path

(ASYNC240)


[warning] 170-170: Async functions should not use pathlib.Path methods, use trio.Path or anyio.path

(ASYNC240)


[warning] 213-213: Async functions should not use pathlib.Path methods, use trio.Path or anyio.path

(ASYNC240)

adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py

[warning] 420-420: Dynamically typed expressions (typing.Any) are disallowed in subagents

(ANN401)


[warning] 426-428: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 433-433: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 436-436: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 438-438: Avoid specifying long messages outside the exception class

(TRY003)

adapters/claude/src/nemo_fabric_adapters/claude/adapter.py

[warning] 32-32: Use from nemo_fabric_adapters.common import relay_gateway in lieu of alias

Replace with from nemo_fabric_adapters.common import relay_gateway

(PLR0402)


[warning] 33-33: Use from nemo_fabric_adapters.common import relay_hooks in lieu of alias

Replace with from nemo_fabric_adapters.common import relay_hooks

(PLR0402)


[warning] 125-125: Dynamically typed expressions (typing.Any) are disallowed in value

(ANN401)


[warning] 135-135: Dynamically typed expressions (typing.Any) are disallowed in value

(ANN401)


[warning] 148-148: Dynamically typed expressions (typing.Any) are disallowed in value

(ANN401)


[warning] 670-670: Unnecessary dict comprehension for iterable; use dict.fromkeys instead

Replace with dict.fromkeys(iterable))

(C420)


[warning] 711-711: Too many branches (22 > 12)

(PLR0912)


[warning] 711-711: Too many statements (56 > 50)

(PLR0915)

tests/adapters/test_claude_adapter.py

[error] 458-458: Possible hardcoded password assigned to: "FABRIC_UNRELATED_SECRET"

(S105)


[error] 460-460: Possible hardcoded password assigned to: "FABRIC_UNRELATED_SECRET"

(S105)


[warning] 506-506: Missing return type annotation for private function query_result

(ANN202)


[warning] 506-506: Unused function argument: prompt

(ARG001)


[warning] 571-571: Missing return type annotation for private function query_result

(ANN202)


[warning] 571-571: Unused function argument: prompt

(ARG001)


[warning] 571-571: Unused function argument: options

(ARG001)


[warning] 629-629: Missing return type annotation for private function query_result

(ANN202)


[warning] 629-629: Missing type annotation for **_

(ANN003)


[warning] 689-689: Missing return type annotation for private function query_failure

(ANN202)


[warning] 689-689: Unused function argument: prompt

(ARG001)


[warning] 689-689: Unused function argument: options

(ARG001)

🔇 Additional comments (34)
crates/fabric-core/src/config.rs (4)

2709-2796: LGTM!


55-103: LGTM!

Also applies to: 432-432, 1690-1701


1607-1638: 🗄️ Data Integrity & Integration

This concern doesn’t apply: the shipped hermes, claude, and deepagents descriptors already declare tools.blocked, so the routing change stays aligned with existing adapter support.

			> Likely an incorrect or invalid review comment.

1920-1922: 🗄️ Data Integrity & Integration

Nothing to change: ToolsPlan.blocked is already omitted when empty. capability_plan.tools still serializes as {} and matches the schema default.

			> Likely an incorrect or invalid review comment.
crates/fabric-core/src/doctor.rs (2)

590-608: Good coverage for fail-closed doctor behavior on unsupported tool policy.

Test correctly asserts that an Unsupported route with kind: Tools escalates the overall report to DoctorStatus::Fail rather than Warn, aligning with the runtime's fail-closed enforcement in runtime.rs.


14-15: LGTM!

Also applies to: 477-480

crates/fabric-core/src/runtime.rs (2)

2053-2083: Test correctly validates fail-closed enforcement at runtime start.

Confirms start_runtime rejects blocked-tools policy when the adapter only declares generic "tools" (not "tools.blocked"), returning FabricError::UnsupportedToolsPolicy. Good defense-in-depth alongside the doctor check in doctor.rs.


21-22: LGTM!

README.md (2)

50-53: LGTM!

Also applies to: 69-75, 77-82, 92-97, 118-120, 146-158, 160-162, 194-196


84-90: 🎯 Functional Correctness

Keep the Hermes install example as-is nemo-fabric[hermes] already pulls in both hermes-agent and nemo-fabric-adapters-hermes; replacing it with nemo-fabric-adapters-hermes would drop Hermes Agent.

			> Likely an incorrect or invalid review comment.
adapters/claude/README.md (1)

24-33: LGTM!

Also applies to: 51-53, 65-65, 77-100, 121-121, 145-145, 191-199

adapters/deepagents/README.md (1)

55-57: LGTM!

Also applies to: 72-83

docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx (1)

20-20: LGTM!

schemas/adapter-descriptor.schema.json (1)

8-8: LGTM!

Also applies to: 220-220

schemas/run-plan.schema.json (1)

8-8: LGTM!

Also applies to: 617-624, 1611-1636, 1751-1751

adapters/hermes/fabric-adapter.json (1)

18-18: 🗄️ Data Integrity & Integration

Same tools.blocked accepts-path verification as the DeepAgents manifest.

Same concern raised for adapters/deepagents/fabric-adapter.json: confirm the descriptor validator/capability resolver recognizes "tools.blocked" as a distinct accepted path.

adapters/common/src/nemo_fabric_adapters/common/utils.py (3)

8-8: LGTM!

Also applies to: 25-30, 53-56, 61-62, 114-140, 177-184, 196-198, 236-265, 500-537, 541-545


167-198: Line-range metadata conflicts with shown snippet for tools_config/blocked_tools/merge_unique.

The line-range change details describe tools_config, blocked_tools (167-176), and merge_unique (187-195) as newly added logic, but the annotated snippet marks 142-176 and 185-195 as "unchanged... not shown." Since these functions underpin the entire blocked-tools policy (consumed by Claude/Hermes/DeepAgents adapters per the PR description), their actual implementation should be reviewed directly — particularly whether blocked_tools/merge_unique validate input types strictly (a past review comment on the Claude adapter flagged exactly this concern for merge_unique coercing malformed values).


442-497: 🎯 Functional Correctness | 🏗️ Heavy lift

Verify atif sinks aren't silently dropped under observability_version == 2.

relay_cli_plugin_config only converts the atof section into the sink-based v2 format (config["atof"] = {"enabled": ..., "sinks": ...}); the atif section is left untouched even though config["version"] is bumped to 2 for the whole component. If the external Relay CLI's v2 contract expects sink-based config uniformly, ATIF trajectory output configured under atif.enabled=True could be misinterpreted or ignored by a v2 CLI, silently losing trajectory telemetry (the e2e/hermes tests exercise atof+atif together but not through this v2 conversion path).

Please confirm with the NeMo Relay CLI v2 contract docs whether atif requires an analogous sink transform, or whether it intentionally stays in the legacy shape for v2.

adapters/claude/src/nemo_fabric_adapters/claude/adapter.py (1)

14-43: LGTM!

Also applies to: 84-106, 121-167, 216-266, 276-334, 337-437, 440-511, 527-572, 575-588, 641-642, 665-708

adapters/deepagents/fabric-adapter.json (1)

12-12: 🗄️ Data Integrity & Integration

Confirm accepts validation supports the dotted tools.blocked sub-path.

This adds "tools.blocked" alongside the existing "tools" entry. The same pattern appears in the Claude and Hermes descriptors and is asserted by test_claude_descriptor_is_narrow_and_versioned, so it looks intentional, but the descriptor-accepts validation logic (schemas/adapter-descriptor.schema.json, crates/fabric-core capability-plan resolution) isn't in this review's file set. Please confirm the resolver treats "tools.blocked" as a distinct, recognized capability path rather than an unused/no-op string.

Based on a retrieved learning, config.accepts should stay limited to top-level Fabric capability sections consumed by resolve_capability_plan; confirming this dotted form is consumed the same way avoids silently-ignored entries.

Source: Learnings

tests/adapters/test_claude_adapter.py (1)

6-9: LGTM!

Also applies to: 25-25, 30-61, 128-340, 359-415, 418-461, 463-746, 764-772

tests/e2e/test_claude.py (1)

14-27: LGTM!

Also applies to: 32-121, 124-148, 151-214, 220-256

adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (2)

226-235: Shared middleware factory refactor already applied.

Confirms the previously requested extraction (_tool_gate_middleware) that removed duplication between allow-list and blocked-list middleware is in place.


363-383: LGTM!

adapters/hermes/README.md (1)

6-25: LGTM!

adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py (2)

128-138: LGTM!


38-43: 🔒 Security & Privacy

No change needed: disabled_toolsets already wins over enabled_toolsets.
Blocked toolsets cannot be re-enabled through the adapter’s enabled_toolsets path.

			> Likely an incorrect or invalid review comment.
tests/adapters/test_deepagents.py (3)

70-83: LGTM!


414-431: LGTM!


581-636: Good coverage of default-subagent gating and unenforceable-subagent rejection.

test_subagents_are_gated_by_blocked_tools, test_default_subagent_is_gated_by_blocked_tools, and test_blocked_tools_reject_unenforceable_subagents directly exercise the previously-flagged gap (implicit default subagent bypassing tools.blocked) and the new graph_id/runnable rejection path. This addresses the prior reviewer's concern about default subagent enforcement.

tests/adapters/test_hermes_adapter.py (2)

55-126: LGTM!


327-345: LGTM!

adapters/claude/fabric-adapter.json (1)

11-11: 🗄️ Data Integrity & Integration

No change needed for tools.blocked: resolve_capability_plan matches tools.blocked explicitly, and other adapter descriptors already use the same dotted entry.

			> Likely an incorrect or invalid review comment.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 5

Caution

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

⚠️ Outside diff range comments (1)
schemas/run-plan.schema.json (1)

261-264: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Require the normalized tools plan in CapabilityPlan.

default does not make a JSON Schema property required. A plan that omits tools can still validate, contradicting the contract that normalized plans always expose tools and use {} when no policy is configured. Add tools to CapabilityPlan.required and keep Rust serialization aligned.

As per path instructions, schemas must encode the first-class normalized capability_plan.tools field.

Also applies to: 1674-1674

🤖 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 `@schemas/run-plan.schema.json` around lines 261 - 264, Update the
CapabilityPlan schema’s required properties to include tools, while retaining
its default {} behavior for omitted policy configuration. Ensure the
corresponding Rust serialization model emits the normalized
capability_plan.tools field consistently with this required schema contract.

Source: Path instructions

🤖 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 `@adapters/claude/src/nemo_fabric_adapters/claude/adapter.py`:
- Around line 711-804: Reduce the PLR0912/PLR0915 complexity of run_claude by
extracting relay lifecycle logic into focused helpers, such as _start_relay for
gateway startup and _finalize_relay for gateway shutdown, plugin removal, and
cleanup-error construction. Keep query streaming, session persistence, relay
output wrapping, and cleanup-error merging behavior unchanged while moving the
corresponding branches out of run_claude.

In `@adapters/deepagents/README.md`:
- Around line 84-85: Update the preflight-failure description in the README to
identify the condition as “an invalid or unsupported passthrough option,”
preserving the existing references to missing credentials, the absent package,
and invalid MCP servers.

In `@adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py`:
- Around line 414-445: Narrow the _gated_subagents subagents parameter from Any
to list[Any] | None, matching its existing None-or-list validation and
preserving the AdapterConfigError behavior for other runtime values.

In `@README.md`:
- Line 84: Update the README installation instruction to format the package
extra “nemo-fabric[hermes]” as inline code, while leaving the surrounding
wording unchanged.

In `@tests/adapters/test_hermes_adapter.py`:
- Around line 355-470: Add a regression test covering overlapping tool
configuration, with a name present in both tools.blocked and
settings.enabled_toolsets (and, where applicable, disabled_toolsets). In the
adapter.run_hermes test flow, assert the blocked tool is removed from the
enabled_toolsets passed to AIAgent or otherwise cannot execute, preserving
fail-closed behavior.

---

Outside diff comments:
In `@schemas/run-plan.schema.json`:
- Around line 261-264: Update the CapabilityPlan schema’s required properties to
include tools, while retaining its default {} behavior for omitted policy
configuration. Ensure the corresponding Rust serialization model emits the
normalized capability_plan.tools field consistently with this required schema
contract.
🪄 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: 73272b4d-8569-4ca5-bf4a-2ceb3c08f1e4

📥 Commits

Reviewing files that changed from the base of the PR and between 7c7db88 and 4a59a66.

📒 Files selected for processing (21)
  • README.md
  • adapters/claude/README.md
  • adapters/claude/fabric-adapter.json
  • adapters/claude/src/nemo_fabric_adapters/claude/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/utils.py
  • adapters/deepagents/README.md
  • adapters/deepagents/fabric-adapter.json
  • adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py
  • adapters/hermes/README.md
  • adapters/hermes/fabric-adapter.json
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • crates/fabric-core/src/config.rs
  • crates/fabric-core/src/doctor.rs
  • crates/fabric-core/src/runtime.rs
  • docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx
  • schemas/adapter-descriptor.schema.json
  • schemas/run-plan.schema.json
  • tests/adapters/test_claude_adapter.py
  • tests/adapters/test_deepagents.py
  • tests/adapters/test_hermes_adapter.py
  • tests/e2e/test_claude.py
📜 Review details
🔇 Additional comments (34)
crates/fabric-core/src/config.rs (4)

2709-2796: LGTM!


55-103: LGTM!

Also applies to: 432-432, 1690-1701


1607-1638: 🗄️ Data Integrity & Integration

This concern doesn’t apply: the shipped hermes, claude, and deepagents descriptors already declare tools.blocked, so the routing change stays aligned with existing adapter support.

			> Likely an incorrect or invalid review comment.

1920-1922: 🗄️ Data Integrity & Integration

Nothing to change: ToolsPlan.blocked is already omitted when empty. capability_plan.tools still serializes as {} and matches the schema default.

			> Likely an incorrect or invalid review comment.
crates/fabric-core/src/doctor.rs (2)

590-608: Good coverage for fail-closed doctor behavior on unsupported tool policy.

Test correctly asserts that an Unsupported route with kind: Tools escalates the overall report to DoctorStatus::Fail rather than Warn, aligning with the runtime's fail-closed enforcement in runtime.rs.


14-15: LGTM!

Also applies to: 477-480

crates/fabric-core/src/runtime.rs (2)

2053-2083: Test correctly validates fail-closed enforcement at runtime start.

Confirms start_runtime rejects blocked-tools policy when the adapter only declares generic "tools" (not "tools.blocked"), returning FabricError::UnsupportedToolsPolicy. Good defense-in-depth alongside the doctor check in doctor.rs.


21-22: LGTM!

README.md (2)

50-53: LGTM!

Also applies to: 69-75, 77-82, 92-97, 118-120, 146-158, 160-162, 194-196


84-90: 🎯 Functional Correctness

Keep the Hermes install example as-is nemo-fabric[hermes] already pulls in both hermes-agent and nemo-fabric-adapters-hermes; replacing it with nemo-fabric-adapters-hermes would drop Hermes Agent.

			> Likely an incorrect or invalid review comment.
adapters/claude/README.md (1)

24-33: LGTM!

Also applies to: 51-53, 65-65, 77-100, 121-121, 145-145, 191-199

adapters/deepagents/README.md (1)

55-57: LGTM!

Also applies to: 72-83

docs/reference/api/rust-library-reference/fabric-core/config/struct-adapterconfigsupport.mdx (1)

20-20: LGTM!

schemas/adapter-descriptor.schema.json (1)

8-8: LGTM!

Also applies to: 220-220

schemas/run-plan.schema.json (1)

8-8: LGTM!

Also applies to: 617-624, 1611-1636, 1751-1751

adapters/hermes/fabric-adapter.json (1)

18-18: 🗄️ Data Integrity & Integration

Same tools.blocked accepts-path verification as the DeepAgents manifest.

Same concern raised for adapters/deepagents/fabric-adapter.json: confirm the descriptor validator/capability resolver recognizes "tools.blocked" as a distinct accepted path.

adapters/common/src/nemo_fabric_adapters/common/utils.py (3)

8-8: LGTM!

Also applies to: 25-30, 53-56, 61-62, 114-140, 177-184, 196-198, 236-265, 500-537, 541-545


167-198: Line-range metadata conflicts with shown snippet for tools_config/blocked_tools/merge_unique.

The line-range change details describe tools_config, blocked_tools (167-176), and merge_unique (187-195) as newly added logic, but the annotated snippet marks 142-176 and 185-195 as "unchanged... not shown." Since these functions underpin the entire blocked-tools policy (consumed by Claude/Hermes/DeepAgents adapters per the PR description), their actual implementation should be reviewed directly — particularly whether blocked_tools/merge_unique validate input types strictly (a past review comment on the Claude adapter flagged exactly this concern for merge_unique coercing malformed values).


442-497: 🎯 Functional Correctness | 🏗️ Heavy lift

Verify atif sinks aren't silently dropped under observability_version == 2.

relay_cli_plugin_config only converts the atof section into the sink-based v2 format (config["atof"] = {"enabled": ..., "sinks": ...}); the atif section is left untouched even though config["version"] is bumped to 2 for the whole component. If the external Relay CLI's v2 contract expects sink-based config uniformly, ATIF trajectory output configured under atif.enabled=True could be misinterpreted or ignored by a v2 CLI, silently losing trajectory telemetry (the e2e/hermes tests exercise atof+atif together but not through this v2 conversion path).

Please confirm with the NeMo Relay CLI v2 contract docs whether atif requires an analogous sink transform, or whether it intentionally stays in the legacy shape for v2.

adapters/claude/src/nemo_fabric_adapters/claude/adapter.py (1)

14-43: LGTM!

Also applies to: 84-106, 121-167, 216-266, 276-334, 337-437, 440-511, 527-572, 575-588, 641-642, 665-708

adapters/deepagents/fabric-adapter.json (1)

12-12: 🗄️ Data Integrity & Integration

Confirm accepts validation supports the dotted tools.blocked sub-path.

This adds "tools.blocked" alongside the existing "tools" entry. The same pattern appears in the Claude and Hermes descriptors and is asserted by test_claude_descriptor_is_narrow_and_versioned, so it looks intentional, but the descriptor-accepts validation logic (schemas/adapter-descriptor.schema.json, crates/fabric-core capability-plan resolution) isn't in this review's file set. Please confirm the resolver treats "tools.blocked" as a distinct, recognized capability path rather than an unused/no-op string.

Based on a retrieved learning, config.accepts should stay limited to top-level Fabric capability sections consumed by resolve_capability_plan; confirming this dotted form is consumed the same way avoids silently-ignored entries.

Source: Learnings

tests/adapters/test_claude_adapter.py (1)

6-9: LGTM!

Also applies to: 25-25, 30-61, 128-340, 359-415, 418-461, 463-746, 764-772

tests/e2e/test_claude.py (1)

14-27: LGTM!

Also applies to: 32-121, 124-148, 151-214, 220-256

adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (2)

226-235: Shared middleware factory refactor already applied.

Confirms the previously requested extraction (_tool_gate_middleware) that removed duplication between allow-list and blocked-list middleware is in place.


363-383: LGTM!

adapters/hermes/README.md (1)

6-25: LGTM!

adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py (2)

128-138: LGTM!


38-43: 🔒 Security & Privacy

No change needed: disabled_toolsets already wins over enabled_toolsets.
Blocked toolsets cannot be re-enabled through the adapter’s enabled_toolsets path.

			> Likely an incorrect or invalid review comment.
tests/adapters/test_deepagents.py (3)

70-83: LGTM!


414-431: LGTM!


581-636: Good coverage of default-subagent gating and unenforceable-subagent rejection.

test_subagents_are_gated_by_blocked_tools, test_default_subagent_is_gated_by_blocked_tools, and test_blocked_tools_reject_unenforceable_subagents directly exercise the previously-flagged gap (implicit default subagent bypassing tools.blocked) and the new graph_id/runnable rejection path. This addresses the prior reviewer's concern about default subagent enforcement.

tests/adapters/test_hermes_adapter.py (2)

55-126: LGTM!


327-345: LGTM!

adapters/claude/fabric-adapter.json (1)

11-11: 🗄️ Data Integrity & Integration

No change needed for tools.blocked: resolve_capability_plan matches tools.blocked explicitly, and other adapter descriptors already use the same dotted entry.

			> Likely an incorrect or invalid review comment.
🛑 Comments failed to post (5)
adapters/claude/src/nemo_fabric_adapters/claude/adapter.py (1)

711-804: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

run_claude complexity exceeds lint thresholds (22 branches, 56 statements).

The function interleaves relay start/stop, query streaming, session persistence, and multi-stage cleanup-error merging in one body. This is a lifecycle-critical path (gateway process leaks, plugin cleanup, session mismatch) where added complexity increases the risk of subtle regressions on future edits. Consider extracting the relay-start/relay-stop-and-cleanup blocks into dedicated helpers (e.g., _start_relay(...), _finalize_relay(...)) to bring branch/statement counts down and isolate the error-merging logic from the query loop.
Based on learnings and static analysis, ruff flags PLR0912/PLR0915 on this function.

🧰 Tools
🪛 Ruff (0.15.21)

[warning] 711-711: Too many branches (22 > 12)

(PLR0912)


[warning] 711-711: Too many statements (56 > 50)

(PLR0915)

🤖 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 `@adapters/claude/src/nemo_fabric_adapters/claude/adapter.py` around lines 711
- 804, Reduce the PLR0912/PLR0915 complexity of run_claude by extracting relay
lifecycle logic into focused helpers, such as _start_relay for gateway startup
and _finalize_relay for gateway shutdown, plugin removal, and cleanup-error
construction. Keep query streaming, session persistence, relay output wrapping,
and cleanup-error merging behavior unchanged while moving the corresponding
branches out of run_claude.

Source: Linters/SAST tools

adapters/deepagents/README.md (1)

84-85: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Qualify the passthrough failure condition.

The text implies that any passthrough option is a failure, but supported options are documented above. Change this to “an invalid or unsupported passthrough option.”

As per path instructions, documentation must align with current repository behavior and public API.

🤖 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 `@adapters/deepagents/README.md` around lines 84 - 85, Update the
preflight-failure description in the README to identify the condition as “an
invalid or unsupported passthrough option,” preserving the existing references
to missing credentials, the absent package, and invalid MCP servers.

Source: Path instructions

adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py (1)

414-445: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Default subagent gating now addressed.

_gated_subagents now injects a gated general-purpose subagent when none is explicitly configured, and rejects graph_id/runnable subagents outright — this resolves the earlier gap where the implicit default subagent could bypass tools.blocked.

One residual nit: the subagents parameter is typed Any (flagged by Ruff ANN401), while the function body's own logic already assumes/validates it's None | list. A narrower type (list[Any] | None) would match the runtime checks without weakening validation.

🧰 Tools
🪛 Ruff (0.15.21)

[warning] 420-420: Dynamically typed expressions (typing.Any) are disallowed in subagents

(ANN401)


[warning] 426-428: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 433-433: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 436-436: Avoid specifying long messages outside the exception class

(TRY003)


[warning] 438-438: Avoid specifying long messages outside the exception class

(TRY003)

🤖 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 `@adapters/deepagents/src/nemo_fabric_adapters/deepagents/adapter.py` around
lines 414 - 445, Narrow the _gated_subagents subagents parameter from Any to
list[Any] | None, matching its existing None-or-list validation and preserving
the AdapterConfigError behavior for other runtime values.

Source: Linters/SAST tools

README.md (1)

84-84: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Format the package extra as inline code.

As per coding guidelines, package names must use inline code formatting.

Suggested wording
-Install Hermes into its own environment (the nemo-fabric[hermes] extra will install Hermes Agent, and the Hermes Agent adapter but not Fabric itself):
+Install Hermes into its own environment (the `nemo-fabric[hermes]` extra will install Hermes Agent and the Hermes Agent adapter but not Fabric itself):
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Install Hermes into its own environment (the `nemo-fabric[hermes]` extra will install Hermes Agent and the Hermes Agent adapter but not Fabric itself):
🤖 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 `@README.md` at line 84, Update the README installation instruction to format
the package extra “nemo-fabric[hermes]” as inline code, while leaving the
surrounding wording unchanged.

Source: Coding guidelines

tests/adapters/test_hermes_adapter.py (1)

355-470: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider adding coverage for the enabled/disabled toolset overlap case.

None of the tests exercise tools.blocked together with an overlapping enabled_toolsets/disabled_toolsets (e.g., a tool name present in both tools.blocked and settings.enabled_toolsets). Given the concern raised in adapter.py about AIAgent precedence between these two kwargs, a regression test asserting the blocked name is excluded from what's ultimately passed as enabled_toolsets (or otherwise proven non-executable) would directly validate fail-closed behavior.

🧰 Tools
🪛 Ruff (0.15.21)

[warning] 388-388: Prefer dict over useless lambda

Replace with lambda with dict

(PIE807)


[warning] 390-390: Unused lambda argument: force

(ARG005)


[warning] 391-391: Unused lambda argument: args

(ARG005)


[warning] 391-391: Unused lambda argument: kwargs

(ARG005)

🤖 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 `@tests/adapters/test_hermes_adapter.py` around lines 355 - 470, Add a
regression test covering overlapping tool configuration, with a name present in
both tools.blocked and settings.enabled_toolsets (and, where applicable,
disabled_toolsets). In the adapter.run_hermes test flow, assert the blocked tool
is removed from the enabled_toolsets passed to AIAgent or otherwise cannot
execute, preserving fail-closed behavior.

Signed-off-by: Anuradha Karuppiah <26330987+AnuradhaKaruppiah@users.noreply.github.com>
@AnuradhaKaruppiah

Copy link
Copy Markdown
Collaborator Author

Overall looks good, Two policy-enforcement issues should ideally be addressed before merge.

Great review. Addressed all comments.

@AjayThorve

Copy link
Copy Markdown
Collaborator

/merge

@rapids-bot
rapids-bot Bot merged commit bd512a3 into NVIDIA:main Jul 15, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants