Skip to content

feat: add typed workflow configuration - #176

Merged
rapids-bot[bot] merged 1 commit into
NVIDIA:mainfrom
AjayThorve:topic/custom_agents
Aug 5, 2026
Merged

feat: add typed workflow configuration#176
rapids-bot[bot] merged 1 commit into
NVIDIA:mainfrom
AjayThorve:topic/custom_agents

Conversation

@AjayThorve

@AjayThorve AjayThorve commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Overview

Add an optional, typed FabricConfig.workflow contract for adapters that expose selectable executables or custom agents. A workflow contains an adapter-defined entrypoint.kind, entrypoint.ref, and immutable construction settings.

Adapters opt in with a descriptor-owned workflow_schema. NeMo Fabric validates the complete workflow during planning and again before runtime startup. workflow_schema is the single support and shape claim; adapters without it reject configured workflows instead of silently ignoring them.

This is the prerequisite contract for the external NAT reference adapter in #175. No bundled adapter opts into workflows in this PR.

Details

  • Add Rust and Python authoring/plan-snapshot types for workflow configuration.
  • Add workflow_schema to fabric-adapter.json descriptors and generated schemas.
  • Preserve additive extension fields at the workflow and entrypoint levels.
  • Support adapter defaults only when the descriptor schema explicitly accepts null; schema defaults are not applied.
  • Report descriptor context and canonical workflow... paths on validation failures.
  • Update generated API references, SDK guidance, adapter guidance, and the exported consumer integration skill.

Breaking Changes

Existing serialized JSON and Python configurations remain valid because workflow and workflow_schema are optional. Downstream Rust code that constructs FabricConfig or AdapterDescriptor with struct literals must initialize the new optional field (normally None).

Validation

  • RUSTUP_TOOLCHAIN=1.94.0 just test-rust — 55 core tests plus CLI, scaffold, and doc tests passed.
  • RUSTUP_TOOLCHAIN=1.94.0 just test-python — 602 passed, 15 skipped.
  • just build-python
  • cargo check -p fabric-python --locked
  • RUSTUP_TOOLCHAIN=1.94.0 just docs
  • uv run pre-commit run --all-files --show-diff-on-failure
  • cargo fmt --all -- --check
  • git diff --check

Where should the reviewer start?

Start with WorkflowConfig, WorkflowEntrypointConfig, and validate_workflow in crates/fabric-core/src/config.rs, then review the Python parity in python/src/nemo_fabric/models.py and the fail-closed planning coverage in tests/python/test_workflow_validation.py.

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

Relates to #175

  • 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

    • Added optional workflow configuration for selecting adapter-provided executables and entry points.
    • Added workflow settings support with adapter-defined schema validation.
    • Added workflow configuration models to the Python and Rust APIs.
    • Added clear validation errors for unsupported or invalid workflow settings.
  • Documentation

    • Updated quick-start, SDK, schema, adapter, and API references with workflow configuration guidance.
  • Tests

    • Added coverage for serialization, round-tripping, valid workflows, missing schemas, and invalid configuration.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: e97e22ab-cca3-4124-b4b9-c1c5ccc4d82c

📥 Commits

Reviewing files that changed from the base of the PR and between 55450ff and 9959d9f.

