Skip to content

feat: move Hermes agent adapter to v1alpha2 - #193

Open
zhongxuanwang-nv wants to merge 9 commits into
NVIDIA:mainfrom
zhongxuanwang-nv:feat/hermes-agent-contract-v1alpha2
Open

feat: move Hermes agent adapter to v1alpha2#193
zhongxuanwang-nv wants to merge 9 commits into
NVIDIA:mainfrom
zhongxuanwang-nv:feat/hermes-agent-contract-v1alpha2

Conversation

@zhongxuanwang-nv

@zhongxuanwang-nv zhongxuanwang-nv commented Aug 10, 2026

Copy link
Copy Markdown
Member

Overview

Moves the Hermes Agent adapter onto the typed fabric.adapter/v1alpha2 agent_config input, now available on main through #190.

Hermes directly imports the internal nemo-fabric-adapter-contract package because it owns the typed lifecycle boundary. This adds no third-party dependency or license change.

Details

  • Deserializes AgentConfig at the lifecycle boundary and maps typed models, instructions, runtime settings, tools, MCP servers, and skills into Hermes configuration.
  • Limits raw lifecycle data to runtime context and invocation data; synchronizes the packaged CLI and Harbor descriptors.
  • Makes Hermes tests portable across Python versions and Windows path separators.

Validation

  • uv run --no-sync pytest tests/adapters/test_hermes_adapter.py tests/adapters/test_hermes_config_builder.py tests/adapters/test_hermes_streaming.py tests/e2e/test_hermes_config_mapping.py tests/adapters/test_adapter_package_metadata.py (49 passed)
  • just test-python (722 passed, 16 skipped)
  • just test-rust
  • Ruff, lockfile, wheel-metadata, attribution, and license-diff checks

Where should the reviewer start?

Start with adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py, especially main, build_hermes_config, and HermesRuntime.start. tests/adapters/test_hermes_adapter.py covers the typed lifecycle boundary; tests/e2e/test_hermes_config_mapping.py covers generated configuration portability.

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

  • Relates to FABRIC-187

  • 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

    • Hermes now accepts validated agent configuration settings.
    • Added support for typed model, tool, skill, workspace, instruction, runtime, telemetry, and MCP settings.
    • Workspace paths and MCP environment values are handled consistently.
    • Hermes sessions support improved startup, invocation, persistence, and cleanup behavior.
  • Bug Fixes

    • Invalid or incomplete configuration is rejected during startup.
    • Model metadata and tool settings are preserved when launching Hermes.
    • Telemetry provider configuration is validated before runtime use.

@coderabbitai

coderabbitai Bot commented Aug 10, 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

The Hermes adapter now consumes validated AgentConfig and RuntimeContext objects. Typed settings configure models, tools, skills, workspaces, instructions, MCP servers, startup, invocation, streaming, and cleanup.

Changes

Hermes AgentConfig Integration

Layer / File(s) Summary
Typed contract wiring
adapters/hermes/fabric-adapter.json, adapters/hermes/pyproject.toml, crates/fabric-cli/assets/adapters/hermes/fabric-adapter.json, examples/harbor/swebench/adapters/hermes/fabric-adapter.json, tests/adapters/test_adapter_package_metadata.py
Hermes declares agent_config input, adds the adapter-contract dependency, and validates package metadata.
Hermes typed configuration and runtime
adapters/hermes/src/.../adapter.py
Configuration generation, lifecycle startup, invocation, relay correlation, model reporting, and cleanup now use typed configuration and runtime state.
Typed validation coverage
tests/adapters/test_hermes_adapter.py, tests/adapters/test_hermes_config_builder.py, tests/adapters/test_hermes_streaming.py, tests/e2e/test_hermes_config_mapping.py
Tests cover typed configuration mapping, MCP conversion, telemetry validation, startup rejection, persistent sessions, streaming, cleanup, and lifecycle wiring.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Lifecycle
  participant AgentConfig
  participant HermesAdapter
  participant MCPServers
  participant AIAgent
  Lifecycle->>AgentConfig: Load and validate configuration
  Lifecycle->>HermesAdapter: Start with AgentConfig and RuntimeContext
  HermesAdapter->>MCPServers: Discover configured MCP servers
  MCPServers-->>HermesAdapter: Return MCP tools
  HermesAdapter->>AIAgent: Create agent with typed settings
  HermesAdapter->>AIAgent: Invoke request with RuntimeContext request ID
  AIAgent-->>HermesAdapter: Return response and model metadata
  HermesAdapter->>Lifecycle: Clear typed state on cleanup
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
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.
Description check ✅ Passed The description includes the required overview, reviewer guidance, related issue action keyword, validation details, and completed contribution checkboxes.
Title check ✅ Passed The title uses valid Conventional Commits format, accurately describes the migration, stays under 72 characters, and has no trailing period.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@github-actions

Copy link
Copy Markdown

@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: 7

Caution

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

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

197-213: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not silently discard MCP tool policy.

AgentMcpServerConfig includes allowed_tools and blocked_tools, but this conversion emits neither field. A configured allowlist or blocklist therefore has no effect, and Hermes can expose tools that the configuration excludes.

Map the policy to supported Hermes fields. If Hermes cannot enforce it, reject nonempty allowed_tools or blocked_tools with an actionable error. Add coverage for both cases.

