Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 33 additions & 7 deletions .agents/skills/contribute-adapter/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,38 @@ Decide the following before implementation:
point, and focused tests. For Python, use `pyproject.toml`, `uv.lock`,
`src/nemo_fabric_adapters/<name>/adapter.py`, and
`tests/adapters/test_<name>*.py`. Keep the package independent and small.
- Keep published runtime dependencies (`[project].dependencies` for Python)
razor-thin and adapter-owned. For an SDK/module boundary, declare every runtime
library the adapter host directly imports, including SDK/client libraries. For
an external process or separately managed harness environment, do not install
or upgrade the harness or consumer agent environment; keep test-only
dependencies in a non-published, language-native group
(`[dependency-groups]` for UV/Python).
- Keep each published leaf adapter's runtime dependencies
(`[project].dependencies` for Python) razor-thin and adapter-owned. Do not
declare the wrapped harness/SDK or dependencies directly declared by its
supported package. Do not treat incidental transitive dependencies as
harness-owned. Declare other libraries required by adapter behavior. When a
library is optional, provide and test the dependency-free fallback. A
separately managed harness means that the environment owner installs and
versions its SDK/module or provides its external executable or service; the
adapter must not install or upgrade it.
- Keep `nemo-fabric-runtime` as an exact-version unconditional dependency of the
root `nemo-fabric` metapackage. Give every installable Python harness adapter
one canonical root extra `<extra>` that depends on the matching version of
`nemo-fabric-adapters-<adapter>[harness]`; the extra name does not need to
match the adapter directory.
- Keep a leaf adapter's base installation limited to adapter-owned dependencies.
Give every leaf a `harness` extra for its supported harness packages and a
`full` extra for every package-installable optional integration. If the
adapter imports NeMo Relay Python APIs, also provide a `relay` extra and
include it in `full`. If Relay is an external executable, do not provide a
leaf `relay` extra, and make `full` equivalent to `harness`. Document external
executable or service prerequisites separately. Do not add directory-name or
legacy aliases unless compatibility explicitly requires them.
- Install leaf adapters through their `harness` extras in the root
`adapter-tests` dependency group, and put other test-only packages in an
appropriate non-published group. For packaged harnesses, "compatible" means
satisfying the constraint declared by the leaf `harness` extra; document that
constraint for leaf-only installations. Derive exact pins or bounded ranges
from the supported upstream contract and test evidence; do not claim a
broader range than the evidence supports. Verify the unconditional root
runtime dependency, root-to-leaf harness delegation, `adapter-tests`
delegation, and leaf `harness`, `relay`, and `full` metadata. Inspect the
built root and leaf wheel metadata.
- Start with the narrowest truthful `fabric-adapter.json`. Keep
`config.accepts`, `config.generates`, requirements, telemetry declarations,
and lifecycle capabilities synchronized with implementation and tests.
Expand Down Expand Up @@ -151,6 +176,7 @@ and examples together when they expose the changed behavior.
Run `validate-change` and the applicable adapter commands:

```bash
uv sync --group adapter-tests
uv run --no-sync pytest tests/adapters/test_<name>*.py
just test-python
just lock-python && just wheels # Package or dependency changes.
Expand Down
7 changes: 7 additions & 0 deletions .agents/skills/maintain-packaging/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ consumed outside the source tree.
Treat every direct dependency as a long-lived API, supply-chain, and licensing
commitment.

- Keep `nemo-fabric` as a metapackage that unconditionally installs the
exact-version `nemo-fabric-runtime` distribution. Root harness extras delegate
to version-matched leaf adapter `harness` extras. Do not add root adapter-only
aliases.
- Keep leaf adapters adapter-only by default. Every leaf provides `harness` and
`full`; provide `relay` only when the adapter imports the NeMo Relay Python
package. For external Relay executables, `full` equals `harness`.
- First prefer the standard library, an existing dependency, or a small local
implementation when it keeps the behavior clear and maintainable.
- When multiple dependencies satisfy the technical requirement, prefer the
Expand Down
15 changes: 15 additions & 0 deletions .agents/skills/python-tests/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,21 @@ license: Apache-2.0
```
Simply allow the resulting KeyError to be raised if the "data" key is not present in the results dictionary, as this will provide a clear indication of what went wrong in the test.

## Packaging Metadata Tests

