Skip to content

fix(intake): accept ATIF observation on all step types - #1189

Merged
walston merged 6 commits into
mainfrom
intake-atif-observation-all-steps/nwalston
Aug 10, 2026
Merged

fix(intake): accept ATIF observation on all step types#1189
walston merged 6 commits into
mainfrom
intake-atif-observation-all-steps/nwalston

Conversation

@walston

@walston walston commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Problem

Relay emits an observation on any ATIF step, but Intake's schema only permitted observation on agent steps. In-process harnesses like DeepAgents attach an observation to a nested system step, so Intake rejected the entire ATIF POST with HTTP 422 and stored nothing — DeepAgents traces never reached Intake/Studio.

Diagnosed by @yczhang-nv (Yuchen Zhang), who also recommended the fix below.

Fix

  • Move observation from AtifStepAgent to the shared AtifStepBase, so every step type (system/user/agent) can carry one.
  • Run the observation validators (validate_atif_tool_call_references, validate_atif_v17_subagent_ref_resolution_keys) on all step types (tool-call ids are still sourced only from agent steps).
  • Let the mapper read observations on any step (_step_observation no longer gates on AtifStepAgent).
  • Add a regression test reproducing a DeepAgents nested-system-step observation.

Verification

  • ruff + ty clean; services/intake/tests/test_atif_v17.py 23/23 pass (incl. the new test_atif_v17_observation_on_nested_system_step).
  • E2E: with this fix, invoking a DeepAgents agent produces Intake spans including the previously-422ing nested system-* steps — confirmed both via the Intake spans API and in the Studio trace view.

Notes

Independent Intake bug fix, split out from the Fabric email-phishing example work. Getting DeepAgents to emit ATIF additionally requires Fabric ≥ 0207e06 (0.2.0); that dependency bump is a separate, platform-wide change and is not part of this PR.

Summary by CodeRabbit

  • New Features

    • ATIF agent, system, and user steps can now include optional observations through the API.
    • Observation data and results are preserved when converted into nested spans.
  • Bug Fixes

    • Observation and tool-call references are validated consistently across supported step types.
  • Documentation

    • Clarified how execution profiles are filtered and returned across deployment configurations.
  • Tests

    • Added regression coverage for system-step observations, references, and mapping behavior.

Relay emits an `observation` on any ATIF step, but Intake only permitted it on
agent steps. In-process harnesses like DeepAgents put an observation on a nested
system step, so Intake rejected the entire ATIF POST with HTTP 422 and stored
nothing.

Move `observation` from AtifStepAgent to the shared AtifStepBase; run the
tool-call-reference and v1.7 subagent-ref validators on all step types; let the
mapper read observations on any step. Adds a regression test reproducing a
DeepAgents nested-system-step observation.

Co-authored-by: Yuchen Zhang <134643420+yczhang-nv@users.noreply.github.com>
Signed-off-by: Nathan Walston <nwalston@nvidia.com>
@walston
walston requested review from a team as code owners August 7, 2026 21:45
@github-actions github-actions Bot added the fix label Aug 7, 2026
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a49a251c-2596-495e-a01e-a34d4b1cc6bf

📥 Commits

Reviewing files that changed from the base of the PR and between b6ff20a and 2a38418.

