Skip to content

fix(agent-eval): stop leaking task.intent to the agent under evaluation - #605

Merged
SandyChapman merged 1 commit into
mainfrom
claude/gallant-noether-ac62cb
Jul 14, 2026
Merged

fix(agent-eval): stop leaking task.intent to the agent under evaluation#605
SandyChapman merged 1 commit into
mainfrom
claude/gallant-noether-ac62cb

Conversation

@SandyChapman

@SandyChapman SandyChapman commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Problem

The agent-eval runtimes framed the harness prompt with task.intent — the eval-side description of the desired behavior (what the grader checks for). Handing that to the agent under evaluation is a reward-hacking hole: the agent can read the grader's intent and target it directly. Same class of concern as the held-out-reference field work (AGENT-EVAL).

Three runtimes leaked it:

  • FabricAgentRuntimef"Task id: {id}\nIntent: {intent}\nInputs: {inputs}\n"
  • default_codex_prompt — an explicit Intent: {task.intent} line
  • docker_sandbox._task_promptintent as the last-resort fallback, written into the agent's instruction.md

Change

Unify the framing so every runtime builds the prompt from task.inputs only:

  • New runtimes/fabric/_common.py with a shared, intent-free fabric_input: task id → instruction (inputs["instruction"|"prompt"]) → remaining inputs content → seed files listed by name (not dumped inline). The host FabricAgentRuntime now calls it. Built as the shared home so the AALGO-321 container runtime (PR feat(evaluator-sdk): sandboxed containerized Fabric runner (AALGO-321) #604) reuses it instead of carrying its own copy.
  • default_codex_prompt drops the Intent: line, lifts the instruction from inputs, keeps its workspace-edit trailer.
  • docker_sandbox._task_prompt no longer falls back to task.intent; a task with no instruction in inputs yields an empty prompt rather than leaking intent.

Tests

Updated test_fabric_runtime.py, test_codex_runtime.py, and test_docker_sandbox_runtime.py to lock in the intent-free contract across all three runtimes (assert instruction is surfaced, intent text and Intent: label are absent).

  • pytest (all three suites) → 34 passed
  • ruff check / ruff format → clean
  • ty → no new diagnostics

Relates to AALGO-321 fabric-runtime dedup (PR #604).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Updated prompt framing across Codex, Docker sandbox, and Fabric to use only task instruction/prompt (with instruction taking priority) and to omit any evaluation intent details.
    • Simplified prompt payloads by generating the Inputs: JSON from remaining task inputs only, excluding instruction-related fields and the seeded-files key.
    • Adjusted seeded-workspace behavior so staged file metadata/content isn’t inlined into the agent prompt.
  • Tests
    • Tightened Codex prompt redaction checks and updated seed-related expectations.
    • Updated Docker sandbox and Fabric tests to ensure intent is never present and seeded content isn’t inlined.

@SandyChapman
SandyChapman requested review from a team as code owners July 8, 2026 15:03
@github-actions github-actions Bot added the fix label Jul 8, 2026
@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

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

Prompt construction in Codex, Docker sandbox, and Fabric runtimes now excludes task.intent and derives instructions from task.inputs. Fabric uses a shared helper, and tests now assert the revised prompt contents.

Changes

Intent-free prompt construction

Layer / File(s) Summary
Codex prompt construction and tests
packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/codex/runtime.py, packages/nemo_evaluator_sdk/tests/agent_eval/test_codex_runtime.py
default_codex_prompt now pulls instruction from task.inputs, filters instruction/prompt and seed-file inputs from the JSON body, and stops emitting Intent:; tests assert Intent: is absent and seed filename assertions were removed.
Docker sandbox prompt construction and tests
packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/docker_sandbox.py, packages/nemo_evaluator_sdk/tests/agent_eval/test_docker_sandbox_runtime.py
_task_prompt now uses only task.inputs["prompt"]/["instruction"], removing the task.intent fallback; the test now expects an empty prompt when both are missing and checks intent text is absent.
Shared Fabric prompt helper, wiring, and tests
packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py, packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py, packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
fabric_input and _instruction build prompts from task.inputs without task.intent; runtime.py imports and uses the shared helper instead of the removed local one; tests cover intent exclusion and seed-file handling.

Suggested reviewers: ngoncharenko, arpitsardhana

🚥 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 accurately summarizes the main change: removing task.intent leakage from agent-eval prompts.
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
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/gallant-noether-ac62cb

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.

🧹 Nitpick comments (1)
packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/codex/runtime.py (1)

389-416: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Intent removed correctly; consider deduping vs. fabric_input.

Logic here (instruction derivation, body_inputs filtering, seed-file listing) is nearly identical to the new fabric_input/_instruction helpers in fabric/_common.py. That module's own docstring argues for centralizing this exact logic to prevent security-relevant drift between runtimes — the same argument applies here since default_codex_prompt isn't sharing that implementation.

Consider extracting a shared prompt-framing helper (e.g. instruction resolution + body-input filtering) usable by both codex and fabric runtimes, so future changes to intent-exclusion logic can't accidentally apply to one runtime and not the other.

🤖 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_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/codex/runtime.py`
around lines 389 - 416, The prompt framing logic in default_codex_prompt
duplicates the instruction resolution, body_inputs filtering, and seed-file
handling already being centralized in fabric/_common.py. Refactor this function
to call a shared helper used by both the codex and fabric runtimes for deriving
the instruction and filtering inputs, and keep only codex-specific wording here
so the intent-exclusion behavior stays consistent across runtimes.
🤖 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.

Nitpick comments:
In
`@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/codex/runtime.py`:
- Around line 389-416: The prompt framing logic in default_codex_prompt
duplicates the instruction resolution, body_inputs filtering, and seed-file
handling already being centralized in fabric/_common.py. Refactor this function
to call a shared helper used by both the codex and fabric runtimes for deriving
the instruction and filtering inputs, and keep only codex-specific wording here
so the intent-exclusion behavior stays consistent across runtimes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 8c8c88d4-7bdc-4c84-99e2-f694a811be0a

📥 Commits

Reviewing files that changed from the base of the PR and between ccb9d26 and 9b09903.

📒 Files selected for processing (7)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/codex/runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/docker_sandbox.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_codex_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_docker_sandbox_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py

@SandyChapman
SandyChapman force-pushed the claude/gallant-noether-ac62cb branch from 9b09903 to 580b4c5 Compare July 8, 2026 15:15

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

🧹 Nitpick comments (1)
packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py (1)

17-17: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

from __future__ import annotations stringifies type hints.

Conflicts with guideline to prefer concrete over string-based type hints. Drop it since annotations here (str | None, Mapping, Sequence) work fine without it.

As per coding guidelines, "In Python code, prefer concrete type hints over string-based type hints, and do not import those types only under TYPE_CHECKING; import them normally when possible."

🤖 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_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py`
at line 17, Remove the future annotations import from the module so type hints
stay concrete rather than stringified. The affected symbols are the module-level
annotations that use str | None, Mapping, and Sequence in the same file; verify
they still resolve normally without from __future__ import annotations and keep
the imports for those types as regular runtime imports rather than
TYPE_CHECKING-only.

Source: Coding guidelines

🤖 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.

Nitpick comments:
In
`@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py`:
- Line 17: Remove the future annotations import from the module so type hints
stay concrete rather than stringified. The affected symbols are the module-level
annotations that use str | None, Mapping, and Sequence in the same file; verify
they still resolve normally without from __future__ import annotations and keep
the imports for those types as regular runtime imports rather than
TYPE_CHECKING-only.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a53fc711-4e90-455d-91a7-532c29687fc5

📥 Commits

Reviewing files that changed from the base of the PR and between 9b09903 and 580b4c5.

📒 Files selected for processing (7)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/codex/runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/docker_sandbox.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_codex_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_docker_sandbox_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_codex_runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/codex/runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/docker_sandbox.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_docker_sandbox_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 23849/31015 76.9% 61.7%
Integration Tests 13811/29664 46.6% 19.6%

@SandyChapman
SandyChapman force-pushed the claude/gallant-noether-ac62cb branch from 580b4c5 to 741ddb6 Compare July 8, 2026 15:28

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

🧹 Nitpick comments (1)
packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py (1)

62-69: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Minor: redundant branching.

Can collapse to one return:

♻️ Simplify
-    for key in _INSTRUCTION_KEYS:
-        value = inputs.get(key)
-        if isinstance(value, str) and value:
-            return value
-        if value:
-            return str(value)
-    return None
+    for key in _INSTRUCTION_KEYS:
+        value = inputs.get(key)
+        if value:
+            return value if isinstance(value, str) else str(value)
+    return None
🤖 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_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py`
around lines 62 - 69, The _instruction helper has redundant branching when
reading from _INSTRUCTION_KEYS; simplify the logic in _instruction by using a
single return path for non-empty values instead of separate string and truthy
checks. Keep the same behavior for string and non-string values, but collapse
the conditional flow so the value is handled in one place.
🤖 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.

Nitpick comments:
In
`@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py`:
- Around line 62-69: The _instruction helper has redundant branching when
reading from _INSTRUCTION_KEYS; simplify the logic in _instruction by using a
single return path for non-empty values instead of separate string and truthy
checks. Keep the same behavior for string and non-string values, but collapse
the conditional flow so the value is handled in one place.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c517fb11-cd33-4e4a-85d9-fbf854cf1cbf

📥 Commits

Reviewing files that changed from the base of the PR and between 580b4c5 and 741ddb6.

⛔ Files ignored due to path filters (4)
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/codex/runtime.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/docker_sandbox.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/_common.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/beta/evaluator/agent_eval/runtimes/fabric/runtime.py is excluded by !sdk/**
📒 Files selected for processing (7)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/codex/runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/docker_sandbox.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_codex_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_docker_sandbox_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
🚧 Files skipped from review as they are similar to previous changes (6)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/codex/runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_docker_sandbox_runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/docker_sandbox.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_codex_runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py

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

🧹 Nitpick comments (1)
packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py (1)

51-58: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Simplify branching.

-    for key in _INSTRUCTION_KEYS:
-        value = inputs.get(key)
-        if isinstance(value, str) and value:
-            return value
-        if value:
-            return str(value)
-    return None
+    for key in _INSTRUCTION_KEYS:
+        value = inputs.get(key)
+        if value:
+            return value if isinstance(value, str) else str(value)
+    return None
🤖 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_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py`
around lines 51 - 58, The _instruction helper has redundant branching when
checking values from _INSTRUCTION_KEYS. Simplify the logic in _instruction by
collapsing the string and truthy checks into a single path so it returns the
first non-empty value consistently, while preserving the existing behavior of
returning the original string when possible and stringifying other truthy
values.
🤖 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.

Nitpick comments:
In
`@packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py`:
- Around line 51-58: The _instruction helper has redundant branching when
checking values from _INSTRUCTION_KEYS. Simplify the logic in _instruction by
collapsing the string and truthy checks into a single path so it returns the
first non-empty value consistently, while preserving the existing behavior of
returning the original string when possible and stringifying other truthy
values.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c25ce1cd-d118-42a3-bf48-70b568cc5098

📥 Commits

Reviewing files that changed from the base of the PR and between 741ddb6 and 3aabb1d.

📒 Files selected for processing (5)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/codex/runtime.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/_common.py
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_codex_runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/nemo_evaluator_sdk/src/nemo_evaluator_sdk/agent_eval/runtimes/fabric/runtime.py
  • packages/nemo_evaluator_sdk/tests/agent_eval/test_fabric_runtime.py

@SandyChapman
SandyChapman force-pushed the claude/gallant-noether-ac62cb branch 2 times, most recently from 0173310 to a53beca Compare July 9, 2026 19:41
The prompt handed to the agent under evaluation is now exactly the task's
natural-language instruction (inputs["instruction"]) with no runtime-added
framing. intent stays eval-side only (a reward-hacking hole if leaked).

- Add AgentEvalTask.agent_prompt(): resolves inputs["instruction"], raising when
  it is absent so an instruction-less task fails-and-skips.
- Route the fabric, codex, and docker-sandbox runtimes through it and delete the
  duplicated prompt resolvers; drop the prompt/intent fallbacks (_task_row no
  longer falls back to task.intent).
- Also stop persisting grader-only fields (intent, reference) into the codex
  evidence dir: the docker variant mounts it into the sandbox (danger-full-access),
  so task.json is redacted to keep the held-out ground truth out of the agent's reach.

Signed-off-by: Sandy Chapman <schapman@nvidia.com>
@SandyChapman
SandyChapman force-pushed the claude/gallant-noether-ac62cb branch from a53beca to 44610da Compare July 14, 2026 12:26
@SandyChapman
SandyChapman enabled auto-merge July 14, 2026 12:29
@SandyChapman
SandyChapman added this pull request to the merge queue Jul 14, 2026
Merged via the queue into main with commit 9c4584b Jul 14, 2026
55 checks passed
@SandyChapman
SandyChapman deleted the claude/gallant-noether-ac62cb branch July 14, 2026 12:55
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