When adapter installation metadata changes, assert the published composition
directly:

- The root project unconditionally depends on the exact-version
`nemo-fabric-runtime` distribution.
- Each root harness extra delegates to the matching version of the leaf
adapter's `harness` extra.
- Bare leaf dependencies remain adapter-owned, and the root `adapter-tests`
dependency group installs each leaf through its `harness` extra.
- Every leaf provides `full`. Only adapters that import NeMo Relay Python APIs
provide `relay`; for adapters that use an external Relay executable, `full`
equals `harness`.

## Common Commands

```bash
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/ci_python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,13 @@ jobs:
with:
shared-key: fabric-rust-${{ runner.os }}-${{ runner.arch }}

# PyYAML is not a project dependency, but test_hermes_config_mapping
# imports it to read Hermes Agent config fixtures, so install it for the tests.
# Exercise the supported root adapter and harness compositions. The
# adapter-tests group also keeps local test dependencies independently
# installable for leaf adapter development.
- name: Build SDK with native extension
run: |
uv venv --python "${UV_PYTHON:-${{ matrix.python-version }}}" .venv
uv sync --group test --no-group dev --extra claude --extra codex --extra deepagents ${{ matrix.python-version != '3.11' && '--extra harbor' || '' }} ${{ matrix.python-version != '3.14' && '--extra hermes-agent' || '' }} --extra relay --extra runtime
uv sync --no-default-groups --group adapter-tests --group test --extra claude --extra codex --extra deepagents ${{ matrix.python-version != '3.11' && '--extra harbor' || '' }} ${{ matrix.python-version != '3.14' && '--extra hermes-agent' || '' }} --extra relay

- name: Run pytest
run: |
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ repos:
hooks:
- id: cargo-lockfile-check
name: Cargo.lock is up to date
entry: bash -c 'cargo metadata --format-version 1 --no-deps >/dev/null'
entry: bash -c 'cargo metadata --format-version 1 --locked >/dev/null'
language: system
files: '^(Cargo\.toml|Cargo\.lock|crates/.*/Cargo\.toml)$'
pass_filenames: false
Expand Down
11 changes: 8 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,21 @@ The resulting wheel files are placed in the `dist/` directory. Install the
packages into a virtual environment with:

```bash
uv pip install --find-links ./dist "nemo-fabric[runtime]"
uv pip install --find-links ./dist nemo-fabric
```

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

```bash
uv pip install --find-links ./dist "nemo-fabric[hermes]"
uv pip install --find-links ./dist "nemo-fabric[hermes-agent]"
```

To install only the Hermes adapter and its supported harness, use
`nemo-fabric-adapters-hermes[harness]`. Install
`nemo-fabric-adapters-hermes` without an extra when the environment already
manages a compatible Hermes Agent installation.

Refer to the [installation guide](docs/getting-started/install.mdx) for the
complete list of adapters and installation options.

Expand Down
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

75 changes: 52 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,21 @@ It provides:

## Supported Harnesses

NeMo Fabric provides the following harness integrations:

| Agent Harness | Package Extra |
| --- | --- |
| [Claude Code](docs/integrations/harness/claude.mdx) | `nemo-fabric[claude]` |
| [Codex](docs/integrations/harness/codex.mdx) | `nemo-fabric[codex]` |
| [Hermes Agent](docs/integrations/harness/hermes.mdx) | `nemo-fabric[hermes]` |
| [LangChain Deep Agents](docs/integrations/harness/deepagents.mdx) | `nemo-fabric[deepagents]` |
NeMo Fabric provides the following harness integrations. The package
expressions install the components shown in each column:

| Agent Harness | Runtime, Adapter, and Harness | Adapter and Harness | Adapter Only |
| --- | --- | --- | --- |
| [Claude Code](docs/integrations/harness/claude.mdx) | `nemo-fabric[claude]` | `nemo-fabric-adapters-claude[harness]` | `nemo-fabric-adapters-claude` |
| [Codex](docs/integrations/harness/codex.mdx) | `nemo-fabric[codex]` | `nemo-fabric-adapters-codex[harness]` | `nemo-fabric-adapters-codex` |
| [Hermes Agent](docs/integrations/harness/hermes.mdx) | `nemo-fabric[hermes-agent]` | `nemo-fabric-adapters-hermes[harness]` | `nemo-fabric-adapters-hermes` |
| [LangChain Deep Agents](docs/integrations/harness/deepagents.mdx) | `nemo-fabric[deepagents]` | `nemo-fabric-adapters-deepagents[harness]` | `nemo-fabric-adapters-deepagents` |

The `nemo-fabric` package always installs the runtime, and each root harness
extra adds the corresponding adapter and supported harness. Use the
adapter-package forms for split environments or environments that already
manage the harness. For `harness`, `full`, and Relay behavior, refer to the
[installation guide](docs/getting-started/install.mdx).

Capabilities vary by harness. Review the compatibility matrix and use plan()
and doctor() before relying on optional capabilities such as MCP, skills,
Expand All @@ -63,12 +70,14 @@ Agent in one Python environment.

### Install NeMo Fabric and Hermes Agent

Create and activate a virtual environment, then install the required packages:
Hermes Agent supports Python 3.11 through 3.13. With a supported Python
version, create and activate a virtual environment, then install the required
packages:

```bash
python -m venv .venv
source .venv/bin/activate
pip install "nemo-fabric[runtime, hermes-agent]"
pip install "nemo-fabric[hermes-agent]"
```

### Set the API Key
Expand Down Expand Up @@ -123,25 +132,42 @@ For a guided version of this example, refer to the
[example notebooks overview](examples/notebooks/README.md) describes the other
available notebooks.

## Use Separate Environments
## Deployment Scenarios

### Scenario 1: Runtime and Harness in the Same Environment

This is the simplest deployment. The `nemo-fabric` package, selected adapter,
and supported harness share one Python environment. The quick start above uses
this model with `nemo-fabric[hermes-agent]`.

The quick start uses one Python environment. Real-world deployments commonly
separate the application or evaluation host from the task environment where
NeMo Fabric and the selected harness run. For example, Harbor constructs
`FabricConfig` in its host process, then runs NeMo Fabric, the adapter, and the
harness inside an isolated task container. Refer to the
### Scenario 2: Isolated Sandbox for Task Execution

This is the Harbor deployment model. The Harbor host constructs and serializes
the final typed `FabricConfig`. Harbor then installs and runs NeMo Fabric, the
selected adapter, and the harness inside an isolated task environment such as a
Docker container or Daytona sandbox. Adapter discovery and task-path resolution
occur inside that sandbox.

Install `nemo-fabric[harbor]==0.1.0` in the host environment. Install a complete
harness composition such as `nemo-fabric[claude]==0.1.0` or
`nemo-fabric[hermes-agent,relay]==0.1.0` in the task environment. For Claude or
Codex Relay streaming, also provision the external NeMo Relay CLI in the task
environment. Refer to the
[Harbor execution model](examples/harbor/README.md#execution-model) for details.

NeMo Fabric can also operate with the NeMo Fabric runtime and the agent harness
in separate Python environments. This setup can match existing deployment
boundaries and isolate their dependencies.
### Scenario 3: Runtime and Harness in Separate Python Environments

NeMo Fabric can run the runtime and agent harness in separate, locally
accessible Python environments. This setup isolates their Python dependencies
while the runtime launches the adapter through the adapter environment's
interpreter.

Create an environment for the NeMo Fabric runtime:

```bash
python -m venv .venv-fabric
source .venv-fabric/bin/activate
pip install "nemo-fabric[runtime]"
pip install nemo-fabric==0.1.0
```

Create another environment for the adapter and harness. For example, install
Expand All @@ -150,11 +176,14 @@ the Hermes Agent integration:
```bash
python -m venv .venv-hermes
source .venv-hermes/bin/activate
pip install "nemo-fabric[hermes-agent]"
pip install "nemo-fabric-adapters-hermes[harness]==0.1.0"
```

**Note:** The `nemo-fabric[hermes-agent]` package extra installs the Hermes Agent adapter and Hermes Agent itself, to install just the adapter, use `nemo-fabric[hermes]`.

The adapter package keeps this environment independent from the
`nemo-fabric` distribution. Its `harness` extra installs the compatible Hermes
Agent dependency alongside the adapter. Use matching NeMo Fabric release
versions for the runtime and adapter package unless a different pairing has
been explicitly validated.

Run NeMo Fabric from its environment and set `ADAPTER_PYTHON` to the interpreter
that contains the adapter and harness:
Expand Down
37 changes: 19 additions & 18 deletions adapters/claude/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,26 @@ The `nvidia.fabric.claude` adapter uses the official Claude Agent SDK for
Python behind NeMo Fabric's normalized invocation contract. The SDK is an
implementation detail; consumers select the Claude harness by adapter ID.

This adapter pins `claude-agent-sdk==0.2.120`. The SDK supplies and selects its
compatible Claude Code runtime.
The `harness` extra pins `claude-agent-sdk==0.2.120`; use the same version for an
environment-managed SDK. The SDK supplies a compatible Claude Code runtime.

## Install

To install just the Claude adapter by itself:
The following table shows which components each installation provides:

```bash
pip install "nemo-fabric[claude]"
```
| Installation | Runtime | Adapter | Harness | NeMo Relay CLI |
| --- | --- | --- | --- | --- |
| `pip install "nemo-fabric[claude]"` | Yes | Yes | Yes | No |
| `pip install "nemo-fabric-adapters-claude[harness]"` | No | Yes | Yes | No |
| `pip install nemo-fabric-adapters-claude` | No | Yes | No | No |

To install just the Claude adapter along with the NeMo Fabric Runtime:
For split runtime and adapter environments, configure `ADAPTER_PYTHON` or
`harness.settings.python` and use matching NeMo Fabric release versions. Refer
to the [installation guide](https://nvidia-nemo-fabric.docs.buildwithfern.com/nemo/fabric/getting-started/install#install-an-adapter-and-harness-without-the-runtime).

```bash
pip install "nemo-fabric[claude, runtime]"
```
The `full` extra is equivalent to `harness`. Relay is optional for ordinary
runs. Relay telemetry and `Runtime.invoke_stream()` require the external CLI
described under [Relay Observability](#relay-observability).

## Authentication

Expand Down Expand Up @@ -58,12 +62,6 @@ Refer to the [Claude adapter authentication guide](https://nvidia-nemo-fabric.do
for mode selection, required WIF variables, and the Relay boundary. Package
installation is verified by the adapter wheel and module-entrypoint tests.

Relay-enabled runs also require the external `nemo-relay` CLI. Refer to the [NeMo Relay CLI](https://docs.nvidia.com/nemo/fabric/getting-started/install#nemo-relay-cli) install guide for instructions on installing the CLI tool.

The Python `nemo-relay` package does not install this executable. Refer to the
[NeMo Relay installation guide](https://docs.nvidia.com/nemo/relay/getting-started/installation)
for other supported installation methods.

## Execution Model

The Claude adapter implements NeMo Fabric's persistent local-host wire protocol.
Expand Down Expand Up @@ -113,6 +111,10 @@ by the SDK and is not persisted as a NeMo Fabric artifact.

## Relay Observability

Relay requires a separately installed NeMo Relay 0.6.x CLI on `PATH`; the Python
`nemo-relay` package does not provide the executable. Follow the
[NeMo Relay installation instructions](https://nvidia-nemo-fabric.docs.buildwithfern.com/nemo/fabric/getting-started/install#install-nemo-relay).

Enable Relay through the normalized NeMo Fabric configuration:

```python
Expand All @@ -134,8 +136,7 @@ gateway has the same lifecycle as that single invocation.
The NeMo Fabric result includes `relay_runtime.gateway_config_path`,
`relay_runtime.gateway_log_path`, and the collected `relay_artifacts`. Relay
startup failures return a stable adapter error and retain the gateway log for
diagnosis. The default Claude Agent SDK dependency bundles a compatible Claude
Code executable.
diagnosis.

## Typed Configuration

Expand Down
9 changes: 8 additions & 1 deletion adapters/claude/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,17 @@ readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"nemo-fabric-adapters-common == 0.2.0",
"claude-agent-sdk==0.2.120",
"tomli-w~=1.2",
]

[project.optional-dependencies]
harness = [
"claude-agent-sdk==0.2.120",
]
full = [
"claude-agent-sdk==0.2.120",
]

[project.urls]
Repository = "https://github.com/NVIDIA/nemo-fabric/"
Documentation = "https://nvidia-nemo-fabric.docs.buildwithfern.com/nemo/fabric"
Expand Down
Loading
Loading