> This page is for NeMo Relay, version v0.11.1.
> For other versions, use one of these documentation indexes:
> - Latest (v0.10.4) (default): https://docs.nvidia.com/nemo/relay/latest/llms.txt
> - dev: https://docs.nvidia.com/nemo/relay/dev/llms.txt
> - v0.11.1: https://docs.nvidia.com/nemo/relay/v0.11.1/llms.txt
> - v0.10.4: https://docs.nvidia.com/nemo/relay/v0.10.4/llms.txt
> - v0.9.4: https://docs.nvidia.com/nemo/relay/v0.9.4/llms.txt
> - v0.8.4: https://docs.nvidia.com/nemo/relay/v0.8.4/llms.txt
> - v0.7.3: https://docs.nvidia.com/nemo/relay/v0.7.3/llms.txt

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

# NeMo Relay Deep Agents Integration

> Add NeMo Relay observability to Deep Agents applications.

Use the `nemo_relay.integrations.deepagents` package to add NeMo Relay
observability to Deep Agents applications through the LangChain and LangGraph
integration surfaces that Deep Agents builds on.

## Setup

Install the Deep Agents integration extra in your application environment.

#### uv

```bash
uv add "nemo-relay[deepagents]"
```

#### pip

```bash
pip install "nemo-relay[deepagents]"
```

The example below uses the NVIDIA LangChain provider. Install that provider
extra too if you want to run the example as written:

#### uv

```bash
uv add "nemo-relay[deepagents,langchain-nvidia]"
```

#### pip

```bash
pip install "nemo-relay[deepagents,langchain-nvidia]"
```

## Usage Example

```python
import nemo_relay
from deepagents import create_deep_agent
from nemo_relay.integrations.deepagents import (
    NemoRelayDeepAgentsCallbackHandler,
    add_nemo_relay_integration,
)

agent = create_deep_agent(
    **add_nemo_relay_integration(
        model="nvidia:nvidia/nemotron-3-nano-omni-30b-a3b-reasoning",
        tools=[],
        name="main-agent",
    )
)

input_payload = {
    "messages": [
        {
            "role": "user",
            "content": "Research recent GPU news",
        }
    ]
}

with nemo_relay.scope.scope("deepagents-request", nemo_relay.ScopeType.Agent):
    result = agent.invoke(
        input_payload,
        config={"callbacks": [NemoRelayDeepAgentsCallbackHandler()]},
    )

final_message = result["messages"][-1]
print(f"Final response: {final_message.content}")
```

Add `skills=[...]` or subagent configuration after this minimal path is working
when you need to capture Deep Agents skill or subagent marks.

## Middleware Ordering

Use the `position` option in `add_nemo_relay_integration` to choose where to add
Relay in your middleware list. Pass this option by name.

| Position            | Placement              | Recorded tool result                   |
| ------------------- | ---------------------- | -------------------------------------- |
| `"inner"` (default) | After your middleware  | Before your wrappers change the result |
| `"outer"`           | Before your middleware | After your wrappers change the result  |

Use `position="outer"` to record text that your middleware adds to tool
results. This can include status text or review notes. Relay tool events and
ATIF observations then include that text. This example uses your
`status_middleware` instance:

```python
agent = create_deep_agent(
    **add_nemo_relay_integration(
        model="nvidia:nvidia/nemotron-3-nano-omni-30b-a3b-reasoning",
        tools=[],
        middleware=[status_middleware],
        position="outer",
    )
)
```

Refer to the
[LangChain middleware example](/nemo/relay/v0.11.1/supported-integrations/langchain#middleware-ordering)
for a status wrapper with sync and async methods. The same wrapper order applies
to `invoke` and `ainvoke`.

The default is `position="inner"`. In this mode, text that your wrappers add
still reaches the model. Relay's recorded tool result does not include it.
The next LLM request event can contain that text. ATIF uses the tool
observation to record the tool result.

The helper uses the same position for custom subagents that you define as
dictionaries. Set `instrument_subagents=False` to skip adding Relay to them.
The helper copies middleware lists and subagent dictionaries. It does not
change the lists or dictionaries that you pass in.

If a list already contains `NemoRelayDeepAgentsMiddleware`, the helper keeps
that instance in place. To move it, change its position in the list yourself.

Deep Agents controls the order of its built-in middleware. The `position`
option only places Relay before or after your middleware. Even with `"outer"`,
built-in wrappers can run outside Relay. Relay does not record their later
changes to the result. It also does not record changes from graph hooks that
run after its wrapper returns.

This option does not add Relay to precompiled, remote, or automatically
generated subagents. Refer to [Observability](#observability) for the support
limits for those subagents.

Order also affects model calls. An outer Relay wrapper records a request
before inner wrappers change it. It records a response after they return.
Refer to
[LangChain middleware ordering](/nemo/relay/v0.11.1/supported-integrations/langchain#middleware-ordering)
for guidance on retries and caches.

## Verify the Integration

The integration works correctly when:

* The Deep Agents run completes and prints a final response.
* The `deepagents-request` scope contains a semantic `main-agent` Agent scope.
* In-process delegated agents appear as nested Agent scopes with names derived
  from callback metadata. Unnamed top-level runs use the `DeepAgent` fallback.
* Skill, subagent, and human-in-the-loop marks appear when those features are exercised.

## Observability

The integration composes the existing NeMo Relay LangChain and LangGraph hooks,
then emits Deep Agents-specific marks for configured skills, subagents, and
human-in-the-loop lifecycle events.

It captures:

* LangChain model and tool calls through NeMo Relay managed execution.
* Semantic orchestrator and in-process subagent Agent scopes through the
  Deep Agents callback handler. Internal LangGraph node runs do not create
  additional Agent scopes in this specialized handler.
* Human-in-the-loop interrupt and resume marks.
* Configured skills and subagent summaries at agent-run start.
* Automatic `skill.load` marks when a Deep Agents tool requests a complete
  `SKILL.md` read; this is distinct from the configured-skills summary.
* In-process dictionary-style subagents with the same NeMo Relay middleware, so
  their model and tool calls are captured when Deep Agents invokes them.

The automatically configured `general-purpose` subagent is identified from
Deep Agents callback metadata and appears as a nested Agent scope when invoked.
Deep Agents does not inherit arbitrary parent middleware into that generated
subagent, so its internal model and tool calls are not managed by Relay.
Precompiled local subagent runnables can expose a semantic run boundary through
the callback, but their internal model and tool calls require separate Relay
instrumentation. Remote graphs or processes likewise need Relay instrumentation
inside that graph or process to capture their internal calls.

Refer to [Observability](/nemo/relay/v0.11.1/configure-plugins/observability/about)
for details on exporting NeMo Relay observability data to third-party systems.