📒 Files selected for processing (52)
  • .agents/skills/contribute-adapter/SKILL.md
  • README.md
  • adapters/README.md
  • crates/fabric-cli/src/presets.rs
  • crates/fabric-cli/templates/rust/main.rs.tmpl
  • crates/fabric-core/src/config.rs
  • crates/fabric-core/src/error.rs
  • crates/fabric-core/src/lib.rs
  • crates/fabric-core/src/runtime.rs
  • crates/fabric-core/src/schema.rs
  • docs/reference/api/python-library-reference/index.md
  • docs/reference/api/python-library-reference/nemo_fabric.models.md
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-capabilitykind.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-capabilitytarget.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayatifstorageconfig.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayatofmode.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayatofsinkconfig.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayatofstreamfieldnamepolicy.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayatofstreamtransport.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayotlptransport.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayunsupportedbehavior.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/fn-load-adapter-descriptor.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/fn-resolve-run-plan-from-config.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/index.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/struct-adapterdescriptor.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/struct-fabricconfig.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/struct-workflowconfig.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/struct-workflowentrypointconfig.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/doctor/enum-doctorstatus.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/doctor/fn-doctor-plan.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/doctor/index.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/doctor/struct-doctorcheck.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/doctor/struct-doctorreport.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/error/enum-fabricerror.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/error/index.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/error/type-result.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/fn-version.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/index.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/runtime/index.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/schema/index.mdx
  • docs/sdk/python.mdx
  • python/src/nemo_fabric/__init__.py
  • python/src/nemo_fabric/models.py
  • python/src/nemo_fabric/types.py
  • schemas/SCHEMA.md
  • schemas/adapter-descriptor.schema.json
  • schemas/agent.schema.json
  • schemas/run-plan.schema.json
  • skills/integrations/consumer/nemo-fabric-integrate/SKILL.md
  • skills/integrations/consumer/nemo-fabric-integrate/references/config-mapping.md
  • tests/python/test_sdk_contract.py
  • tests/python/test_workflow_validation.py

Walkthrough

The change adds adapter-owned workflow configuration across Rust, Python, and JSON schemas. Planning and runtime startup validate workflows against adapter descriptors. SDK models, errors, tests, and documentation now expose the workflow contract.

Changes

Workflow configuration

Layer / File(s) Summary
Workflow configuration contracts
crates/fabric-core/..., python/src/nemo_fabric/..., schemas/*.json, crates/fabric-cli/...
Adds workflow models, optional FabricConfig.workflow, descriptor workflow_schema, serialization, and schema definitions.
Descriptor and runtime validation
crates/fabric-core/src/config.rs, crates/fabric-core/src/runtime.rs, crates/fabric-core/src/error.rs
Validates workflow schemas, entrypoints, and settings during planning and runtime startup. Adds FabricError::InvalidWorkflow and tests.
SDK integration and usage guidance
python/src/nemo_fabric/..., tests/python/*, README.md, adapters/README.md, skills/..., docs/sdk/python.mdx
Exports workflow models, preserves them through snapshots, tests validation, and documents adapter-owned workflows.
Public API reference updates
docs/reference/api/python-library-reference/*, docs/reference/api/rust-library-reference/*
Documents workflow types, fields, exports, descriptor metadata, and the new error variant. Updates navigation positions.

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

Sequence Diagram(s)

sequenceDiagram
  participant FabricConfig
  participant resolve_run_plan_from_config
  participant AdapterDescriptor
  participant validate_workflow
  participant start_runtime
  FabricConfig->>resolve_run_plan_from_config: Submit workflow configuration
  resolve_run_plan_from_config->>AdapterDescriptor: Resolve selected descriptor
  resolve_run_plan_from_config->>validate_workflow: Validate against workflow_schema
  validate_workflow-->>resolve_run_plan_from_config: Return valid workflow or InvalidWorkflow
  start_runtime->>validate_workflow: Validate workflow before startup
  validate_workflow-->>start_runtime: Return validation result
Loading

Possibly related PRs

  • NVIDIA/NeMo-Fabric#175: Related workflow configuration, schema validation, runtime validation, and documentation changes.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.04% 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
Title check ✅ Passed The title uses valid Conventional Commits syntax, an allowed type, an imperative summary, and stays below 72 characters.
Description check ✅ Passed The description covers the overview, reviewer starting points, related issue, validation results, breaking changes, and required confirmations.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@github-actions

github-actions Bot commented Aug 5, 2026

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

Caution

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

⚠️ Outside diff range comments (1)
tests/python/test_sdk_contract.py (1)

79-85: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Replace Any in the variadic keyword annotation.

Ruff reports ANN401 for **settings: Any. Use object or a concrete JSON-value type so this test helper passes the configured lint rules while still accepting the invalid integer test value.

🤖 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/python/test_sdk_contract.py` around lines 79 - 85, Update the variadic
keyword annotation in the test helper used by FabricConfig.from_mapping to
replace Any with object or an appropriate JSON-value type; retain support for
the invalid integer setting exercised by the test.

Source: Linters/SAST tools

🤖 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/README.md`:
- Around line 30-35: Update the “Complete FabricConfig Support” compatibility
table in adapters/README.md to add a workflow row covering workflow.entrypoint
and workflow.settings, marking both unsupported for Claude, Codex, Deep Agents,
and Hermes Agent, consistent with docs/sdk/python.mdx.

In `@crates/fabric-core/src/runtime.rs`:
- Line 544: Update start_runtime to validate the deserialized RunPlan
configuration at the runtime boundary by calling validate_config before
prepare_environment, while retaining validate_workflow for adapter-specific
checks. Ensure blank workflow.entrypoint.kind or workflow.entrypoint.ref values
are rejected before environment preparation.

In `@python/src/nemo_fabric/models.py`:
- Around line 124-130: Update WorkflowConfig serialization so an empty settings
mapping is excluded from the emitted workflow mapping, matching Rust behavior
while preserving non-empty settings. Extend the relevant Python/Rust parity test
coverage for WorkflowConfig.to_mapping() to verify both omission when settings
is empty and retention when populated.

---

Outside diff comments:
In `@tests/python/test_sdk_contract.py`:
- Around line 79-85: Update the variadic keyword annotation in the test helper
used by FabricConfig.from_mapping to replace Any with object or an appropriate
JSON-value type; retain support for the invalid integer setting exercised by the
test.
🪄 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: 409501fd-69a3-4b7c-a03c-71f1054eca62

📥 Commits

Reviewing files that changed from the base of the PR and between 55450ff and 5bf0401.

📒 Files selected for processing (52)
  • .agents/skills/contribute-adapter/SKILL.md
  • README.md
  • adapters/README.md
  • crates/fabric-cli/src/presets.rs
  • crates/fabric-cli/templates/rust/main.rs.tmpl
  • crates/fabric-core/src/config.rs
  • crates/fabric-core/src/error.rs
  • crates/fabric-core/src/lib.rs
  • crates/fabric-core/src/runtime.rs
  • crates/fabric-core/src/schema.rs
  • docs/reference/api/python-library-reference/index.md
  • docs/reference/api/python-library-reference/nemo_fabric.models.md
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-capabilitykind.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-capabilitytarget.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayatifstorageconfig.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayatofmode.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayatofsinkconfig.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayatofstreamfieldnamepolicy.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayatofstreamtransport.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayotlptransport.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/enum-relayunsupportedbehavior.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/fn-load-adapter-descriptor.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/fn-resolve-run-plan-from-config.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/index.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/struct-adapterdescriptor.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/struct-fabricconfig.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/struct-workflowconfig.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/config/struct-workflowentrypointconfig.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/doctor/enum-doctorstatus.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/doctor/fn-doctor-plan.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/doctor/index.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/doctor/struct-doctorcheck.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/doctor/struct-doctorreport.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/error/enum-fabricerror.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/error/index.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/error/type-result.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/fn-version.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/index.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/runtime/index.mdx
  • docs/reference/api/rust-library-reference/nemo-fabric-core/schema/index.mdx
  • docs/sdk/python.mdx
  • python/src/nemo_fabric/__init__.py
  • python/src/nemo_fabric/models.py
  • python/src/nemo_fabric/types.py
  • schemas/SCHEMA.md
  • schemas/adapter-descriptor.schema.json
  • schemas/agent.schema.json
  • schemas/run-plan.schema.json
  • skills/integrations/consumer/nemo-fabric-integrate/SKILL.md
  • skills/integrations/consumer/nemo-fabric-integrate/references/config-mapping.md
  • tests/python/test_sdk_contract.py
  • tests/python/test_workflow_validation.py

Comment thread adapters/README.md
Comment thread crates/fabric-core/src/runtime.rs
Comment thread python/src/nemo_fabric/models.py
Signed-off-by: Ajay Thorve <athorve@nvidia.com>
@AjayThorve
AjayThorve force-pushed the topic/custom_agents branch from 5bf0401 to 9959d9f Compare August 5, 2026 22:13
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

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

LGTM

@AjayThorve

Copy link
Copy Markdown
Collaborator Author

/merge

@rapids-bot
rapids-bot Bot merged commit a227a6b into NVIDIA:main Aug 5, 2026
32 checks passed
rapids-bot Bot pushed a commit that referenced this pull request Aug 6, 2026
#### Overview

Adds a source-only NeMo Agent Toolkit (NAT) adapter under `external/` as the first third-party reference implementation of the public NeMo Fabric adapter contract.

The adapter translates typed `FabricConfig` input into an in-memory NAT `Config`, loads installed NAT components, and owns one persistent `WorkflowBuilder` and `SessionManager` across `start`, repeated `invoke`, and `stop`. This PR intentionally does not add wheel metadata, bundled catalog entries, or installed-adapter discovery wiring.

The typed workflow contract is already available on `main` through #176. This PR now contains only the external NAT reference adapter, its examples, and focused tests.

#### Details

- Adds the `nvidia.fabric.nat` descriptor and generic Python lifecycle runner.
- Selects NAT workflows through root `workflow.entrypoint` and maps `workflow.settings` into the selected NAT component; no NAT workflow YAML or `config_file` path is used.
- Uses descriptor `workflow_schema` as the single workflow support and validation claim. `harness.settings` is limited to registered NAT `functions` and `function_groups`.
- Maps normalized models and ReAct system instructions. Built-in ReAct behavior is applied only to NAT's short and canonical qualified ReAct references, so a third-party `custom/react_agent` is not mutated.
- Maps per-server MCP `allowed_tools` and `blocked_tools` into NAT `include` or `exclude` policy. An explicit empty allowlist fails closed by omitting the generated group because NAT interprets `include=[]` as unfiltered.
- Applies root `tools.enabled` and `tools.blocked` across NAT functions, function groups, and `<group>__<member>` selectors.
- Loads custom workflows, functions, and function groups through installed NAT `nat.components` registrations.
- Adds typed calculator-MCP and NAT-native email-phishing examples using the same root workflow contract. The calculator example includes a source-only stdio MCP server and requires no separately managed endpoint.
- Normalizes errors without exposing underlying exception text in NeMo Fabric results or stderr artifacts.

#### Validation

- `uv run --no-sync pytest -q tests/adapters/test_external_nat_adapter.py` — 52 passed, 2 optional real-NAT tests skipped when NAT is not installed.
- `just test-python` — 652 passed, 17 skipped.
- A direct MCP stdio protocol check discovered `add`, `subtract`, `multiply`, and `divide`, and returned `42.0` for `multiply(21, 2)`.
- Real NAT 1.8 typed-`Config` validation passed for both `react_agent` and `nat.plugins.langchain.agent.react_agent/react_agent`.
- Both typed examples produce current NeMo Fabric plans against the external descriptor.
- Changed-file pre-commit hooks and `git diff --check` passed.

Live model invocation was not exercised because it requires credentials.

#### Where should the reviewer start?

Start with `_nat_workflow`, `_is_react_agent`, and `build_nat_config_mapping` in `external/nat/src/nemo_fabric_adapters/nat/adapter.py`. Then review `workflow_schema` in `external/nat/fabric-adapter.json` and the root-workflow/example coverage in `tests/adapters/test_external_nat_adapter.py`.

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

- Relates to FABRIC-117
- Relates to #176

- [x] I confirm this contribution is my own work, or I have the right to submit it under this project's license.
- [x] I searched existing issues and open pull requests, and this does not duplicate existing work.

Authors:
  - Ajay Thorve (https://github.com/AjayThorve)

Approvers:
  - Zhongxuan (Daniel) Wang (https://github.com/zhongxuanwang-nv)

URL: #175
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