> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/nemo/fabric/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.nvidia.com/nemo/fabric/_mcp/server.

# Use the Pi Adapter

> Install and configure the NVIDIA NeMo Fabric harness integration for Pi.

Use the NVIDIA NeMo Fabric `nvidia.fabric.pi` adapter to run tasks with the Pi
SDK in a persistent Node.js process.

## Install the Adapter

Pi requires Node.js 22.19.0 or newer.

### Install for Consumers

Install the npm adapter in the project that owns the NeMo Fabric configuration,
then install the compatible Pi SDK harness version selected by that project:

```bash
npm install nemo-fabric-adapters-pi
npm install @earendil-works/pi-ai@^0.84.2 @earendil-works/pi-coding-agent@^0.84.2
```

The Pi packages are optional peers: installing `nemo-fabric-adapters-pi` alone
does not install the harness. Starting the adapter without compatible Pi
packages returns `pi_harness_unavailable`.

### Install for Source Development

For focused Pi development in the NeMo Fabric source tree, install the Pi
adapter workspace and its pinned harness from the repository root:

```bash
just install-typescript-pi
```

To install and build all maintained TypeScript workspaces instead, run:

```bash
just build-typescript
```

The full build installs its own dependencies, so you do not need to run
`just install-typescript-pi` first.

### Install NeMo Relay

Relay-enabled Pi runs require `nemo-relay>=0.9.0,<0.10.0` on `PATH`. Install it
separately from the npm adapter:

```bash
pip install "nemo-relay-cli-bin>=0.9.0,<0.10.0"
```

To select a specific Relay executable instead of relying on `PATH`, set
`FABRIC_NEMO_RELAY_COMMAND` to its absolute path:

```bash
FABRIC_NEMO_RELAY_COMMAND="/absolute/path/to/nemo-relay" uv run python your_app.py
```