🤖 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/hermes/src/nemo_fabric_adapters/hermes/adapter.py` around lines 197
- 213, The hermes_mcp_server_config conversion currently drops
AgentMcpServerConfig.allowed_tools and blocked_tools. Map both policies to the
supported Hermes configuration fields; if Hermes does not support either policy,
raise an actionable ValueError whenever the corresponding collection is nonempty
instead of silently ignoring it. Add coverage for nonempty allowlist and
blocklist configurations.

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 `@adapter-contract/pyproject.toml`:
- Around line 27-32: Update the test environment dependency configuration so the
root adapters group installs nemo-fabric-adapter-contract with its pydantic
extra, ensuring the named tests can import pydantic_support without a separate
direct dependency. Regenerate uv.lock after modifying the dependency entry.

In `@adapter-contract/src/nemo_fabric_adapter_contract/codec.py`:
- Around line 43-46: Update the return annotation on
ContractValidationError.prepend to reference ContractValidationError directly
instead of using a quoted string, preserving the existing return behavior.

In `@adapter-contract/src/nemo_fabric_adapter_contract/pydantic_support.py`:
- Line 18: Introduce a separate bounded TypeVar for set_pydantic_extensions,
constrained to the supported contract dataclass type, and use it for that
function’s block parameter and return type. Keep the existing unbounded _T for
type_adapter so its generic behavior remains unchanged.

In `@adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py`:
- Around line 152-158: Update the configuration builder containing the
skill_dirs construction to accept the configuration root, resolve each relative
skill path against that root, and preserve absolute paths unchanged before
assigning config["skills"]["external_dirs"]. Do not expand home-directory
shorthand.

In `@docs/adapter-contract/normalized-configuration.md`:
- Around line 83-84: Update step 3 in the normalized configuration documentation
to name the set_pydantic_extensions helper from
nemo_fabric_adapter_contract.pydantic_support, and mention that it requires the
optional pydantic extra while retaining the existing set_extensions guidance.

In `@tests/adapter_contract/test_agent_execution.py`:
- Around line 120-155: Change
test_agent_execution_dataclasses_track_rust_schema_block_fields to parametrize
individual (filename, model) pairs instead of passing model tuples and looping
inside the test. Keep both field-name and required-field assertions unchanged,
so pytest reports the specific model that diverges from its Rust schema.

In `@tests/adapter_contract/test_dependency_boundary.py`:
- Line 44: Update the subprocess invocation in the dependency-boundary test to
capture the child process’s stdout and stderr, then assert using the captured
output so failures include the traceback and identify the failing import while
preserving the existing non-zero exit validation.

---

Outside diff comments:
In `@adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py`:
- Around line 197-213: The hermes_mcp_server_config conversion currently drops
AgentMcpServerConfig.allowed_tools and blocked_tools. Map both policies to the
supported Hermes configuration fields; if Hermes does not support either policy,
raise an actionable ValueError whenever the corresponding collection is nonempty
instead of silently ignoring it. Add coverage for nonempty allowlist and
blocklist configurations.
🪄 Autofix

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: e76832f5-b51c-42de-810c-6634f56dd134

📥 Commits

Reviewing files that changed from the base of the PR and between 9f0881e and 42a2312.

⛔ Files ignored due to path filters (3)
  • adapter-contract/uv.lock is excluded by !**/*.lock
  • adapters/hermes/uv.lock is excluded by !**/*.lock
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (27)
  • adapter-contract/pypi.md
  • adapter-contract/pyproject.toml
  • adapter-contract/src/nemo_fabric_adapter_contract/codec.py
  • adapter-contract/src/nemo_fabric_adapter_contract/models.py
  • adapter-contract/src/nemo_fabric_adapter_contract/pydantic_support.py
  • adapters/common/README.md
  • adapters/common/src/nemo_fabric_adapters/common/lifecycle.py
  • adapters/hermes/fabric-adapter.json
  • adapters/hermes/pyproject.toml
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • crates/fabric-cli/assets/adapters/hermes/fabric-adapter.json
  • docs/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
  • examples/harbor/swebench/adapters/hermes/fabric-adapter.json
  • external/nat/README.md
  • external/nat/src/nemo_fabric_adapters/nat/adapter.py
  • skills/nemo-fabric-build-adapter/SKILL.md
  • tests/adapter_contract/test_agent_config.py
  • tests/adapter_contract/test_agent_execution.py
  • tests/adapter_contract/test_dependency_boundary.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapters/test_adapters_common_lifecycle.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapters/test_hermes_adapter.py
  • tests/adapters/test_hermes_config_builder.py
  • tests/adapters/test_hermes_streaming.py
  • tests/e2e/test_hermes_config_mapping.py
📜 Review details
⏰ Context from checks skipped due to timeout. (14)
  • GitHub Check: Preview docs
  • GitHub Check: Test (Python 3.12, linux-amd64)
  • GitHub Check: Test (Python 3.11, macos-arm64)
  • GitHub Check: Test (Python 3.11, windows-amd64)
  • GitHub Check: Test (Python 3.13, linux-amd64)
  • GitHub Check: Test (Python 3.13, macos-arm64)
  • GitHub Check: Test (Python 3.12, macos-arm64)
  • GitHub Check: Test (Python 3.11, linux-amd64)
  • GitHub Check: Test (Python 3.13, windows-amd64)
  • GitHub Check: Test (Python 3.12, windows-amd64)
  • GitHub Check: Test (Python 3.14, windows-amd64)
  • GitHub Check: Test (Python 3.13, linux-arm64)
  • GitHub Check: Test (Python 3.11, linux-arm64)
  • GitHub Check: Pre-commit
🧰 Additional context used
📓 Path-based instructions (43)
**/*.{md,rst}

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

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

Files:

  • adapters/common/README.md
  • docs/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
  • adapter-contract/pypi.md
  • skills/nemo-fabric-build-adapter/SKILL.md
  • external/nat/README.md
**/*

📄 CodeRabbit inference engine (.agents/skills/karpathy-guidelines/SKILL.md)

**/*: 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.

**/*: Always spell NVIDIA in all caps; do not use Nvidia, nvidia, nVidia, nVIDIA, or NV.
Use an NVIDIA before a noun, because the name begins with an “en” sound.
Do not add a registered trademark symbol after NVIDIA when referring to the company; use trademark symbols with product names only when required by the document type or legal guidance.
Verify official capitalization, spacing, hyphenation, and spelling for NVIDIA and third-party product names; do not rewrite official product names for grammar or title-case rules.
Precede NVIDIA product names with NVIDIA on first mention when natural and accurate, and link the first mention when the destination helps the reader.
On first use, include the company name and full model qualifier when it helps identify the model; preserve official capitalization and punctuation, and use shorter family names only after establishing the full name.
For learning-oriented and developer content, do not force trademark symbols unless explicitly required; for press, ...

Files:

  • adapters/common/README.md
  • tests/adapter_contract/test_dependency_boundary.py
  • docs/adapter-contract/execution.md
  • adapter-contract/src/nemo_fabric_adapter_contract/pydantic_support.py
  • docs/adapter-contract/normalized-configuration.md
  • adapter-contract/pyproject.toml
  • adapter-contract/pypi.md
  • tests/adapters/test_adapters_common_lifecycle.py
  • skills/nemo-fabric-build-adapter/SKILL.md
  • crates/fabric-cli/assets/adapters/hermes/fabric-adapter.json
  • adapters/hermes/fabric-adapter.json
  • examples/harbor/swebench/adapters/hermes/fabric-adapter.json
  • tests/adapters/test_hermes_config_builder.py
  • external/nat/src/nemo_fabric_adapters/nat/adapter.py
  • adapters/hermes/pyproject.toml
  • tests/adapters/test_hermes_streaming.py
  • tests/e2e/test_hermes_config_mapping.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapter_contract/test_agent_config.py
  • external/nat/README.md
  • adapter-contract/src/nemo_fabric_adapter_contract/codec.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapter_contract/test_agent_execution.py
  • adapter-contract/src/nemo_fabric_adapter_contract/models.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/lifecycle.py
**/*.{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:

  • adapters/common/README.md
  • docs/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
  • adapter-contract/pypi.md
  • skills/nemo-fabric-build-adapter/SKILL.md
  • external/nat/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/common/README.md
  • docs/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
  • adapter-contract/pypi.md
  • skills/nemo-fabric-build-adapter/SKILL.md
  • external/nat/README.md
**/*.{md,mdx,yml,py,rs,sh}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)

Keep documentation aligned with current NeMo Fabric behavior, repository layout, entry points, commands, package names, APIs, bindings, and support claims.

Files:

  • adapters/common/README.md
  • tests/adapter_contract/test_dependency_boundary.py
  • docs/adapter-contract/execution.md
  • adapter-contract/src/nemo_fabric_adapter_contract/pydantic_support.py
  • docs/adapter-contract/normalized-configuration.md
  • adapter-contract/pypi.md
  • tests/adapters/test_adapters_common_lifecycle.py
  • skills/nemo-fabric-build-adapter/SKILL.md
  • tests/adapters/test_hermes_config_builder.py
  • external/nat/src/nemo_fabric_adapters/nat/adapter.py
  • tests/adapters/test_hermes_streaming.py
  • tests/e2e/test_hermes_config_mapping.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapter_contract/test_agent_config.py
  • external/nat/README.md
  • adapter-contract/src/nemo_fabric_adapter_contract/codec.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapter_contract/test_agent_execution.py
  • adapter-contract/src/nemo_fabric_adapter_contract/models.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/lifecycle.py
**/*.{md,mdx}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)

**/*.{md,mdx}: Use the full product name NVIDIA NeMo Fabric on first use, typically in the title and H1; use NeMo Fabric thereafter. Use fabric alone only for the CLI tool and surround it with backticks.
Treat incorrect or stale commands, package names, paths, APIs, support claims, procedures, examples, terminology, or public behavior documentation as blocking issues.
Capitalize NVIDIA correctly and format code, commands, paths, and filenames as inline code where needed.
Use title case for technical-documentation headings.
Introduce code blocks, tables, and lists with complete lead-in sentences; ensure examples match current APIs and build commands.
Use descriptive anchor text, avoid raw URLs and generic labels such as here, and use repository-relative .mdx paths for links within docs/.
Prefer active voice, present tense, short sentences, plain English, consistent terminology, and imperative, parallel, scannable procedures.
Use after instead of once when expressing temporal sequence, and use can rather than may when describing possibility rather than permission.
Avoid ambiguous numeric dates and ordinal dates in body text.
For learning-oriented documentation, do not force trademark symbols unless the source document explicitly requires them.
When reporting documentation-review findings, lead with Must fix, Should fix, and Nice to have categories; include file path, line reference, current problem, rationale, and a concrete rewrite or direction.

Files:

  • adapters/common/README.md
  • docs/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
  • adapter-contract/pypi.md
  • skills/nemo-fabric-build-adapter/SKILL.md
  • external/nat/README.md
**/*.md

📄 CodeRabbit inference engine (CONTRIBUTING.md)

Update relevant SDK, API reference, adapter, example, integration, and support documentation when the corresponding public surface changes.

Files:

  • adapters/common/README.md
  • docs/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
  • adapter-contract/pypi.md
  • skills/nemo-fabric-build-adapter/SKILL.md
  • external/nat/README.md
**/*.{html,md}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

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

Files:

  • adapters/common/README.md
  • docs/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
  • adapter-contract/pypi.md
  • skills/nemo-fabric-build-adapter/SKILL.md
  • external/nat/README.md
adapters/*/{README.md,fabric-adapter.json}

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

Document installation, supported configuration, harness-only settings, credentials, lifecycle, telemetry, artifacts, limitations, and focused test commands; keep documentation consistent with descriptor claims.

Files:

  • adapters/common/README.md
  • adapters/hermes/fabric-adapter.json
adapters/*/README.md

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

Provide a credential-free fixture covering plan, doctor, and run, plus a canonical typed SDK example and, when required, a canonical harness-native YAML fixture.

Files:

  • adapters/common/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 NeMo Fabric contracts.

Files:

  • adapters/common/README.md
  • adapters/hermes/fabric-adapter.json
  • examples/harbor/swebench/adapters/hermes/fabric-adapter.json
  • adapters/hermes/pyproject.toml
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/lifecycle.py
{*.md,**/*.md,**/*.mdx,**/*.ipynb}

⚙️ CodeRabbit configuration file

{*.md,**/*.md,**/*.mdx,**/*.ipynb}: Enforce the product name in user-facing prose: use "NVIDIA NeMo Fabric" on first use and "NeMo Fabric" thereafter. Flag standalone capitalized "Fabric" when it refers to the product. Do not flag the lowercase fabric CLI command, package/import/crate names, code identifiers, API symbols, configuration keys, file paths, or unrelated generic uses of the word.

Files:

  • adapters/common/README.md
  • docs/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
  • adapter-contract/pypi.md
  • skills/nemo-fabric-build-adapter/SKILL.md
  • external/nat/README.md
**/*.{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:

  • tests/adapter_contract/test_dependency_boundary.py
  • adapter-contract/src/nemo_fabric_adapter_contract/pydantic_support.py
  • tests/adapters/test_adapters_common_lifecycle.py
  • crates/fabric-cli/assets/adapters/hermes/fabric-adapter.json
  • adapters/hermes/fabric-adapter.json
  • examples/harbor/swebench/adapters/hermes/fabric-adapter.json
  • tests/adapters/test_hermes_config_builder.py
  • external/nat/src/nemo_fabric_adapters/nat/adapter.py
  • tests/adapters/test_hermes_streaming.py
  • tests/e2e/test_hermes_config_mapping.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapter_contract/test_agent_config.py
  • adapter-contract/src/nemo_fabric_adapter_contract/codec.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapter_contract/test_agent_execution.py
  • adapter-contract/src/nemo_fabric_adapter_contract/models.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/lifecycle.py
**/*.{rs,py}

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

For native binding changes, run cargo check -p fabric-python --locked.

Use snake_case for functions and variables; use PascalCase for Rust types and Python classes.

Files:

  • tests/adapter_contract/test_dependency_boundary.py
  • adapter-contract/src/nemo_fabric_adapter_contract/pydantic_support.py
  • tests/adapters/test_adapters_common_lifecycle.py
  • tests/adapters/test_hermes_config_builder.py
  • external/nat/src/nemo_fabric_adapters/nat/adapter.py
  • tests/adapters/test_hermes_streaming.py
  • tests/e2e/test_hermes_config_mapping.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapter_contract/test_agent_config.py
  • adapter-contract/src/nemo_fabric_adapter_contract/codec.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapter_contract/test_agent_execution.py
  • adapter-contract/src/nemo_fabric_adapter_contract/models.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/lifecycle.py
**/*.{py,pyi}

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

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

In Python SDK, adapters, examples, and tests, follow the existing style, use type annotations for public APIs, and keep native binding declarations synchronized with their Rust implementations.

Files:

  • tests/adapter_contract/test_dependency_boundary.py
  • adapter-contract/src/nemo_fabric_adapter_contract/pydantic_support.py
  • tests/adapters/test_adapters_common_lifecycle.py
  • tests/adapters/test_hermes_config_builder.py
  • external/nat/src/nemo_fabric_adapters/nat/adapter.py
  • tests/adapters/test_hermes_streaming.py
  • tests/e2e/test_hermes_config_mapping.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapter_contract/test_agent_config.py
  • adapter-contract/src/nemo_fabric_adapter_contract/codec.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapter_contract/test_agent_execution.py
  • adapter-contract/src/nemo_fabric_adapter_contract/models.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/lifecycle.py
**/*.{rs,py,pyi}

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

**/*.{rs,py,pyi}: If public configuration types change, confirm schema snapshot tests in just test-rust pass and review generated schema diffs.
For schema or public contract changes, run both language suites and review changes under schemas/ and generated API references.

Files:

  • tests/adapter_contract/test_dependency_boundary.py
  • adapter-contract/src/nemo_fabric_adapter_contract/pydantic_support.py
  • tests/adapters/test_adapters_common_lifecycle.py
  • tests/adapters/test_hermes_config_builder.py
  • external/nat/src/nemo_fabric_adapters/nat/adapter.py
  • tests/adapters/test_hermes_streaming.py
  • tests/e2e/test_hermes_config_mapping.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapter_contract/test_agent_config.py
  • adapter-contract/src/nemo_fabric_adapter_contract/codec.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapter_contract/test_agent_execution.py
  • adapter-contract/src/nemo_fabric_adapter_contract/models.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/lifecycle.py
**/*.{py,pyi,rs}

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

For Python SDK or PyO3 binding changes, use python-tests, run focused pytest tests first, then just test-python; rebuild with just build-python when native code or packaging changes.

Public contract changes must keep native Python binding declarations synchronized with their Rust implementations.

Files:

  • tests/adapter_contract/test_dependency_boundary.py
  • adapter-contract/src/nemo_fabric_adapter_contract/pydantic_support.py
  • tests/adapters/test_adapters_common_lifecycle.py
  • tests/adapters/test_hermes_config_builder.py
  • external/nat/src/nemo_fabric_adapters/nat/adapter.py
  • tests/adapters/test_hermes_streaming.py
  • tests/e2e/test_hermes_config_mapping.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapter_contract/test_agent_config.py
  • adapter-contract/src/nemo_fabric_adapter_contract/codec.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapter_contract/test_agent_execution.py
  • adapter-contract/src/nemo_fabric_adapter_contract/models.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/lifecycle.py
**/*.{rs,py,toml}

📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)

When editing version helpers, verify every nemo-fabric-* workspace package through Cargo metadata and reject a static version in python/pyproject.toml.

Files:

  • tests/adapter_contract/test_dependency_boundary.py
  • adapter-contract/src/nemo_fabric_adapter_contract/pydantic_support.py
  • adapter-contract/pyproject.toml
  • tests/adapters/test_adapters_common_lifecycle.py
  • tests/adapters/test_hermes_config_builder.py
  • external/nat/src/nemo_fabric_adapters/nat/adapter.py
  • adapters/hermes/pyproject.toml
  • tests/adapters/test_hermes_streaming.py
  • tests/e2e/test_hermes_config_mapping.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapter_contract/test_agent_config.py
  • adapter-contract/src/nemo_fabric_adapter_contract/codec.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapter_contract/test_agent_execution.py
  • adapter-contract/src/nemo_fabric_adapter_contract/models.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/lifecycle.py
**/*.{toml,rs,py}

📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)

Avoid blind repository-wide replacement of version-like strings; distinguish package-version references from examples and unrelated dependency versions.

Files:

  • tests/adapter_contract/test_dependency_boundary.py
  • adapter-contract/src/nemo_fabric_adapter_contract/pydantic_support.py
  • adapter-contract/pyproject.toml
  • tests/adapters/test_adapters_common_lifecycle.py
  • tests/adapters/test_hermes_config_builder.py
  • external/nat/src/nemo_fabric_adapters/nat/adapter.py
  • adapters/hermes/pyproject.toml
  • tests/adapters/test_hermes_streaming.py
  • tests/e2e/test_hermes_config_mapping.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapter_contract/test_agent_config.py
  • adapter-contract/src/nemo_fabric_adapter_contract/codec.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapter_contract/test_agent_execution.py
  • adapter-contract/src/nemo_fabric_adapter_contract/models.py
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • tests/adapters/test_hermes_adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/lifecycle.py
tests/**/*.{rs,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

When adding functionality, include tests in the corresponding Rust crate or the relevant area under tests/.

Files:

  • tests/adapter_contract/test_dependency_boundary.py
  • tests/adapters/test_adapters_common_lifecycle.py
  • tests/adapters/test_hermes_config_builder.py
  • tests/adapters/test_hermes_streaming.py
  • tests/e2e/test_hermes_config_mapping.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapter_contract/test_agent_config.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapter_contract/test_agent_execution.py
  • tests/adapters/test_hermes_adapter.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 type annotations to test functions.
When mocking a class, use unittest.mock.MagicMock or AsyncMock, using the spec argument when necessary, rather than defining a new class.
Prefix mocked class names with mock, not fake.
Prefer pytest fixtures over helper methods.
If a fixture is needed in multiple test files, define it once in conftest.py rather than repeating it.
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 returned value is unused or it returns no value.
Avoid defensive programming in tests; access expected values directly so missing data raises a clear failure, such as using results["data"] instead of results.get("data").
When adapter installation metadata changes, packaging metadata tests must directly assert that the root project depends unconditionally on the exact-version nemo-fabric-runtime distribution.
Packaging metadata tests must verify that each root harness extra delegates to the matching version of the leaf adapter's harness extra.
Packaging metadata tests must verify that bare leaf dependencies remain adapter-owned and that the root adapter-tests dependency group installs each leaf through its harness extra.
Packaging metadata tests must verify that every leaf provides full; only adapters importing NeMo Relay Python APIs provide relay, while adapters using an external Relay executable have full equal to harness.

Files:

  • tests/adapter_contract/test_dependency_boundary.py
  • tests/adapters/test_adapters_common_lifecycle.py
  • tests/adapters/test_hermes_config_builder.py
  • tests/adapters/test_hermes_streaming.py
  • tests/e2e/test_hermes_config_mapping.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapter_contract/test_agent_config.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapter_contract/test_agent_execution.py
  • tests/adapters/test_hermes_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/adapter_contract/test_dependency_boundary.py
  • tests/adapters/test_adapters_common_lifecycle.py
  • tests/adapters/test_hermes_config_builder.py
  • tests/adapters/test_hermes_streaming.py
  • tests/e2e/test_hermes_config_mapping.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapter_contract/test_agent_config.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapter_contract/test_agent_execution.py
  • tests/adapters/test_hermes_adapter.py
{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/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.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/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
docs/**/*.{md,mdx,yml}

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

Run just docs when the documentation site changes.

Files:

  • docs/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
docs/**

📄 CodeRabbit inference engine (AGENTS.md)

Run just docs after changing the documentation site.

Files:

  • docs/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
{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.
For links between files under docs/, require paths relative to the source file with the target file's .mdx extension so they work in both Fern builds and repository browsers. Flag Fern site-root links such as NeMo Fabric overview; use the repository-relative equivalent, such as NeMo Fabric overview.

Files:

  • docs/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
**/*.{rs,toml}

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

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

For Rust core, CLI, or shared runtime semantic changes, run Rust formatting and tests, and add Python tests when behavior is exposed through the SDK.

Use Rust stable tooling; format Rust code with cargo fmt --all, verify formatting with cargo fmt --all -- --check, and compile with cargo check --workspace --locked.

Files:

  • adapter-contract/pyproject.toml
  • adapters/hermes/pyproject.toml
**/{Cargo.toml,Cargo.lock,pyproject.toml,package.json}

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

For new or updated dependencies, document the functional need, alternatives considered, and why the selected dependency is the narrowest fit.

Files:

  • adapter-contract/pyproject.toml
  • adapters/hermes/pyproject.toml
**/*.{toml,lock}

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

If a manifest or lockfile changes, run the license-diff script against origin/main, review transitive license changes, and run the attributions-rust and attributions-python pre-commit hooks.

Files:

  • adapter-contract/pyproject.toml
  • adapters/hermes/pyproject.toml
**/*.{yml,yaml,toml,lock}

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

For CI or packaging changes, use maintain-ci or maintain-packaging, then run recipes and checks whose behavior changed.

Files:

  • adapter-contract/pyproject.toml
  • adapters/hermes/pyproject.toml
**/*.{toml,yaml,yml,sh,bash}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

TOML, YAML, and shell files must use the specified # SPDX copyright and Apache-2.0 license headers.

Files:

  • adapter-contract/pyproject.toml
  • adapters/hermes/pyproject.toml
**/{Cargo.toml,pyproject.toml}

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

**/{Cargo.toml,pyproject.toml}: Keep package names, dependency declarations, import paths, module names, and workspace or Python package metadata internally consistent.
Prefer the standard library, an existing dependency, or a small local implementation before adding a new direct dependency.
When multiple dependencies satisfy the requirement, prefer a maintained OSS option with clear SPDX metadata, a smaller transitive graph, and permissive licensing such as Apache-2.0, MIT, BSD, or ISC.

Files:

  • adapter-contract/pyproject.toml
  • adapters/hermes/pyproject.toml
**/{Cargo.toml,pyproject.toml,Cargo.lock,uv.lock}

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

**/{Cargo.toml,pyproject.toml,Cargo.lock,uv.lock}: For new dependencies, record the functional need, viable alternatives considered, why the selected dependency is the narrowest fit, and any unresolved licensing question.
After updating manifests or lockfiles, run uv run --no-project python scripts/licensing/license_diff.py --base-ref origin/main and review added packages and license changes.
Keep workspace, Python package, and lockfile versions aligned wherever the packaging contract requires alignment.

Files:

  • adapter-contract/pyproject.toml
  • adapters/hermes/pyproject.toml
tests/adapters/**/*.py

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

tests/adapters/**/*.py: If an adapter or integration changes, run its focused tests.
For adapter behavior changes, run focused adapter tests under tests/adapters, then run just test-python.

Files:

  • tests/adapters/test_adapters_common_lifecycle.py
  • tests/adapters/test_hermes_config_builder.py
  • tests/adapters/test_hermes_streaming.py
  • tests/adapters/test_adapter_package_metadata.py
  • tests/adapters/test_external_nat_adapter.py
  • tests/adapters/test_hermes_adapter.py
**/SKILL.md

📄 CodeRabbit inference engine (.agents/skills/README.md)

Each maintainer skill file must begin with YAML frontmatter containing at least name and description.

Files:

  • skills/nemo-fabric-build-adapter/SKILL.md

⚙️ CodeRabbit configuration file

**/SKILL.md: Do not flag SKILL.md files for missing SPDX headers. Skill entrypoints intentionally start with YAML frontmatter instead.
Verify that every SKILL.md keeps valid YAML frontmatter with at least name and description fields before the Markdown body.

Files:

  • skills/nemo-fabric-build-adapter/SKILL.md
skills/**

📄 CodeRabbit inference engine (AGENTS.md)

skills/**: Keep consumer skills self-contained and dependent only on supported public Python SDK contracts and published documentation; do not include repository internals.
Do not add repository-internal contribution guidance to consumer skills.
Consumer skills must link to public GitHub documentation and example URLs rather than a docs-site domain so they remain portable when exported.

Files:

  • skills/nemo-fabric-build-adapter/SKILL.md
**/*.{json,jsonschema}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

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

Files:

  • crates/fabric-cli/assets/adapters/hermes/fabric-adapter.json
  • adapters/hermes/fabric-adapter.json
  • examples/harbor/swebench/adapters/hermes/fabric-adapter.json
adapters/*/fabric-adapter.json

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

Define a narrow, truthful adapter descriptor; keep config.accepts, config.generates, requirements, telemetry declarations, lifecycle capabilities, and advertised capabilities synchronized with implementation and tests.

Files:

  • adapters/hermes/fabric-adapter.json
{pyproject.toml,adapters/**/pyproject.toml}

📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)

{pyproject.toml,adapters/**/pyproject.toml}: Update the literal project.version in the root setuptools project and every adapter pyproject.toml.
Keep internal exact-version requirements aligned: root nemo-fabric-* == <version> optional dependencies and each adapter's nemo-fabric-adapters-common == <version> dependency.

Files:

  • adapters/hermes/pyproject.toml
adapters/*/pyproject.toml

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

adapters/*/pyproject.toml: Keep leaf adapter runtime dependencies razor-thin and adapter-owned. Do not declare the wrapped harness/SDK or dependencies already declared by its supported package; provide dependency-free fallbacks for optional libraries.
Provide every installable Python leaf adapter with a harness extra and a full extra for package-installable integrations; provide a relay extra when importing NeMo Relay Python APIs, but not when Relay is an external executable.
For packaged harnesses, declare and document a harness version constraint supported by upstream contracts and test evidence; do not claim a broader range than the evidence supports.

Files:

  • adapters/hermes/pyproject.toml
adapters/*/{pyproject.toml,uv.lock}

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

Keep each adapter package independent and small, using Python package metadata and lock files as applicable.

Files:

  • adapters/hermes/pyproject.toml
adapters/*/src/**/*.py

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

adapters/*/src/**/*.py: Implement adapters using the existing Fabric python or process runner and normalized request/result contracts; do not add a runner or one-off abstraction for a single adapter.
Treat normalized config, Fabric-resolved plans, and runtime_context as authoritative; reserve harness.settings for adapter-wide behavior and apply precedence in the order: normalized config, plans/context, harness settings, descriptor/default values.
Reject conflicting duplicate declarations and unsupported behavior with actionable errors naming the field and supported alternatives; never silently drop configuration.
Validate dependency versions, hooks, and credentials before harness invocation, and never expose credential values in outputs, errors, events, logs, or fixtures.
Forward only required system, selected credential, telemetry, and documented harness-specific environment variables; never forward or log unrelated environment values.
Maintain one local adapter host per Fabric runtime across ordered startinvoke*stop operations. Emit one JSON lifecycle response per request on stdout and diagnostics on stderr.
Return harness-level invocation failures as successful lifecycle responses containing response: null, failed: true, and structured error fields (code, message, retryable, and optional metadata).
Do not emit NeMo Relay stream records on adapter stdout; return exactly one terminal lifecycle response while streaming occurs through the SDK-owned out-of-band endpoint.
Scope workspace, generated configuration, state, sessions, and artifacts to the resolved runtime context, and isolate stateful adapter instances by Fabric runtime ID.
Use start to initialize adapter-owned harness state, retain it for continuation across repeated invoke calls on the same runtime, and release it in stop.

Files:

  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
  • adapters/common/src/nemo_fabric_adapters/common/lifecycle.py
🧠 Learnings (4)
📚 Learning: 2026-08-07T07:15:59.993Z
Learnt from: AnuradhaKaruppiah
Repo: NVIDIA/NeMo-Fabric PR: 186
File: docs/adapter-contract/registration-and-discovery.md:103-104
Timestamp: 2026-08-07T07:15:59.993Z
Learning: Keep documentation files under docs/adapter-contract/ in portable Markdown (.md), not MDX. GitHub and the public authoring skill consume these files directly, and the NVIDIA NeMo Fabric documentation pipeline accepts them without conversion; do not flag the lack of MDX conversion for these files.

Applied to files:

  • docs/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
📚 Learning: 2026-08-07T16:20:01.603Z
Learnt from: AnuradhaKaruppiah
Repo: NVIDIA/NeMo-Fabric PR: 186
File: docs/adapter-contract/README.md:1-4
Timestamp: 2026-08-07T16:20:01.603Z
Learning: For maintained Markdown files under docs/adapter-contract/, Fern parses content as MDX. Write SPDX license headers as JSX comments (`{/* ... */}`), not HTML comments, because HTML comments cause Fern parsing failures. This JSX form is accepted by the repository copyright checker and validated by Docs Preview.

Applied to files:

  • docs/adapter-contract/execution.md
  • docs/adapter-contract/normalized-configuration.md
📚 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:

  • crates/fabric-cli/assets/adapters/hermes/fabric-adapter.json
  • adapters/hermes/fabric-adapter.json
  • examples/harbor/swebench/adapters/hermes/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
🪛 ast-grep (0.45.0)
tests/adapter_contract/test_dependency_boundary.py

[error] 43-43: Command coming from incoming request
Context: subprocess.run([sys.executable, "-c", script], check=True, env=env)
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(subprocess-from-request)

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

[info] 428-428: use jsonify instead of json.dumps for JSON output
Context: json.dumps(user_message, sort_keys=True)
Note: [CWE-116] Improper Encoding or Escaping of Output.

(use-jsonify)

🪛 Ruff (0.16.1)
tests/adapter_contract/test_dependency_boundary.py

[error] 44-44: subprocess call: check for execution of untrusted input

(S603)

adapter-contract/src/nemo_fabric_adapter_contract/pydantic_support.py

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

(TRY003)

tests/e2e/test_hermes_config_mapping.py

[error] 66-66: Probable insecure usage of temporary file or directory: "/tmp/fabric-skills/code-review"

(S108)

adapter-contract/src/nemo_fabric_adapter_contract/codec.py

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

Remove quotes

(UP037)


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

(ANN401)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(ANN401)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(ANN401)


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

(ANN401)


[warning] 158-158: Too many return statements (18 > 6)

(PLR0911)


[warning] 158-158: Too many branches (33 > 12)

(PLR0912)


[warning] 158-158: Too many statements (58 > 50)

(PLR0915)


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

(ANN401)


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

(ANN401)


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

(ANN401)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(TRY003)


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

(ANN401)


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

(ANN401)

adapter-contract/src/nemo_fabric_adapter_contract/models.py

[warning] 27-27: Missing return type annotation for private function _optional

(ANN202)


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

(ANN401)


[warning] 31-31: Missing return type annotation for private function _empty_dict

(ANN202)


[warning] 35-35: Missing return type annotation for private function _json_dict

(ANN202)


[warning] 39-39: Missing return type annotation for private function _empty_list

(ANN202)


[warning] 43-43: Missing return type annotation for private function _json_value_field

(ANN202)


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

(ANN401)


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

(TRY003)


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

(TRY003)


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

(ANN401)


[warning] 99-99: Do not perform function call _json_dict in dataclass defaults

(RUF009)


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

(TRY003)


[warning] 117-117: Do not perform function call _json_dict in dataclass defaults

(RUF009)


[warning] 129-129: Do not perform function call _json_dict in dataclass defaults

(RUF009)


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

(TRY003)


[warning] 163-163: Do not perform function call _optional in dataclass defaults

(RUF009)


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

(TRY003)


[warning] 184-184: Do not perform function call _empty_list in dataclass defaults

(RUF009)


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

(TRY003)


[warning] 201-201: Do not perform function call _empty_list in dataclass defaults

(RUF009)


[warning] 202-202: Do not perform function call _empty_dict in dataclass defaults

(RUF009)


[warning] 203-203: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 204-204: Do not perform function call _empty_list in dataclass defaults

(RUF009)


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

(TRY003)


[warning] 224-224: Do not perform function call _empty_dict in dataclass defaults

(RUF009)


[warning] 233-233: Do not perform function call _json_dict in dataclass defaults

(RUF009)


[warning] 244-244: Do not perform function call _empty_dict in dataclass defaults

(RUF009)


[warning] 245-245: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 246-246: Do not perform function call _empty_list in dataclass defaults

(RUF009)


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

(TRY003)


[warning] 277-277: Do not perform function call _json_dict in dataclass defaults

(RUF009)


[warning] 284-284: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 285-285: Do not perform function call _empty_dict in dataclass defaults

(RUF009)


[warning] 286-286: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 287-287: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 288-288: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 289-289: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 290-290: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 291-291: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 298-298: Do not perform function call _json_value_field in dataclass defaults

(RUF009)


[warning] 299-299: Do not perform function call _json_dict in dataclass defaults

(RUF009)


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

(TRY003)


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

(TRY003)


[warning] 382-382: Do not perform function call _json_value_field in dataclass defaults

(RUF009)


[warning] 383-383: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 384-384: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 385-385: Do not perform function call _empty_list in dataclass defaults

(RUF009)


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

(TRY003)


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

(TRY003)


[warning] 415-415: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 416-416: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 417-417: Do not perform function call _empty_dict in dataclass defaults

(RUF009)


[warning] 419-419: Do not perform function call _json_dict in dataclass defaults

(RUF009)


[warning] 420-420: Do not perform function call _json_dict in dataclass defaults

(RUF009)


[warning] 435-435: Do not perform function call _json_dict in dataclass defaults

(RUF009)


[warning] 448-448: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 449-449: Do not perform function call _empty_list in dataclass defaults

(RUF009)


[warning] 457-457: Do not perform function call _optional in dataclass defaults

(RUF009)


[warning] 458-458: Do not perform function call _empty_dict in dataclass defaults

(RUF009)


[warning] 459-459: Do not perform function call _json_dict in dataclass defaults

(RUF009)


[warning] 471-471: Do not perform function call _optional in dataclass defaults

(RUF009)

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

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

(TRY003)


[warning] 295-298: Abstract raise to an inner function

(TRY301)


[warning] 339-339: Abstract raise to an inner function

(TRY301)


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

(TRY003)

Comment thread adapter-contract/pyproject.toml
Comment thread adapter-contract/src/nemo_fabric_adapter_contract/codec.py
Comment thread adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
Comment thread docs/adapter-contract/normalized-configuration.md
Comment thread tests/adapter_contract/test_agent_execution.py
Comment thread tests/adapter_contract/test_dependency_boundary.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.

Caution

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

⚠️ Outside diff range comments (1)
tests/adapters/test_hermes_adapter.py (1)

67-87: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Validate all Hermes descriptor copies in the test. Assert contract_version, config.input, and config.accepts for all three descriptor paths. The current test reads only adapters/hermes/fabric-adapter.json, so packaged copies can drift undetected.

🤖 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 67 - 87, Update
test_descriptor_uses_the_typed_agent_config_contract to load and validate all
three Hermes descriptor paths, including packaged copies, rather than only
adapters/hermes/fabric-adapter.json. For each descriptor, assert
contract_version, config.input, and the complete expected config.accepts list
using the same values already defined in the test.
🤖 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.

Outside diff comments:
In `@tests/adapters/test_hermes_adapter.py`:
- Around line 67-87: Update test_descriptor_uses_the_typed_agent_config_contract
to load and validate all three Hermes descriptor paths, including packaged
copies, rather than only adapters/hermes/fabric-adapter.json. For each
descriptor, assert contract_version, config.input, and the complete expected
config.accepts list using the same values already defined in the test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 63c8dbfc-1f3c-4c29-bd51-b76d774b2a93

📥 Commits

Reviewing files that changed from the base of the PR and between 42a2312 and 81044d8.

📒 Files selected for processing (1)
  • tests/adapters/test_hermes_adapter.py
📜 Review details
⏰ Context from checks skipped due to timeout. (18)
  • GitHub Check: Preview docs
  • GitHub Check: Test (Python 3.13, windows-amd64)
  • GitHub Check: Test (Python 3.12, windows-amd64)
  • GitHub Check: Test (Python 3.11, windows-amd64)
  • GitHub Check: Test (Python 3.14, windows-amd64)
  • GitHub Check: Test (Python 3.12, macos-arm64)
  • GitHub Check: Test (Python 3.11, macos-arm64)
  • GitHub Check: Test (Python 3.12, linux-arm64)
  • GitHub Check: Test (Python 3.14, macos-arm64)
  • GitHub Check: Test (Python 3.13, macos-arm64)
  • GitHub Check: Test (Python 3.12, linux-amd64)
  • GitHub Check: Test (Python 3.13, linux-arm64)
  • GitHub Check: Test (Python 3.13, linux-amd64)
  • GitHub Check: Test (Python 3.14, linux-arm64)
  • GitHub Check: Test (Python 3.11, linux-arm64)
  • GitHub Check: Test (Python 3.14, linux-amd64)
  • GitHub Check: Test (Python 3.11, linux-amd64)
  • GitHub Check: Pre-commit
🧰 Additional context used
📓 Path-based instructions (13)
**/*.{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:

  • tests/adapters/test_hermes_adapter.py
**/*

📄 CodeRabbit inference engine (.agents/skills/karpathy-guidelines/SKILL.md)

**/*: 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.

**/*: Always spell NVIDIA in all caps; do not use Nvidia, nvidia, nVidia, nVIDIA, or NV.
Use an NVIDIA before a noun, because the name begins with an “en” sound.
Do not add a registered trademark symbol after NVIDIA when referring to the company; use trademark symbols with product names only when required by the document type or legal guidance.
Verify official capitalization, spacing, hyphenation, and spelling for NVIDIA and third-party product names; do not rewrite official product names for grammar or title-case rules.
Precede NVIDIA product names with NVIDIA on first mention when natural and accurate, and link the first mention when the destination helps the reader.
On first use, include the company name and full model qualifier when it helps identify the model; preserve official capitalization and punctuation, and use shorter family names only after establishing the full name.
For learning-oriented and developer content, do not force trademark symbols unless explicitly required; for press, ...

Files:

  • tests/adapters/test_hermes_adapter.py
**/*.{rs,py}

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

For native binding changes, run cargo check -p fabric-python --locked.

Use snake_case for functions and variables; use PascalCase for Rust types and Python classes.

Files:

  • tests/adapters/test_hermes_adapter.py
**/*.{py,pyi}

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

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

In Python SDK, adapters, examples, and tests, follow the existing style, use type annotations for public APIs, and keep native binding declarations synchronized with their Rust implementations.

Files:

  • tests/adapters/test_hermes_adapter.py
**/*.{rs,py,pyi}

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

**/*.{rs,py,pyi}: If public configuration types change, confirm schema snapshot tests in just test-rust pass and review generated schema diffs.
For schema or public contract changes, run both language suites and review changes under schemas/ and generated API references.

Files:

  • tests/adapters/test_hermes_adapter.py
tests/adapters/**/*.py

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

tests/adapters/**/*.py: If an adapter or integration changes, run its focused tests.
For adapter behavior changes, run focused adapter tests under tests/adapters, then run just test-python.

Files:

  • tests/adapters/test_hermes_adapter.py
**/*.{py,pyi,rs}

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

For Python SDK or PyO3 binding changes, use python-tests, run focused pytest tests first, then just test-python; rebuild with just build-python when native code or packaging changes.

Public contract changes must keep native Python binding declarations synchronized with their Rust implementations.

Files:

  • tests/adapters/test_hermes_adapter.py
**/*.{rs,py,toml}

📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)

When editing version helpers, verify every nemo-fabric-* workspace package through Cargo metadata and reject a static version in python/pyproject.toml.

Files:

  • tests/adapters/test_hermes_adapter.py
**/*.{toml,rs,py}

📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)

Avoid blind repository-wide replacement of version-like strings; distinguish package-version references from examples and unrelated dependency versions.

Files:

  • tests/adapters/test_hermes_adapter.py
**/*.{md,mdx,yml,py,rs,sh}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)

Keep documentation aligned with current NeMo Fabric behavior, repository layout, entry points, commands, package names, APIs, bindings, and support claims.

Files:

  • tests/adapters/test_hermes_adapter.py
tests/**/*.{rs,py}

📄 CodeRabbit inference engine (CONTRIBUTING.md)

When adding functionality, include tests in the corresponding Rust crate or the relevant area under tests/.

Files:

  • tests/adapters/test_hermes_adapter.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 type annotations to test functions.
When mocking a class, use unittest.mock.MagicMock or AsyncMock, using the spec argument when necessary, rather than defining a new class.
Prefix mocked class names with mock, not fake.
Prefer pytest fixtures over helper methods.
If a fixture is needed in multiple test files, define it once in conftest.py rather than repeating it.
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 returned value is unused or it returns no value.
Avoid defensive programming in tests; access expected values directly so missing data raises a clear failure, such as using results["data"] instead of results.get("data").
When adapter installation metadata changes, packaging metadata tests must directly assert that the root project depends unconditionally on the exact-version nemo-fabric-runtime distribution.
Packaging metadata tests must verify that each root harness extra delegates to the matching version of the leaf adapter's harness extra.
Packaging metadata tests must verify that bare leaf dependencies remain adapter-owned and that the root adapter-tests dependency group installs each leaf through its harness extra.
Packaging metadata tests must verify that every leaf provides full; only adapters importing NeMo Relay Python APIs provide relay, while adapters using an external Relay executable have full equal to harness.

Files:

  • tests/adapters/test_hermes_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_hermes_adapter.py
🔇 Additional comments (3)
tests/adapters/test_hermes_adapter.py (3)

32-35: LGTM!

Also applies to: 193-230, 280-303, 343-378, 412-440, 502-509, 519-529, 545-555, 627-640, 654-665, 744-756, 767-768, 826-826, 847-850


18-19: 🩺 Stability & Availability

Remove this comment

			> Likely an incorrect or invalid review comment.

567-596: 🗄️ Data Integrity & Integration

Retain the current coverage. AgentConfig.from_mapping is the intended normalization boundary. Lifecycle tests cover valid conversion and invalid mappings before runtime creation, and Hermes tests cover direct rejection of untyped configuration. No additional nested-mapping rejection test is required here.

Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
@zhongxuanwang-nv
zhongxuanwang-nv force-pushed the feat/hermes-agent-contract-v1alpha2 branch from 81044d8 to af9716f Compare August 11, 2026 00:40
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.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: 1

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

Inline comments:
In `@adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py`:
- Around line 302-305: Update the environment setup in the Hermes adapter
initialization to assign TERMINAL_TIMEOUT from the normalized runtime
configuration, replacing setdefault so each runtime’s
harness.settings.terminal_timeout or default value is authoritative. Add a
regression test that starts two runtimes sequentially with different timeout
values and verifies the second runtime applies its own timeout.
🪄 Autofix

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: cb72a2fe-5a31-420c-a27b-8acb4e068931

📥 Commits

Reviewing files that changed from the base of the PR and between 6866910 and 77cc52f.

📒 Files selected for processing (1)
  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
📜 Review details
⏰ Context from checks skipped due to timeout. (19)
  • GitHub Check: Preview docs
  • GitHub Check: Test (Python 3.13, macos-arm64)
  • GitHub Check: Test (Python 3.13, windows-amd64)
  • GitHub Check: Test (Python 3.14, macos-arm64)
  • GitHub Check: Test (Python 3.11, linux-amd64)
  • GitHub Check: Test (Python 3.12, macos-arm64)
  • GitHub Check: Test (Python 3.13, linux-amd64)
  • GitHub Check: Test (Python 3.11, macos-arm64)
  • GitHub Check: Test (Python 3.12, windows-amd64)
  • GitHub Check: Test (Python 3.11, windows-amd64)
  • GitHub Check: Test (Python 3.11, linux-arm64)
  • GitHub Check: Test (Python 3.12, linux-arm64)
  • GitHub Check: Test (Python 3.12, linux-amd64)
  • GitHub Check: Test (Python 3.14, linux-amd64)
  • GitHub Check: Test (Python 3.14, windows-amd64)
  • GitHub Check: Test (Python 3.13, linux-arm64)
  • GitHub Check: Test (arm64)
  • GitHub Check: Test (Python 3.14, linux-arm64)
  • GitHub Check: Pre-commit
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{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/src/nemo_fabric_adapters/hermes/adapter.py
**/*

📄 CodeRabbit inference engine (.agents/skills/karpathy-guidelines/SKILL.md)

**/*: 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.

**/*: Always spell NVIDIA in all caps; do not use Nvidia, nvidia, nVidia, nVIDIA, or NV.
Use an NVIDIA before a noun, because the name begins with an “en” sound.
Do not add a registered trademark symbol after NVIDIA when referring to the company; use trademark symbols with product names only when required by the document type or legal guidance.
Verify official capitalization, spacing, hyphenation, and spelling for NVIDIA and third-party product names; do not rewrite official product names for grammar or title-case rules.
Precede NVIDIA product names with NVIDIA on first mention when natural and accurate, and link the first mention when the destination helps the reader.
On first use, include the company name and full model qualifier when it helps identify the model; preserve official capitalization and punctuation, and use shorter family names only after establishing the full name.
For learning-oriented and developer content, do not force trademark symbols unless explicitly required; for press, ...

Files:

  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
**/*.{rs,py}

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

For native binding changes, run cargo check -p fabric-python --locked.

Use snake_case for functions and variables; use PascalCase for Rust types and Python classes.

Files:

  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
**/*.{py,pyi}

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

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

In Python SDK, adapters, examples, and tests, follow the existing style, use type annotations for public APIs, and keep native binding declarations synchronized with their Rust implementations.

Files:

  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
**/*.{rs,py,pyi}

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

**/*.{rs,py,pyi}: If public configuration types change, confirm schema snapshot tests in just test-rust pass and review generated schema diffs.
For schema or public contract changes, run both language suites and review changes under schemas/ and generated API references.

Files:

  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
**/*.{py,pyi,rs}

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

For Python SDK or PyO3 binding changes, use python-tests, run focused pytest tests first, then just test-python; rebuild with just build-python when native code or packaging changes.

Public contract changes must keep native Python binding declarations synchronized with their Rust implementations.

Files:

  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
**/*.{rs,py,toml}

📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)

When editing version helpers, verify every nemo-fabric-* workspace package through Cargo metadata and reject a static version in python/pyproject.toml.

Files:

  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
**/*.{toml,rs,py}

📄 CodeRabbit inference engine (.agents/skills/update-project-version/SKILL.md)

Avoid blind repository-wide replacement of version-like strings; distinguish package-version references from examples and unrelated dependency versions.

Files:

  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
**/*.{md,mdx,yml,py,rs,sh}

📄 CodeRabbit inference engine (.agents/skills/review-doc-style/SKILL.md)

Keep documentation aligned with current NeMo Fabric behavior, repository layout, entry points, commands, package names, APIs, bindings, and support claims.

Files:

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

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

adapters/*/src/**/*.py: Implement adapters using the existing Fabric python or process runner and normalized request/result contracts; do not add a runner or one-off abstraction for a single adapter.
Treat normalized config, Fabric-resolved plans, and runtime_context as authoritative; reserve harness.settings for adapter-wide behavior and apply precedence in the order: normalized config, plans/context, harness settings, descriptor/default values.
Reject conflicting duplicate declarations and unsupported behavior with actionable errors naming the field and supported alternatives; never silently drop configuration.
Validate dependency versions, hooks, and credentials before harness invocation, and never expose credential values in outputs, errors, events, logs, or fixtures.
Forward only required system, selected credential, telemetry, and documented harness-specific environment variables; never forward or log unrelated environment values.
Maintain one local adapter host per Fabric runtime across ordered startinvoke*stop operations. Emit one JSON lifecycle response per request on stdout and diagnostics on stderr.
Return harness-level invocation failures as successful lifecycle responses containing response: null, failed: true, and structured error fields (code, message, retryable, and optional metadata).
Do not emit NeMo Relay stream records on adapter stdout; return exactly one terminal lifecycle response while streaming occurs through the SDK-owned out-of-band endpoint.
Scope workspace, generated configuration, state, sessions, and artifacts to the resolved runtime context, and isolate stateful adapter instances by Fabric runtime ID.
Use start to initialize adapter-owned harness state, retain it for continuation across repeated invoke calls on the same runtime, and release it in stop.

Files:

  • adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.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 NeMo Fabric contracts.

Files:

  • adapters/hermes/src/nemo_fabric_adapters/hermes/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/hermes/src/nemo_fabric_adapters/hermes/adapter.py
🪛 Ruff (0.16.1)
adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py

[warning] 330-330: Abstract raise to an inner function

(TRY301)


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

(TRY003)


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

(ANN401)


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

(ANN401)

🔇 Additional comments (1)
adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py (1)

284-286: LGTM!

Also applies to: 324-331, 359-384, 420-428, 468-468, 598-612

Comment thread adapters/hermes/src/nemo_fabric_adapters/hermes/adapter.py
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
@zhongxuanwang-nv zhongxuanwang-nv self-assigned this Aug 11, 2026
@zhongxuanwang-nv zhongxuanwang-nv added this to the 0.2 milestone Aug 11, 2026
@zhongxuanwang-nv
zhongxuanwang-nv marked this pull request as ready for review August 11, 2026 02:33
@zhongxuanwang-nv
zhongxuanwang-nv requested a review from a team as a code owner August 11, 2026 02:33
Signed-off-by: Zhongxuan Wang <daniewang@nvidia.com>
@zhongxuanwang-nv zhongxuanwang-nv changed the title feat: migrate Hermes adapter to typed contract feat: move Hermes agent adapter to v1alpha2 Aug 11, 2026

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

Looks pretty good, approved!

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