Skip to content

feat(agents): typed AgentSpec + explore-first onboarding chain (FP-161)#94

Open
aleckhoury wants to merge 16 commits into
mainfrom
fp-161-spec-schema-pydantic/akhoury
Open

feat(agents): typed AgentSpec + explore-first onboarding chain (FP-161)#94
aleckhoury wants to merge 16 commits into
mainfrom
fp-161-spec-schema-pydantic/akhoury

Conversation

@aleckhoury
Copy link
Copy Markdown
Contributor

@aleckhoury aleckhoury commented May 28, 2026

Summary

Make the agent spec a typed, server-side-visible artifact instead of an unstructured local markdown file, and rebuild the onboarding skill chain around it.

  • New AgentSpec Pydantic model (nemo_agents_plugin.spec) with hard validators on Job (vague-phrase rejection, min length) and Framework (langgraph-nat vs needs-wrapper enum). 12 body sections + 2 front-matter fields, sourced from the POR's existing + proposed sections table.
  • New spec_render module with bidirectional AgentSpec ↔ markdown round-trip. Strict parser: rejects unknown sections, duplicate sections, and malformed labeled bullets before the value reaches the Pydantic model.
  • spec_file_ref: FilesetRef | None on the Agent entity and CreateAgentRequest, with a --spec-file-ref flag on nemo agents create. Lets nemo agents list answer "which agents have an onboarded spec?" with a single field check.
  • nemo-explore SKILL.md rewritten to be explore-first and schema-driven: scans the codebase, fills every inferable field, presents the full spec in a single review block, and only asks for gaps. Replaces the hardcoded 12-question Q&A loop.
  • nemo-spec SKILL.md rewritten to validate against AgentSpec, refuse to write when Job or Framework is unresolved, upload the canonical copy to a per-agent Filesets fileset (Fileset is canonical, local file is a write-through cache), and hand SPEC_FILE_REF to nemo-build-agent.
  • nemo-build-agent SKILL.md updated to thread SPEC_FILE_REF through all three nemo agents create invocations.
  • Spec template rewritten to match the new schema + renderer. Drops the Known Issues section (handled by the Insights plugin's first-class entity instead).
  • Plugin OpenAPI regenerated; SDK skill copies re-vendored.

Test plan

  • 45 new unit tests across test_spec.py and test_spec_render.py covering schema, validators, JSON-schema export, render output shape, round-trip identity, and structural parse errors
  • test_entities.py / test_cli.py extended for spec_file_ref on Agent, CreateAgentRequest, and the new CLI flag
  • 102 tests pass across the touched files (pytest plugins/nemo-agents/tests/unit/test_{spec,spec_render,entities,cli,agents_api}.py)
  • ruff check + ruff format --check clean
  • ty check clean on changed files (two pre-existing diagnostics in setup.py unrelated, verified via stash)
  • pre-commit run -a passes all hooks except studio-lint-staged (pre-existing local node-version mismatch, only fires under -a)
  • Exercised end-to-end against an external AIQ checkout (NVIDIA-AI-Blueprints/aiq) via skill symlinks — nemo-explore codebase scan → single review pass → nemo-spec validate + Filesets upload → nemo-build-agent create with --spec-file-ref populated

Notes for reviewers

  • Field-level guidance ("what good looks like") deliberately lives in nemo-explore/SKILL.md, not in the schema docstrings, so the skill stays the single source of truth for interview prompts and the schema stays terse.
  • Framework is marked planned-deprecation in JSON schema (x-planned-deprecation) — expected to relax as NAT supports more frameworks; flagged so future-us can delete the field cleanly.
  • The Known Issues section was deliberately dropped from the schema per the design discussion: known issues / recurring failure patterns are first-class Insight entities owned by the insights plugin, not duplicated into markdown.
  • Stacked: PR2 (#pending) follows up with platform-startup default fixes discovered while testing this end-to-end.

Summary by CodeRabbit

  • New Features

    • Formal agent specification schema with standardized location convention.
    • Redesigned codebase exploration workflow with structured scan-first approach for agent configuration.
  • Documentation

    • Updated agent creation guides with enhanced pre-flight platform and specification checks.
    • Redesigned specification documentation with structured schema, clearer section formatting, and guided workflow (explore → review → handoff).
    • Improved specification template with strict formatting requirements and labeled-field structure.
  • Refactor

    • Streamlined agent configuration pipeline from question-by-question to explore-first, gap-fill-second approach.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 28, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Implements a canonical agent specification system: Pydantic schema with job/categories validation; markdown render/parse for bidirectional conversion; convention-based spec location helpers; and three integrated skill docs (nemo-spec, nemo-explore, nemo-build-agent) coordinating spec lifecycle, codebase exploration, and agent deployment with hard preconditions and Fileset-as-canonical storage.

Changes

Agent Spec System

Layer / File(s) Summary
Agent spec schema and field validation
plugins/nemo-agents/src/nemo_agents_plugin/spec.py
AgentSpec Pydantic model with FrameworkResolution, Framework, ModelChoice, AllowedChanges subtypes; job validator rejects denylisted vague phrases and enforces minimum length; categories validator trims and rejects empty entries; extra="forbid" blocks unknown fields.
Agent spec markdown template and parsing contract
packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/references/templates/agent-spec.md
Reference template defining YAML front matter (name, eval_command) and strict section formatting (bullet-only, labeled-bullet, free-form) for Job, Audience, Tools, Model, Framework, AllowedChanges, Feedback Signals, and other spec sections.
Spec markdown rendering and parsing
plugins/nemo-agents/src/nemo_agents_plugin/spec_render.py
render_spec() generates canonical markdown from AgentSpec with YAML front matter and ordered sections; parse_spec() validates front matter, splits sections via regex, maps labeled bullets to nested types, and raises SpecRenderError for structural/format violations.
Spec location derivation and API integration
plugins/nemo-agents/src/nemo_agents_plugin/entities.py
Adds AGENT_SPEC_FILENAME constant, agent_spec_fileset_name(), and agent_spec_file_ref() helpers that derive canonical spec location as workspace/<agent-name>-spec#AGENTSpec.md by convention; updates Agent docstring to clarify spec location is not persisted.
Skill workflow documentation and orchestration
packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/SKILL.md, packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-explore/SKILL.md, packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-build-agent/SKILL.md
Orchestrates three-skill flow: nemo-explore scans codebase, presents full spec schema, collects missing required fields (Job, Framework); nemo-spec renders deterministic markdown, validates schema round-trip, uploads to Filesets as canonical copy, enforces non-vague job and resolved framework before write; nemo-build-agent pre-flight checks spec fileset exists and delegates platform health to nemo-status.
AgentSpec schema validation tests
plugins/nemo-agents/tests/unit/test_spec.py
Validates schema round-trip, job phrase denylist and minimum-length enforcement, framework requirement, category trimming and empty-entry rejection, and extra="forbid" strictness.
Spec markdown rendering and parsing tests
plugins/nemo-agents/tests/unit/test_spec_render.py
Validates render_spec() omits null eval_command and renders empty lists as _(none)_; verifies round-trips for minimal/full-field/framework-variant specs and markdown table tools; asserts parse_spec() rejects missing/unknown/duplicate sections, invalid labels, and malformed bullets.
Spec location convention tests
plugins/nemo-agents/tests/unit/test_entities.py
Validates agent_spec_fileset_name() appends -spec suffix and agent_spec_file_ref(workspace, agent_name) composes workspace/<agent>-spec#AGENTSpec.md.
CLI payload type annotation
plugins/nemo-agents/src/nemo_agents_plugin/cli.py
Adds explicit dict[str, Any] type annotation to agent creation POST payload.

Suggested reviewers

  • parkanzky
  • tylersbray
  • gabwow
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.21% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title accurately captures the main changes: typed AgentSpec schema (Pydantic model with validators) and explore-first onboarding skill chain redesign.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fp-161-spec-schema-pydantic/akhoury

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

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🤖 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
`@packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-build-agent/SKILL.md`:
- Around line 47-50: The pre-flight check strips the workspace by using
${SPEC_FILE_REF#*/}, so the command nemo files filesets get only checks the
fileset name against the wrong workspace; fix it by preserving and passing the
full reference instead of just the part after the slash—either pass
"${SPEC_FILE_REF}" directly to nemo files filesets get or explicitly split into
workspace="${SPEC_FILE_REF%%/*}" and fileset="${SPEC_FILE_REF#*/}" and call nemo
files filesets get "${workspace}/${fileset}" so the check validates the intended
workspace and fileset together.

In
`@packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/references/templates/agent-spec.md`:
- Around line 55-57: The template contains free-form guidance lines inside
strict list sections which breaks parse_spec()—move any explanatory sentences
out of the "Constraints", "Open Questions", and "Allowed Changes" sections so
those sections contain only the allowed formats: for "Constraints" and "Open
Questions" only bullet items or exactly `_(none)_`, and for "Allowed Changes"
only labeled bullets; update the agent-spec.md template by removing or
relocating the guidance lines currently inside those headings (lines referenced
around the "Constraints", "Open Questions", and "Allowed Changes" sections) into
a preceding or trailing paragraph so parse_spec() can parse those sections
cleanly.

In `@packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/SKILL.md`:
- Line 3: The file uses two different canonical filenames (AGENTSpec.md and
AGENT_SPEC.md); choose AGENT_SPEC.md as the canonical name and replace all
occurrences of AGENTSpec.md, AGENTSpec, and any variants (e.g.,
agents/<name>.spec.md mentions that imply the other form) with AGENT_SPEC.md so
the description, the upload/verification sections, and the examples/usage blocks
(the parts that reference the AgentSpec schema, upload, and fileset steps)
consistently reference AGENT_SPEC.md.
- Around line 128-135: The SPEC_FILE_REF assignment always hardcodes "default"
and ignores any overridden workspace; update the logic that assigns
SPEC_FILE_REF (currently set to "default/${NAME}-spec") to use the actual
workspace variable (e.g., ${WORKSPACE} or the variable used elsewhere in this
file) so it becomes "${WORKSPACE}/${NAME}-spec" (falling back to "default" only
if workspace is unset), and ensure subsequent uses of SPEC_FILE_REF still
reference that variable.

In `@plugins/nemo-agents/src/nemo_agents_plugin/spec.py`:
- Line 185: Replace the Unicode EN DASH (U+2013) with an ASCII hyphen in the
description string so it reads "3-6 task buckets the agent handles."; update the
description value in plugins/nemo-agents/src/nemo_agents_plugin/spec.py where
the description parameter is defined to eliminate the en-dash and use a plain
hyphen.
- Around line 231-240: The _validate_job method currently strips whitespace but
does not re-check length, letting whitespace-padded short strings bypass
_MIN_JOB_LENGTH; update nemo_agents_plugin.spec._validate_job to, after
computing stripped = value.strip(), verify len(stripped) >= _MIN_JOB_LENGTH (or
use StringConstraints(strip_whitespace=True, min_length=_MIN_JOB_LENGTH) on the
job field) and raise a ValueError with a clear message (e.g., "'job' is too
short after trimming") if it fails; keep the existing vague-phrase check against
_VAGUE_JOB_PHRASES and return stripped when valid.

In `@plugins/nemo-agents/tests/unit/test_spec_render.py`:
- Line 151: The pytest assertion using pytest.raises(SpecRenderError,
match="missing section.*Audience") uses a normal string with regex
metacharacters; change the match argument to a raw string (e.g., match=r"missing
section.*Audience") to avoid RUF043 and ensure the regex is interpreted
correctly in the pytest.raises call that references SpecRenderError.
🪄 Autofix (Beta)

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: 75f72587-011d-4b89-a782-12a3dc39c53c

📥 Commits

Reviewing files that changed from the base of the PR and between 4f8e160 and 811445e.

⛔ Files ignored due to path filters (4)
  • sdk/python/nemo-platform/src/nemo_platform/skills/nemo-build-agent/SKILL.md is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/skills/nemo-explore/SKILL.md is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/skills/nemo-spec/SKILL.md is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/skills/nemo-spec/references/templates/agent-spec.md is excluded by !sdk/**
📒 Files selected for processing (15)
  • packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-build-agent/SKILL.md
  • packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-explore/SKILL.md
  • packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/SKILL.md
  • packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/references/templates/agent-spec.md
  • plugins/nemo-agents/openapi/openapi.yaml
  • plugins/nemo-agents/src/nemo_agents_plugin/api/v2/agents.py
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-agents/src/nemo_agents_plugin/entities.py
  • plugins/nemo-agents/src/nemo_agents_plugin/schema.py
  • plugins/nemo-agents/src/nemo_agents_plugin/spec.py
  • plugins/nemo-agents/src/nemo_agents_plugin/spec_render.py
  • plugins/nemo-agents/tests/unit/test_cli.py
  • plugins/nemo-agents/tests/unit/test_entities.py
  • plugins/nemo-agents/tests/unit/test_spec.py
  • plugins/nemo-agents/tests/unit/test_spec_render.py

Comment thread packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-build-agent/SKILL.md Outdated
Comment thread packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/SKILL.md Outdated
Comment thread packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/SKILL.md Outdated
Comment thread plugins/nemo-agents/src/nemo_agents_plugin/spec.py Outdated
Comment thread plugins/nemo-agents/src/nemo_agents_plugin/spec.py Outdated
Comment thread plugins/nemo-agents/tests/unit/test_spec_render.py Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 28, 2026

Suite Lines Covered Line Rate Branch Rate
Unit Tests 18717/24765 75.6% 62.0%
Integration Tests 11995/23529 51.0% 26.2%

Comment thread plugins/nemo-agents/src/nemo_agents_plugin/entities.py Outdated
aleckhoury added a commit that referenced this pull request Jun 1, 2026
Address PR #94 review feedback. The spec_file_ref field on Agent (and the
matching --spec-file-ref CLI flag, API request field, and SPEC_FILE_REF
shell ceremony in the skills) is redundant under the project's stated
constraints: spec and agent always live in the same workspace, and the
spec filename is the industry-standard AGENTSpec.md. The location is
fully derivable from (workspace, agent_name).

- Remove spec_file_ref from Agent entity, CreateAgentRequest schema,
  POST /agents handler, --spec-file-ref CLI option, and openapi.yaml.
- Add canonical helpers in nemo_agents_plugin.entities:
  AGENT_SPEC_FILENAME, agent_spec_fileset_name, agent_spec_file_ref.
  Downstream consumers (analyst, Studio, optimization loop) call these
  rather than reconstructing the path inline; layout changes are then
  a one-function migration.
- Canonicalize the filename to AGENTSpec.md across nemo-spec and
  nemo-build-agent skills and template; drop the SPEC_FILE_REF shell
  variable and the --spec-file-ref flag from skill bash blocks.
- Mirror skill changes to the vendored sdk/python copies.

Also picks up CodeRabbit review fixes:
- spec.py: re-enforce _MIN_JOB_LENGTH after strip (Pydantic min_length
  runs before @field_validator), with vague-phrase check first so the
  more specific diagnosis wins. Replace EN DASH with hyphen for RUF001.
- test_spec_render.py: raw regex string for RUF043.
- agent-spec.md template: move parse-rule guidance out of the strict
  Constraints / Allowed Changes / Open Questions sections into the
  top-level prose block.

Test suite trimmed from 80 to 62 tests by removing assertions that
re-state Field declarations or test Pydantic itself. Remaining tests
lock validators, the markdown round-trip, parser invariants, and the
new convention helpers.
aleckhoury added a commit that referenced this pull request Jun 1, 2026
Address PR #94 review feedback. The spec_file_ref field on Agent (and the
matching --spec-file-ref CLI flag, API request field, and SPEC_FILE_REF
shell ceremony in the skills) is redundant under the project's stated
constraints: spec and agent always live in the same workspace, and the
spec filename is the industry-standard AGENTSpec.md. The location is
fully derivable from (workspace, agent_name).

- Remove spec_file_ref from Agent entity, CreateAgentRequest schema,
  POST /agents handler, --spec-file-ref CLI option, and openapi.yaml.
- Add canonical helpers in nemo_agents_plugin.entities:
  AGENT_SPEC_FILENAME, agent_spec_fileset_name, agent_spec_file_ref.
  Downstream consumers (analyst, Studio, optimization loop) call these
  rather than reconstructing the path inline; layout changes are then
  a one-function migration.
- Canonicalize the filename to AGENTSpec.md across nemo-spec and
  nemo-build-agent skills and template; drop the SPEC_FILE_REF shell
  variable and the --spec-file-ref flag from skill bash blocks.
- Mirror skill changes to the vendored sdk/python copies.

Also picks up CodeRabbit review fixes:
- spec.py: re-enforce _MIN_JOB_LENGTH after strip (Pydantic min_length
  runs before @field_validator), with vague-phrase check first so the
  more specific diagnosis wins. Replace EN DASH with hyphen for RUF001.
- test_spec_render.py: raw regex string for RUF043.
- agent-spec.md template: move parse-rule guidance out of the strict
  Constraints / Allowed Changes / Open Questions sections into the
  top-level prose block.

Test suite trimmed from 80 to 62 tests by removing assertions that
re-state Field declarations or test Pydantic itself. Remaining tests
lock validators, the markdown round-trip, parser invariants, and the
new convention helpers.
aleckhoury added a commit that referenced this pull request Jun 1, 2026
Address PR #94 review feedback. The spec_file_ref field on Agent (and the
matching --spec-file-ref CLI flag, API request field, and SPEC_FILE_REF
shell ceremony in the skills) is redundant under the project's stated
constraints: spec and agent always live in the same workspace, and the
spec filename is the industry-standard AGENTSpec.md. The location is
fully derivable from (workspace, agent_name).

- Remove spec_file_ref from Agent entity, CreateAgentRequest schema,
  POST /agents handler, --spec-file-ref CLI option, and openapi.yaml.
- Add canonical helpers in nemo_agents_plugin.entities:
  AGENT_SPEC_FILENAME, agent_spec_fileset_name, agent_spec_file_ref.
  Downstream consumers (analyst, Studio, optimization loop) call these
  rather than reconstructing the path inline; layout changes are then
  a one-function migration.
- Canonicalize the filename to AGENTSpec.md across nemo-spec and
  nemo-build-agent skills and template; drop the SPEC_FILE_REF shell
  variable and the --spec-file-ref flag from skill bash blocks.
- Mirror skill changes to the vendored sdk/python copies.

Also picks up CodeRabbit review fixes:
- spec.py: re-enforce _MIN_JOB_LENGTH after strip (Pydantic min_length
  runs before @field_validator), with vague-phrase check first so the
  more specific diagnosis wins. Replace EN DASH with hyphen for RUF001.
- test_spec_render.py: raw regex string for RUF043.
- agent-spec.md template: move parse-rule guidance out of the strict
  Constraints / Allowed Changes / Open Questions sections into the
  top-level prose block.

Test suite trimmed from 80 to 62 tests by removing assertions that
re-state Field declarations or test Pydantic itself. Remaining tests
lock validators, the markdown round-trip, parser invariants, and the
new convention helpers.
@aleckhoury aleckhoury force-pushed the fp-161-spec-schema-pydantic/akhoury branch from c91baf3 to 4cfda64 Compare June 1, 2026 19:12
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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
`@packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/references/templates/agent-spec.md`:
- Around line 21-27: The rules list in agent-spec.md omits parser-enforced
bullet-list sections; update the Section-rules block to include `Categories` and
`Success Criteria` alongside `Constraints` and `Open Questions` so the parser
enforces list-only behavior for those sections; ensure you match the existing
phrasing/format (e.g., "- **Bullet sections** (`Constraints`, `Open Questions`,
`Categories`, `Success Criteria`): list items only. If the list is empty, write
`_(none)_`") so generated specs won't fail parsing.
🪄 Autofix (Beta)

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: e5de852a-03c4-49ce-aaf5-b0e136dee2cf

📥 Commits

Reviewing files that changed from the base of the PR and between 811445e and c91baf3.

⛔ Files ignored due to path filters (3)
  • sdk/python/nemo-platform/src/nemo_platform/skills/nemo-build-agent/SKILL.md is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/skills/nemo-spec/SKILL.md is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/skills/nemo-spec/references/templates/agent-spec.md is excluded by !sdk/**
📒 Files selected for processing (10)
  • packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-build-agent/SKILL.md
  • packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/SKILL.md
  • packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/references/templates/agent-spec.md
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-agents/src/nemo_agents_plugin/entities.py
  • plugins/nemo-agents/src/nemo_agents_plugin/spec.py
  • plugins/nemo-agents/tests/unit/test_cli.py
  • plugins/nemo-agents/tests/unit/test_entities.py
  • plugins/nemo-agents/tests/unit/test_spec.py
  • plugins/nemo-agents/tests/unit/test_spec_render.py
💤 Files with no reviewable changes (1)
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • plugins/nemo-agents/src/nemo_agents_plugin/spec.py
  • packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/SKILL.md

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/references/templates/agent-spec.md (1)

21-22: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Section-rules list still incomplete.

Categories and Success Criteria are also bullet-only sections but not listed here. Add them to prevent parse failures.

Suggested fix
-- **Bullet sections** (`Constraints`, `Open Questions`): list items only.
+- **Bullet sections** (`Categories`, `Constraints`, `Success Criteria`, `Open Questions`): list items only.
🤖 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
`@packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/references/templates/agent-spec.md`
around lines 21 - 22, The template's list of "bullet-only" sections is missing
"Categories" and "Success Criteria", causing parse failures; update the rule
block that currently mentions "Constraints" and "Open Questions" to also include
"Categories" and "Success Criteria" as bullet-only sections and ensure the same
empty-list convention (use `_(none)_`) is documented for them; look for the
section rules block in agent-spec.md that describes "Bullet sections" and add
those two section names so the parser enforces bullet-only content consistently.
🤖 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.

Duplicate comments:
In
`@packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/references/templates/agent-spec.md`:
- Around line 21-22: The template's list of "bullet-only" sections is missing
"Categories" and "Success Criteria", causing parse failures; update the rule
block that currently mentions "Constraints" and "Open Questions" to also include
"Categories" and "Success Criteria" as bullet-only sections and ensure the same
empty-list convention (use `_(none)_`) is documented for them; look for the
section rules block in agent-spec.md that describes "Bullet sections" and add
those two section names so the parser enforces bullet-only content consistently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: aac63af3-21ee-4e7b-9cfd-9068e4c6b03d

📥 Commits

Reviewing files that changed from the base of the PR and between c91baf3 and 4cfda64.

⛔ Files ignored due to path filters (3)
  • sdk/python/nemo-platform/src/nemo_platform/skills/nemo-build-agent/SKILL.md is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/skills/nemo-spec/SKILL.md is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/skills/nemo-spec/references/templates/agent-spec.md is excluded by !sdk/**
📒 Files selected for processing (10)
  • packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-build-agent/SKILL.md
  • packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/SKILL.md
  • packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/references/templates/agent-spec.md
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
  • plugins/nemo-agents/src/nemo_agents_plugin/entities.py
  • plugins/nemo-agents/src/nemo_agents_plugin/spec.py
  • plugins/nemo-agents/tests/unit/test_cli.py
  • plugins/nemo-agents/tests/unit/test_entities.py
  • plugins/nemo-agents/tests/unit/test_spec.py
  • plugins/nemo-agents/tests/unit/test_spec_render.py
💤 Files with no reviewable changes (1)
  • plugins/nemo-agents/src/nemo_agents_plugin/cli.py
🚧 Files skipped from review as they are similar to previous changes (7)
  • packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-build-agent/SKILL.md
  • plugins/nemo-agents/tests/unit/test_spec_render.py
  • plugins/nemo-agents/tests/unit/test_entities.py
  • plugins/nemo-agents/tests/unit/test_spec.py
  • packages/nemo_platform_ext/src/nemo_platform_ext/skills/nemo-spec/SKILL.md
  • plugins/nemo-agents/src/nemo_agents_plugin/spec.py
  • plugins/nemo-agents/src/nemo_agents_plugin/entities.py

aleckhoury added a commit that referenced this pull request Jun 1, 2026
Address PR #94 review feedback. The spec_file_ref field on Agent (and the
matching --spec-file-ref CLI flag, API request field, and SPEC_FILE_REF
shell ceremony in the skills) is redundant under the project's stated
constraints: spec and agent always live in the same workspace, and the
spec filename is the industry-standard AGENTSpec.md. The location is
fully derivable from (workspace, agent_name).

- Remove spec_file_ref from Agent entity, CreateAgentRequest schema,
  POST /agents handler, --spec-file-ref CLI option, and openapi.yaml.
- Add canonical helpers in nemo_agents_plugin.entities:
  AGENT_SPEC_FILENAME, agent_spec_fileset_name, agent_spec_file_ref.
  Downstream consumers (analyst, Studio, optimization loop) call these
  rather than reconstructing the path inline; layout changes are then
  a one-function migration.
- Canonicalize the filename to AGENTSpec.md across nemo-spec and
  nemo-build-agent skills and template; drop the SPEC_FILE_REF shell
  variable and the --spec-file-ref flag from skill bash blocks.
- Mirror skill changes to the vendored sdk/python copies.

Also picks up CodeRabbit review fixes:
- spec.py: re-enforce _MIN_JOB_LENGTH after strip (Pydantic min_length
  runs before @field_validator), with vague-phrase check first so the
  more specific diagnosis wins. Replace EN DASH with hyphen for RUF001.
- test_spec_render.py: raw regex string for RUF043.
- agent-spec.md template: move parse-rule guidance out of the strict
  Constraints / Allowed Changes / Open Questions sections into the
  top-level prose block.

Test suite trimmed from 80 to 62 tests by removing assertions that
re-state Field declarations or test Pydantic itself. Remaining tests
lock validators, the markdown round-trip, parser invariants, and the
new convention helpers.

Signed-off-by: Alec Khoury <akhoury@nvidia.com>
@aleckhoury aleckhoury force-pushed the fp-161-spec-schema-pydantic/akhoury branch from c367370 to 870a16f Compare June 1, 2026 20:11
Comment thread plugins/nemo-agents/tests/unit/test_spec_render.py Fixed
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 2, 2026

Documentation preview is ready

Preview: https://nvidia-nemo.github.io/nemo-platform/pr-preview/pr-94/pr-94/

Built from 66669bb in workflow run.

This preview is deployed from this PR branch, updates when docs changes are pushed, and will be removed when the PR closes.

aleckhoury added 10 commits June 2, 2026 15:37
Make the agent spec a typed, server-side-visible artifact instead of an
unstructured local markdown file, and rebuild the onboarding skill chain
around it.

What changes

- New AgentSpec Pydantic model (nemo_agents_plugin.spec) with hard
  validators on Job (vague-phrase rejection, min length) and Framework
  (LangGraph + NAT vs. needs-wrapper enum). 12 body sections + 2
  front-matter fields, sourced from the POR's existing + proposed sections
  table.
- New spec_render module with bidirectional AgentSpec <-> markdown
  round-trip. Strict parser: rejects unknown sections, duplicate sections,
  and malformed labeled bullets before the value reaches the Pydantic
  model.
- spec_file_ref: FilesetRef | None added to the Agent entity and
  CreateAgentRequest, with a --spec-file-ref flag on `nemo agents create`.
  Lets `nemo agents list` answer "which agents have an onboarded spec?"
  with a single field check.
- nemo-explore SKILL.md rewritten to be explore-first and schema-driven:
  scans the codebase, fills every inferable field, presents the full spec
  in a single review block, and only asks the user for gaps. Replaces the
  hardcoded 12-question Q&A loop.
- nemo-spec SKILL.md rewritten to validate against AgentSpec, refuse to
  write when Job or Framework is unresolved, upload the canonical copy to
  a per-agent Filesets fileset (Fileset is canonical, local file is a
  write-through cache), and hand SPEC_FILE_REF to nemo-build-agent.
- nemo-build-agent SKILL.md updated to thread SPEC_FILE_REF through all
  three `nemo agents create` invocations (initial deploy, RAG redeploy,
  guardrails redeploy).
- Spec template (references/templates/agent-spec.md) rewritten to match
  the new schema + renderer format. Drops the Known Issues section
  (handled by the Insights plugin's first-class entity instead).
- Plugin OpenAPI regenerated; SDK skill copies re-vendored.

Tests

- 45 new unit tests across test_spec.py and test_spec_render.py covering
  the schema, validators, JSON-schema export, render output shape,
  round-trip identity, and structural parse errors.
- test_entities.py / test_cli.py extended for spec_file_ref on Agent,
  CreateAgentRequest, and the new CLI flag.
- 102 tests pass across the touched files. ruff + ruff format + ty clean
  on changed files (two ty diagnostics pre-existing in setup.py, unrelated).

Signed-off-by: Alec Khoury <akhoury@nvidia.com>
Address PR #94 review feedback. The spec_file_ref field on Agent (and the
matching --spec-file-ref CLI flag, API request field, and SPEC_FILE_REF
shell ceremony in the skills) is redundant under the project's stated
constraints: spec and agent always live in the same workspace, and the
spec filename is the industry-standard AGENTSpec.md. The location is
fully derivable from (workspace, agent_name).

- Remove spec_file_ref from Agent entity, CreateAgentRequest schema,
  POST /agents handler, --spec-file-ref CLI option, and openapi.yaml.
- Add canonical helpers in nemo_agents_plugin.entities:
  AGENT_SPEC_FILENAME, agent_spec_fileset_name, agent_spec_file_ref.
  Downstream consumers (analyst, Studio, optimization loop) call these
  rather than reconstructing the path inline; layout changes are then
  a one-function migration.
- Canonicalize the filename to AGENTSpec.md across nemo-spec and
  nemo-build-agent skills and template; drop the SPEC_FILE_REF shell
  variable and the --spec-file-ref flag from skill bash blocks.
- Mirror skill changes to the vendored sdk/python copies.

Also picks up CodeRabbit review fixes:
- spec.py: re-enforce _MIN_JOB_LENGTH after strip (Pydantic min_length
  runs before @field_validator), with vague-phrase check first so the
  more specific diagnosis wins. Replace EN DASH with hyphen for RUF001.
- test_spec_render.py: raw regex string for RUF043.
- agent-spec.md template: move parse-rule guidance out of the strict
  Constraints / Allowed Changes / Open Questions sections into the
  top-level prose block.

Test suite trimmed from 80 to 62 tests by removing assertions that
re-state Field declarations or test Pydantic itself. Remaining tests
lock validators, the markdown round-trip, parser invariants, and the
new convention helpers.

Signed-off-by: Alec Khoury <akhoury@nvidia.com>
Second-pass audit of the spec/entity test additions, looking for tests
that lock Pydantic, Field declarations, or constants against themselves
rather than behavior we wrote. Cuts:

- test_no_spec_file_ref_field, test_spec_file_ref_field_rejected:
  assert pydantic silently drops unknown keys without ``extra="forbid"``.
- test_canonical_filename: ``assert AGENT_SPEC_FILENAME == "AGENTSpec.md"``
  locks a constant against itself.
- test_file_ref_uses_active_workspace: redundant with
  test_file_ref_combines_workspace_fileset_and_filename; both exercise
  the same one-line helper.
- test_missing_framework_rejected: tests pydantic's required-field
  handling — framework being required is in the type signature.
- test_category_count_out_of_range_rejected: tests
  ``Field(min_length=3, max_length=6)`` against itself.
- test_validation_error_propagates: tests that parse_spec calls
  AgentSpec(...), which is the next line in the function.

53 tests remain; all genuinely lock validator behavior, the markdown
round-trip contract, parser invariants, or the convention helpers.

Signed-off-by: Alec Khoury <akhoury@nvidia.com>
The CLI's create handler builds its payload from a fixed dict literal
with no source for spec_file_ref — asserting the key is absent locks
nothing the code could plausibly violate.

Signed-off-by: Alec Khoury <akhoury@nvidia.com>
The lsof + curl /v1/models block in nemo-build-agent's pre-flight was a
byte-for-byte duplicate of nemo-status's Step 1. Replace it with a
one-line reference so platform-health probing has a single owner and
future probe changes (new component, port change) land in one place.

Service-specific endpoint checks (Files API, Agents API) stay local to
the skills that need them — nemo-status doesn't probe those today, and
expanding it would change its character from user-facing dashboard to
programmatic health-check service.

Signed-off-by: Alec Khoury <akhoury@nvidia.com>
…and Notes

Final-sweep cleanups before merge:

- cli.py: revert the leftover ``payload: dict[str, Any]`` annotation. It
  was needed when ``payload`` had a conditional ``spec_file_ref`` update
  that widened the inferred type; with that gone the annotation is pure
  diff noise. ``cli.py`` is now byte-identical to ``main``.
- Rename the spec section ``## Eval Command`` to ``## Eval Command Notes``
  to match the underlying ``eval_command_notes`` field name. A human
  reading the markdown could reasonably put the actual command under the
  ``Eval Command`` header, but the runnable command lives in the
  ``eval_command`` front matter; this section is for notes about eval
  state. Updated in the renderer, template, both skills, and the SDK
  vendored copies.

Signed-off-by: Alec Khoury <akhoury@nvidia.com>
The manual yaml edit in 4cfda64 removed the spec_file_ref field but did
not pick up the new Agent class-docstring sentence pointing at
agent_spec_file_ref. Regenerated via make refresh-openapi.

Signed-off-by: Alec Khoury <akhoury@nvidia.com>
Signed-off-by: Alec Khoury <akhoury@nvidia.com>
Signed-off-by: Alec Khoury <akhoury@nvidia.com>
Signed-off-by: Alec Khoury <akhoury@nvidia.com>
@aleckhoury aleckhoury force-pushed the fp-161-spec-schema-pydantic/akhoury branch from acdbad5 to 695a420 Compare June 2, 2026 20:37
Signed-off-by: Alec Khoury <akhoury@nvidia.com>
Signed-off-by: Alec Khoury <akhoury@nvidia.com>
Signed-off-by: Alec Khoury <akhoury@nvidia.com>
Signed-off-by: Alec Khoury <akhoury@nvidia.com>
@aleckhoury aleckhoury requested a review from nicot June 3, 2026 19:18
Signed-off-by: Alec Khoury <akhoury@nvidia.com>
Copy link
Copy Markdown

@nicot nicot left a comment

Choose a reason for hiding this comment

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

Looking great!

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.

3 participants