Skip to content

spike(nemo-agents): NAT-to-Fabric agent transpile (Stage 1)#776

Draft
yamini wants to merge 3 commits into
mainfrom
nat-to-fabric-spike/ykagal
Draft

spike(nemo-agents): NAT-to-Fabric agent transpile (Stage 1)#776
yamini wants to merge 3 commits into
mainfrom
nat-to-fabric-spike/ykagal

Conversation

@yamini

@yamini yamini commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Design doc (please read before reviewing PR)

Why

NAT (NVIDIA NeMo Agent Toolkit) is being sunset. NeMo Platform has a few internal users with NAT agents who will need to move to the Fabric runtime. The open question is how: keep a permanent adapter that interprets NAT config at runtime, or translate each agent once into a Fabric-native config. A permanent adapter keeps the NAT format as a runtime dependency for good; a better approach is a one-time transpiler.

This PR is a proof of approach for the translation path. It shows the translation works end to end for a non-trivial agent and flags what transfers cleanly versus what needs more effort than a config rewrite. Note: This isn't intended to be shippable code.

What

Stage 1 spike under plugins/nemo-agents/examples/nat-to-fabric-spike/: translate a NAT workflow config into a Fabric-native agent.yaml for the LangChain Deep Agents harness, by transpiling rather than running NAT config through a permanent compatibility shim.

Input topology (nat_agent/config.yml)

reasoning_agent (workflow)
  └─ research_orchestrator (react_agent)
       ├─ math_agent (tool_calling_agent) -> mcp_math  (streamable-http, ${ENV} url)
       ├─ time_agent (tool_calling_agent) -> mcp_time  (stdio) + current_timezone
       ├─ jira_agent (tool_calling_agent) -> mcp_jira  (streamable-http, OAuth2)
       └─ code_generation (builtin)

What the tool does

  • Introspects the NAT composition graph. Nested agents are preserved as Deep Agents subagents (with delegates_to), not flattened, in a way that's cycle-safe.
  • Carries mcp_client function groups to Fabric mcp.servers one-to-one (stdio and streamable-http).
  • Flags the following: OAuth2/custom-header auth, NAT builtins needing an MCP equivalent, a middleware: section (e.g. NASSE) that maps to Relay, env vars to set, and dangling refs.
  • --analyze mode: this is a read-only report of what an agent is and how it's composed (topology tree, models, tools, open items), no config emission.
  • Emits fabric/agent.yaml, MIGRATION_REPORT.md, and (in analyze mode) ANALYSIS.md.

Results

Fixture: 3 MCP servers carried, 3 subagents preserved, 1 OAuth2 gap flagged, 2 builtins flagged, 0 errors. Also run against real NAT agents: stock react_agent agents transpile cleanly; agents built from custom registered NAT types are correctly blocked with a pointer to WorkflowBuilder resolution.

Tests

25 pytest cases in test_transpile.py, covering the happy path plus cycles, nested-agent identity, missing/dangling refs, stdio edge cases, non-MCP groups, non-nim LLMs, custom top-level types, middleware detection, and the analyzer.

python3 transpile.py             # writes agent.yaml + MIGRATION_REPORT.md
python3 transpile.py --analyze   # read-only analysis -> ANALYSIS.md
python3 -m pytest test_transpile.py

Scope

Stage 1 only: it emits and validates the config, it does not run the migrated agent on a Fabric runtime (Stage 2, needs a Fabric environment). Validation is a self-contained structural check by default; pass --schema /path/to/nemo-fabric/schemas/agent.schema.json for full JSON Schema validation against a local Fabric checkout.

Next steps

This is a proof of approach, not a shippable feature. Productionizing it still takes:

  • Wiring migrate and analyze into the nemo agents CLI as subcommands.
  • Resolving configs through NAT's WorkflowBuilder instead of parsing YAML, so custom registered types and default prompts come through.
  • Providing MCP equivalents for NAT builtin tools.
  • Adding Stage 2: run the migrated agent on a Fabric runtime and diff behavior against the NAT original.

Translates a NAT (NVIDIA NeMo Agent Toolkit) workflow config into a Fabric-native
agent.yaml for the LangChain Deep Agents harness, rather than running NAT config
through a permanent compatibility shim.

- Walks the NAT composition graph; nested agents are preserved as Deep Agents
  subagents (with delegates_to), not flattened. Cycle-safe.
- Carries mcp_client function groups to Fabric mcp.servers one-to-one (stdio +
  streamable-http).
- Flags rather than guesses: OAuth2/custom-header auth (Deep Agents adapter gap),
  NAT builtins needing an MCP equivalent, env vars to set, dangling refs.
- 21 pytest cases; output validated against the Fabric agent schema (structural
  check committed; full JSON Schema via --schema against a local Fabric checkout).

Stage 1 only: emits and validates the config; does not run it on a Fabric runtime.

Signed-off-by: Yamini <ykagal@gmail.com>
@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 25701/32944 78.0% 62.7%
Integration Tests 14783/31593 46.8% 19.2%

yamini added 2 commits July 18, 2026 10:39
…shing

Running the transpiler on a real blueprint (AI-Q deep researcher) surfaced that
production NAT agents use custom registered _types (chat_deepresearcher_agent,
deep_research_agent, ...), not stock archetypes. child_refs no longer KeyErrors on
an unknown _type; a custom top-level agent type is reported as a blocking error
pointing at NAT WorkflowBuilder resolution. Adds a regression test.

Signed-off-by: Yamini <ykagal@gmail.com>
- --analyze: read-only "what this agent is and how it's composed" report
  (ANALYSIS.md): composition tree, models, tools, and open items. No Fabric
  emission. The low-friction on-ramp for looking at a NAT agent.
- Flags NAT sections the transpiler doesn't carry (middleware/NASSE -> Relay;
  memory, retrievers, etc. -> Fabric/Platform) instead of dropping them.
- metadata.name now defaults to the input filename when there's no reasoning
  wrapper, so distinct agents don't all come out named "react-agent".
- 25 tests (adds analyze, middleware, filename-name cases).

Signed-off-by: Yamini <ykagal@gmail.com>
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.

1 participant