Skip to content

feat(studio): make the example agent a Fabric one - #1229

Closed
marcusds wants to merge 1 commit into
mainfrom
studio-fabric-example-agent/mschwab
Closed

feat(studio): make the example agent a Fabric one#1229
marcusds wants to merge 1 commit into
mainfrom
studio-fabric-example-agent/mschwab

Conversation

@marcusds

@marcusds marcusds commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Create Example Agent offered one sample and it was NAT. nemo-agents-spec-v1 is the format nemo-build-agent produces by default, so the only agent a user could create from Studio was in the legacy format and no Studio path exercised the current one. This points the sample at the Fabric email-phishing agent added in #1117.

The loader already branches on config_format and writes models.default.model for nemo-agents-spec-v1, so only the registry entry and the static asset were missing — the unused configFormat field on SampleAgent was left for exactly this.

Related Issue

No tracking issue. Depends on #1219 — see Limitations.

Changes

  • SAMPLE_AGENTS now holds the Fabric email-phishing agent (configFormat: 'nemo-agents-spec-v1') in place of the NAT email-security-analyst entry.
  • Adds public/sample-agents/email-phishing-agent/agent.yaml as a byte-identical copy of plugins/nemo-agents/examples/nemo-agent-config/email-phishing-agent/agent.yaml (verified: same sha256), with a test asserting the two stay identical so they cannot drift silently.
  • Removes the now-unreferenced public/sample-agents/email-security-analyst/agent.yml. The directory itself stays: EVAL_CONFIG_SAMPLES serves both eval configs, their READMEs, and dataset.jsonl from it.
  • Extends the registry's invariant comment to cover the Fabric case — a NAT entry needs its custom _type installed in the deploy venv; a Fabric entry resolves its stdio MCP url as a console script on PATH, which email-phishing-iocs provides as a workspace member.
  • Adds tests for the registry: each entry's asset exists and declares the config_format the entry claims, the Fabric sample exposes the models.default slot the loader writes to, and generated sample names are still recognised by isSampleAgentName.

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with documentation updates
  • Documentation only
  • Contributor tooling or automation
  • CI, build, or test infrastructure

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Documentation updated for user-visible behavior
  • Documentation not applicable — justification: no user-facing docs name the example agent; the in-file invariant comment is updated instead.

Verification

  • Pull request title follows the repository's Conventional Commit format
  • Every commit includes an appropriate Signed-off-by: trailer
  • uv run pre-commit run -a passes, or any blocked checks are identified below
  • Targeted tests pass, or tests are marked not applicable above
  • No secrets, API keys, or credentials are included

Targeted validation:

  • pnpm --filter nemo-studio-ui typecheck — passed.
  • pnpm --filter nemo-studio-ui test — 315 files / 2857 tests, with intermittent 10s hook timeouts traced to machine load (load average 14 with an antivirus daemon saturating a core), not to this change. Every affected file passes on retry; the failures land in the global MSW beforeAll in vitest.setup.tsx or in a lazy-loaded CodeEditor, neither touched here.
  • npx eslint --fix --max-warnings 0 src/constants — clean.
  • uv run pre-commit run -a — every hook passed except Run uv lock with platform uv, which fails on a local toolchain mismatch: script/uv-lock.sh requires uv exactly 0.9.14 and this machine has 0.9.30. This PR changes no Python and no dependency metadata, the separate Check for uv.lock drift hook passed, and the run left the worktree unmodified. Not marked as passing above.

Limitations

Ordering. This should not merge before #1219. On its own it makes Studio's only example agent a Fabric one, and a Fabric agent cannot be evaluated from Studio until #1219 lands — the eval target is hardcoded to the NAT /generate, which the Fabric server does not serve. Merged first, this turns a latent bug into the default experience.

Not verified end to end. The sample has not been created through Studio and deployed. Its stdio MCP url resolves email-phishing-iocs on PATH, which uv sync --all-packages provides in a dev checkout as a workspace member, but a deployed run was not exercised.

Telemetry endpoint. The asset keeps the example's telemetry.atif.storage block, which posts ATIF to http://127.0.0.1:8080/apis/intake/.... That is correct for the default subprocess deployment, where the agent runs as a child process on the platform host, and wrong for the docker/k8s modes the deployment modal also offers, where 127.0.0.1 is the container. The port is likewise assumed. Left as-is deliberately: patching the Studio copy is what would make it drift from the plugin copy. The durable fix is to rewrite host-less ATIF endpoints at deploy time the way inject_fabric_gateway_url already rewrites model base_urls, which belongs on the backend rather than here.

Summary by CodeRabbit

  • New Features

    • Added a sample email phishing analyzer agent for inspecting complete email messages.
    • The analyzer can identify indicators of compromise and returns a structured phishing verdict.
    • Added support for Fabric-based agent configuration and NVIDIA model execution.
  • Changes

    • Replaced the previous email security analyst sample with the new phishing analyzer example.
    • Updated the sample-agent catalog to recognize and display the new configuration format.

Create Example Agent offered one sample, and it was NAT. nemo-agents-spec-v1 is
the format nemo-build-agent produces by default, so the one agent a user could
create from Studio was in the legacy format, and no Studio path exercised the
current one.

Point the sample at the email-phishing agent the Fabric example ships. The
loader already branches on config_format and writes models.default.model for
nemo-agents-spec-v1, so only the registry entry and the static asset were
missing — the unused configFormat field on SampleAgent was left for exactly this.

The asset is a byte-identical copy of the plugin example rather than an edited
variant, and a test asserts that, so the two cannot drift silently. It keeps the
example's telemetry block, which posts ATIF to 127.0.0.1:8080; that is correct
for a local platform and wrong for a remote one, and is the reason to keep the
copy honest rather than quietly patch it here.