⛔ Files ignored due to path filters (6)
  • sdk/python/nemo-platform/.nmpcontext/openapi.yaml is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/cli/commands/api/jobs/__init__.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/resources/jobs/jobs.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/intake/ingest/atif_step_system_param.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/intake/ingest/atif_step_user_param.py is excluded by !sdk/**
  • sdk/python/nemo-platform/tests/api_resources/intake/ingest/test_atif.py is excluded by !sdk/**
📒 Files selected for processing (2)
  • docs/cli/reference.mdx
  • packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/__init__.py

📝 Walkthrough

Walkthrough

ATIF observations are defined on the shared step base, exposed in the OpenAPI schemas, validated for non-agent steps, mapped for all step types, and covered by a nested system-step regression test. Execution-profile documentation now describes capability filtering and topology-specific results.

Changes

ATIF observation handling

Layer / File(s) Summary
Step observation contracts
openapi/ga/individual/platform.openapi.yaml, openapi/ga/openapi.yaml, openapi/openapi.yaml
The schemas now support optional observations on agent, system, and user steps.
Shared observation and validation
services/intake/src/nmp/intake/spans/ingest/atif_domain.py
AtifStepBase now stores observations. Tool-call and subagent-reference validation now processes observations on applicable step types.
Observation mapping and regression coverage
services/intake/src/nmp/intake/spans/ingest/atif_mapping.py, services/intake/tests/test_atif_v17.py
_step_observation maps observations from all step types. Tests cover nested system-step observations, validation, preservation, and span mapping.

Execution-profile listing documentation

Layer / File(s) Summary
Execution-profile behavior documentation
docs/cli/reference.mdx, packages/nemo_platform_ext/src/nemo_platform_ext/cli/commands/api/jobs/__init__.py
The documentation describes capability filtering, standalone controller pruning, and split-topology API merge results.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% 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 The title clearly and concisely describes the main change: Intake now accepts ATIF observations on all step types.
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
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch intake-atif-observation-all-steps/nwalston

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 `@services/intake/tests/test_atif_v17.py`:
- Around line 1094-1100: Strengthen the assertions in the trajectory_to_spans
test around the non-agent observation case by locating the nested system-step
span and verifying its mapped output or raw observation attributes contain
“is_likely_phishing: true”. Keep the existing spans presence assertion, but
ensure the test fails when _step_observation returns None.
🪄 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: ec1b351f-05d2-4e02-926d-00736b7605c6

📥 Commits

Reviewing files that changed from the base of the PR and between e32287b and 44af795.

📒 Files selected for processing (3)
  • services/intake/src/nmp/intake/spans/ingest/atif_domain.py
  • services/intake/src/nmp/intake/spans/ingest/atif_mapping.py
  • services/intake/tests/test_atif_v17.py

Comment thread services/intake/tests/test_atif_v17.py Outdated
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 32004/40616 78.8% 63.5%
Integration Tests 18550/38542 48.1% 20.8%

Address review: the prior `assert spans` passed even if `_step_observation`
regressed to agent-only, since trajectory/step spans emit independently. Locate
the nested system-step span and assert `_step_observation` returns the
observation value on the non-agent step, so the test fails if the mapper stops
reading observations there.

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
@walston
walston enabled auto-merge August 10, 2026 18:31
walston and others added 2 commits August 10, 2026 12:17
…on-all-steps/nwalston

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
The intake fix moved `observation` from `AtifStepAgent` to `AtifStepBase`,
which changes the ATIF ingest contract: `observation` now appears on the
`system` and `user` step schemas as well. Regenerated via
`script/generate-openapi-spec.sh`; no hand edits.

Co-authored-by: Yuchen Zhang <134643420+yczhang-nv@users.noreply.github.com>
Signed-off-by: Nathan Walston <nwalston@nvidia.com>
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

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.

Stainless sync (`sdk/stainless.sh sync`) for the ATIF ingest contract change:
`observation` moved from `AtifStepAgent` to `AtifStepBase`, so the generated
`AtifStepSystemParam` / `AtifStepUserParam` models now carry it, and the
`.nmpcontext` snapshot matches the regenerated spec (clears `lint-python-sdk`).

Also sweeps one unrelated docstring-only update in `resources/jobs/jobs.py`
(execution-profiles description), which was pre-existing drift on main picked up
by the clean regen — generated output, not hand-edited.

Co-authored-by: Yuchen Zhang <134643420+yczhang-nv@users.noreply.github.com>
Signed-off-by: Nathan Walston <nwalston@nvidia.com>
@walston

walston commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

Pushed two follow-up commits to clear the CI blockers (no change to the fix itself):

  1. chore(openapi): regenerate spec — moving observation to AtifStepBase changes the ATIF ingest contract, so observation now appears on the system and user step schemas too. lint-openapi regenerates + diffs, so the committed specs were stale. Regenerated via script/generate-openapi-spec.sh (no hand edits): openapi/openapi.yaml, openapi/ga/openapi.yaml, openapi/ga/individual/platform.openapi.yaml — +8/-2 each, all the same observation delta.

  2. chore(sdk): regenerate SDKlint-python-sdk (is-up-to-date) diffs the vendored SDK's .nmpcontext snapshot against the live spec. Ran sdk/stainless.sh sync; result is 5 files: observation added to AtifStepSystemParam/AtifStepUserParam, refreshed .nmpcontext/openapi.yaml, and generated test coverage. is-up-to-date now reports up to date.

One heads-up for review: the SDK regen also swept a docstring-only update in resources/jobs/jobs.py (execution-profiles description) — pre-existing drift on main where the spec text had changed but the SDK hadn't been regenerated. It's generated output, so I left it rather than hand-editing the generated tree. Happy to split it out if you'd prefer this PR stay strictly ATIF-scoped.

`lint-cli` runs `make update-cli` and fails if it dirties the tree. Running it
regenerates the jobs execution-profiles docstring in the generated CLI command
(and its vendored SDK copy + CLI reference docs).

This is drift from #1082 (AIRCORE-971, merged to main today), which changed the
jobs API docstring without regenerating the spec/SDK/CLI — swept up here by the
clean regen, since the generators produce it deterministically and the branch
cannot go green otherwise. Generated output, no hand edits.

Co-authored-by: Yuchen Zhang <134643420+yczhang-nv@users.noreply.github.com>
Signed-off-by: Nathan Walston <nwalston@nvidia.com>
@github-actions

Copy link
Copy Markdown
Contributor

@walston
walston added this pull request to the merge queue Aug 10, 2026
Merged via the queue into main with commit b08e2a6 Aug 10, 2026
58 checks passed
@walston
walston deleted the intake-atif-observation-all-steps/nwalston branch August 10, 2026 20:21
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.

3 participants