The adapter does not bundle the Relay Pi extension. Obtain the
[`crates/cli/assets/pi-extension`](https://github.com/NVIDIA/NeMo-Relay/tree/0.9.0/crates/cli/assets/pi-extension)
directory from the Relay 0.9 release and configure its path as described in the
next section.

## Configure the Adapter

Select the Pi harness integration and point NeMo Fabric discovery at the
adapter descriptor. The following example uses the descriptor from an installed
npm package:

```python
from nemo_fabric import DiscoveryConfig, FabricConfig, HarnessConfig
from nemo_fabric import MetadataConfig, ModelConfig, ToolsConfig

config = FabricConfig(
    metadata=MetadataConfig(name="pi-review"),
    discovery=DiscoveryConfig(
        local_paths=[
            "./node_modules/nemo-fabric-adapters-pi/pi.fabric-adapter.json"
        ]
    ),
    harness=HarnessConfig(adapter_id="nvidia.fabric.pi"),
    models={
        "default": ModelConfig(
            provider="nvidia",
            model="nvidia/nemotron-3-nano-omni-30b-a3b-reasoning",
            api_key_env="NVIDIA_API_KEY",
            base_url="https://integrate.api.nvidia.com/v1",
        )
    },
    tools=ToolsConfig(enabled=["read"], blocked=[]),
)
```

For a source build, set `discovery.local_paths` to
`adapters/typescript/pi/pi.fabric-adapter.json` instead.

The adapter supports one selected model from Pi's catalog, an optional base URL
override, `replace` system instructions, tool policy, explicit skill paths,
and explicit local Pi extensions. Set `models.<role>.api_key_env` to the name of
the environment variable that contains the provider credential.

The provider and model pair must already exist in Pi's catalog. A base URL can
override a known model endpoint, but it does not define a new provider.

## Configure Skills and Extensions

Add normalized skill paths with the Python SDK. NeMo Fabric resolves these
paths from the `base_dir` passed to `plan()`, `doctor()`, or `run()`:

```python
config.add_skill_path("./skills/code-review")
```

Pi extensions are adapter-specific trusted code. Configure extension files
relative to `environment.workspace`:

```python
config.harness.settings["extensions"] = ["extensions/review.ts"]
```

The adapter loads only the skill and extension paths in the configuration. It
does not load ambient Pi resources from the user profile or workspace.

## Configure NeMo Relay

Enable Relay with the standard NeMo Fabric configuration and provide the Relay
Pi extension as an adapter setting:

```python
config.runtime.artifacts = "./artifacts/pi"
config.enable_relay(output_dir="./artifacts/relay")
config.harness.settings["relay_extension_path"] = (
    "/path/to/NeMo-Relay/crates/cli/assets/pi-extension"
)
```

Relay requires `runtime.artifacts` so NeMo Fabric can create the runtime-owned
configuration passed to the adapter. The extension path can be absolute or
relative to `environment.workspace`. It can identify a JavaScript or TypeScript
file or a Pi extension package directory. Unlike user-configured Pi extensions,
the Relay extension does not need to remain inside `environment.workspace` when
an absolute path is used.

When the runtime starts, the adapter validates the Relay 0.9 CLI, writes an
explicit `plugins.toml`, starts a loopback gateway, and loads the extension into
the isolated Pi session. The result includes `relay_runtime` and
`relay_artifacts` in `output`. The gateway can produce ATOF, ATIF,
OpenTelemetry, and OpenInference output from the Relay observability
configuration.

The adapter supports one Relay-enabled Pi runtime per adapter process because
the Relay 0.9 extension receives its gateway and upstream configuration through
process environment variables. NeMo Fabric starts each runtime in a separate
adapter process, so concurrent NeMo Fabric runtimes remain isolated. Direct
embedders must likewise place concurrent Relay-enabled Pi runtimes in separate
processes.

Local ATIF trajectories are finalized only after the Pi session closes and are
therefore not included in `relay_artifacts`. The adapter does not wait for local
ATIF during invocation. It collects per-invocation artifacts such as ATOF and
returns the result. After runtime shutdown, retrieve the finalized file directly
from the ATIF output directory. For the configuration above and the default
filename template, it is written to
`./artifacts/relay/<runtime_id>/trajectory-<session_id>.atif.json`. Invocation
results do not prevent subsequent turns.

Session, turn, and tool telemetry does not depend on model redirection. Model
telemetry is available only when Relay supports the selected model API and the
gateway upstream matches the model endpoint. A skipped redirect is recorded as
a `model_redirect` mark with the reason.

## Configure a NeMo Fabric Tool Definition

Pi accepts trusted local JavaScript and TypeScript tool factories. The
normalized definition uses `kind: "module"`; `ref` is relative to the NeMo Fabric
workspace and may include a named export after `#`.

Create `tools/review-context.js` in the configured workspace:

```javascript
export function createTool({ name, settings }) {
  return {
    name,
    label: "Review Context",
    description: "Return configured context for a code review.",
    parameters: { type: "object", properties: {} },
    async execute() {
      return {
        content: [{ type: "text", text: JSON.stringify(settings) }],
        details: {},
      };
    },
  };
}
```

Register and enable the tool:

```python
config.add_tool_definition(
    "review_context",
    kind="module",
    ref="tools/review-context.js#createTool",
    settings={"format": "brief"},
)
config.tools.enabled = ["read", "review_context"]
```

The factory receives `{ name, settings, workspace }` and returns a Pi
`ToolDefinition` with the same name. Tool modules and explicit Pi extensions
run as trusted code in the adapter process. The adapter rejects paths outside
the workspace and duplicate names across built-ins, NeMo Fabric definitions,
and extensions.

## Understand the Runtime Lifecycle

Each NeMo Fabric runtime owns one in-memory Pi session in a persistent Node.js
adapter process. Ordered invocations reuse that session and its conversation
history until the runtime stops. Start a new runtime to change the model,
skills, extensions, custom tools, or workspace.

## Current Limitations

The current adapter does not expose MCP, native OpenAI streaming, caller-driven
cancellation, or remote-service execution. Relay-backed
`Runtime.invoke_stream()` correlation is not yet supported for Pi. Enabling a
third-party extension can add extension-defined skills, prompts, or themes even
though ambient Pi resources remain disabled. The Relay extension does not add
those resources.

The Relay Pi hook route is available only on the loopback gateway and does not
authenticate hook posts. Treat the loopback port as a local trust boundary.