The email-security-analyst directory stays: EVAL_CONFIG_SAMPLES serves both eval
configs, their READMEs, and the dataset from it. Only the now-unreferenced
agent.yml is removed.

The invariant comment gains the Fabric case. A NAT entry needs its custom _type
installed in the deploy venv; a Fabric entry resolves its stdio MCP url as a
console script on PATH, which email-phishing-iocs provides as a workspace member.

Signed-off-by: mschwab <mschwab@nvidia.com>
@github-actions github-actions Bot added the feat label Aug 10, 2026
@marcusds
marcusds force-pushed the studio-fabric-example-agent/mschwab branch from f292a59 to ddf44c7 Compare August 11, 2026 00:21
@github-actions

github-actions Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 32006/40616 78.8% 63.6%
Integration Tests 18552/38542 48.1% 20.8%

@marcusds
marcusds marked this pull request as ready for review August 11, 2026 00:25
@marcusds
marcusds requested review from a team as code owners August 11, 2026 00:25
@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

The Studio sample-agent catalog now replaces the NAT email security analyst with a Fabric-based email phishing analyzer. The new asset defines DeepAgents orchestration, optional IOC extraction, YAML verdict output, and relay telemetry. Tests validate the asset and registry metadata.

Email phishing agent migration

Layer / File(s) Summary
Email phishing agent configuration
web/packages/studio/public/sample-agents/email-phishing-agent/agent.yaml
Adds the orchestrator, phishing analyzer subagent, YAML verdict schema, NVIDIA model, extract_iocs MCP tool, runtime paths, and relay telemetry settings.
Studio registry and asset validation
web/packages/studio/src/constants/sampleAgents.ts, web/packages/studio/src/constants/sampleAgents.test.ts
Registers the Fabric sample, documents Fabric MCP and NAT custom-tool resolution, and validates configuration format, model structure, source parity, and generated sample names.

Sequence Diagram(s)

sequenceDiagram
  participant Orchestrator
  participant PhishingAnalyzer
  participant ExtractIOCs
  participant RelayTelemetry
  Orchestrator->>PhishingAnalyzer: delegate email verdict generation
  PhishingAnalyzer->>ExtractIOCs: optionally extract IOCs
  PhishingAnalyzer-->>Orchestrator: return YAML verdict
  Orchestrator->>RelayTelemetry: emit ATIF/ATOF output
Loading

Possibly related PRs

Suggested reviewers: steramae-nvidia

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: switching Studio's example agent to a Fabric agent.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch studio-fabric-example-agent/mschwab

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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 `@web/packages/studio/src/constants/sampleAgents.test.ts`:
- Around line 21-27: Update the test around
getSampleAgent('email_phishing_agent') to assert that sample.key equals
'email_phishing_agent' before validating the Fabric configuration, ensuring the
test does not pass through the unknown-key fallback.
🪄 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: CHILL

Plan: Enterprise

Run ID: d8bd3803-3c86-4fff-b3c4-bf62f443d473

📥 Commits

Reviewing files that changed from the base of the PR and between f0c28ac and ddf44c7.

📒 Files selected for processing (4)
  • web/packages/studio/public/sample-agents/email-phishing-agent/agent.yaml
  • web/packages/studio/public/sample-agents/email-security-analyst/agent.yml
  • web/packages/studio/src/constants/sampleAgents.test.ts
  • web/packages/studio/src/constants/sampleAgents.ts
💤 Files with no reviewable changes (1)
  • web/packages/studio/public/sample-agents/email-security-analyst/agent.yml

Comment on lines +21 to +27
it('the Fabric sample exposes the model slot loadSampleAgentConfig writes to', () => {
const sample = getSampleAgent('email_phishing_agent');
const text = readFileSync(join(PUBLIC_DIR, sample.agentConfigPath), 'utf8');
const config = YAML.parse(text) as { models?: { default?: { model?: string } } };

expect(sample.configFormat).toBe('nemo-agents-spec-v1');
expect(config.models?.default).toBeDefined();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the selected sample key.

getSampleAgent falls back to SAMPLE_AGENTS[0] for an unknown key. Assert sample.key === 'email_phishing_agent' before validating the Fabric configuration.

Proposed fix
   const sample = getSampleAgent('email_phishing_agent');
+  expect(sample.key).toBe('email_phishing_agent');
   const text = readFileSync(join(PUBLIC_DIR, sample.agentConfigPath), 'utf8');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('the Fabric sample exposes the model slot loadSampleAgentConfig writes to', () => {
const sample = getSampleAgent('email_phishing_agent');
const text = readFileSync(join(PUBLIC_DIR, sample.agentConfigPath), 'utf8');
const config = YAML.parse(text) as { models?: { default?: { model?: string } } };
expect(sample.configFormat).toBe('nemo-agents-spec-v1');
expect(config.models?.default).toBeDefined();
it('the Fabric sample exposes the model slot loadSampleAgentConfig writes to', () => {
const sample = getSampleAgent('email_phishing_agent');
expect(sample.key).toBe('email_phishing_agent');
const text = readFileSync(join(PUBLIC_DIR, sample.agentConfigPath), 'utf8');
const config = YAML.parse(text) as { models?: { default?: { model?: string } } };
expect(sample.configFormat).toBe('nemo-agents-spec-v1');
expect(config.models?.default).toBeDefined();
🤖 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 `@web/packages/studio/src/constants/sampleAgents.test.ts` around lines 21 - 27,
Update the test around getSampleAgent('email_phishing_agent') to assert that
sample.key equals 'email_phishing_agent' before validating the Fabric
configuration, ensuring the test does not pass through the unknown-key fallback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant