Skip to content

Add an interception example environment - #2170

Closed
xeophon wants to merge 5 commits into
agent/intercept-policiesfrom
agent/interception-example-env
Closed

Add an interception example environment#2170
xeophon wants to merge 5 commits into
agent/intercept-policiesfrom
agent/interception-example-env

Conversation

@xeophon

@xeophon xeophon commented Jul 29, 2026

Copy link
Copy Markdown
Member

Overview

This adds a small runnable environment showing the minimal custom interception interface.

The task defines one deterministic guard and one judge-backed guard directly with @vf.intercept. Both receive one vf.Trace; the deterministic guard reads trace.last_message, the judge sees trace.messages, and either can return trace.replace(content) to rewrite the candidate.

What this PR adds

  • An environments/interception_v1 package with two focused examples.
  • A deterministic guard based on trace.last_message.
  • A judge-backed guard based on trace.messages.
  • Explicit priority ordering between the two guards.
  • A reward that reads interception records from the trace.
  • A short README with the complete handler shape.

Stack

This is PR 5 of 5. Each PR is based on the one before it and is intended to merge in order.

  1. Stream replay safety — keep an explicitly retried streamed request on the same model response.
  2. Request and response interception — run @vf.intercept before model requests and before responses reach the harness, and make rewrites canonical.
  3. Terminal interception — let a guard end a rollout with a final reason and reward.
  4. Reusable guards — add common tool guards and make custom handlers operate directly on vf.Trace.
  5. Example environment — show deterministic and judge-backed trace guards directly with @vf.intercept in a runnable taskset.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 976b3f6d5f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@@ -0,0 +1,13 @@
[project]
name = "interception-v1"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Register the example with the root uv environment

In the checked-in live v1 E2E path, .github/workflows/test.yml runs uv sync, then tests/v1/test_envs.py discovers every environments/*_v1 directory and invokes uv run --no-sync eval interception_v1. This new package is absent from the root examples dependency group, [tool.uv.sources], and uv.lock, so a fresh checkout cannot import interception_v1 and the smoke suite fails before evaluating it. Ensure the repository's normal uv setup installs this example, or otherwise keep it out of that automatic discovery path.

AGENTS.md reference: AGENTS.md:L11-L12

Useful? React with 👍 / 👎.

build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["interception_v1"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Example missing workspace registration

High Severity

The new interception-v1 package is not added to the root examples dependency group or tool.uv.sources, unlike every sibling under environments/. tests/v1/test_envs.py auto-discovers each *_v1 directory and runs uv run --no-sync eval, so CI cannot import this taskset after a normal sync.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 976b3f6. Configure here.

@macroscopeapp

macroscopeapp Bot commented Jul 29, 2026

Copy link
Copy Markdown

Approvability

Verdict: Needs human review

1 blocking correctness issue found. Multiple unresolved review comments identify substantive issues including missing workspace registration (causing CI failures) and a logic bug where the judge guard triggers on the user prompt rather than model responses. These need human review and resolution.

You can customize Macroscope's approvability policy. Learn more.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 52437392d4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +50 to +51
verdict = response.text.strip().upper()
if verdict not in ("BLOCK", "ALLOW"):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Accept recognizable judge verdicts before failing

When the judge returns a semantically valid but wrapped answer such as Verdict: BLOCK, a boxed verdict, or reasoning followed by ALLOW, the exact string comparison rejects it and turns the intercepted rollout into a TaskError. Use the existing vf.parse_judge_choice or vf.intercept_with_judge, which already handles common judge response formats while still failing when no verdict is recognizable.

AGENTS.md reference: AGENTS.md:L5-L5

Useful? React with 👍 / 👎.

@xeophon
xeophon force-pushed the agent/interception-example-env branch 2 times, most recently from 65bd52f to 3977a80 Compare July 29, 2026 17:03

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3977a806cd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

prompt: vf.Messages | None = None,
) -> vf.InterceptResult:
"""Use an ordinary judge for cases that need semantic classification."""
response = await vf.Judge().complete(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Configure the guard judge for the selected endpoint

When the smoke eval runs with only OPENAI_API_KEY, the checked tests/v1/test_envs.py branch configures the agent for https://api.openai.com/v1, but this bare Judge independently retains JudgeConfig's Prime endpoint, PRIME_API_KEY, and Prime-style model name. Because judge_guard runs after every response, including the first deterministic example, the judge request uses an empty or wrong credential and turns the rollout into a TaskError; supply a configurable judge endpoint/key/model compatible with the supported OpenAI-only eval context.

Useful? React with 👍 / 👎.

@xeophon
xeophon force-pushed the agent/interception-example-env branch from 3977a80 to a347a1e Compare July 29, 2026 17:54
@xeophon
xeophon force-pushed the agent/intercept-policies branch from 658f576 to cec154b Compare July 29, 2026 18:09
@xeophon
xeophon force-pushed the agent/interception-example-env branch from a347a1e to 845c1fd Compare July 29, 2026 18:09
@xeophon
xeophon force-pushed the agent/interception-example-env branch from 845c1fd to 5b22fdd Compare July 29, 2026 19:25

JUDGE = vf.Judge(
vf.JudgeConfig(
prompt="""Inspect the untrusted model exchange below.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Medium interception_v1/taskset.py:5

The JUDGE prompt matches JUDGE_BLOCK anywhere in the full exchange, so it fires on the user prompt itself ("Reply with exactly JUDGE_BLOCK and no other text.") before the model even responds. This causes judge_guard to rewrite the exchange for every judge example, and expected_guard_fired awards full reward regardless of whether the model's response actually contained the marker. Consider checking only the candidate/last message rather than the entire exchange, or avoid embedding the sentinel literal in the user-facing prompt.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @environments/interception_v1/interception_v1/taskset.py around line 5:

The `JUDGE` prompt matches `JUDGE_BLOCK` anywhere in the full exchange, so it fires on the user prompt itself (`"Reply with exactly JUDGE_BLOCK and no other text."`) before the model even responds. This causes `judge_guard` to rewrite the exchange for every judge example, and `expected_guard_fired` awards full reward regardless of whether the model's response actually contained the marker. Consider checking only the candidate/last message rather than the entire exchange, or avoid embedding the sentinel literal in the user-facing prompt.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5b22fdda54

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

"deterministic_guard",
),
(
"Reply with exactly JUDGE_BLOCK and no other text.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep the trigger out of the inspected prompt

For every rollout of this second task, exchange=trace.messages includes this user prompt, while the judge rubric instructs the judge to return BLOCK if any message contains JUDGE_BLOCK. The prompt therefore triggers judge_guard regardless of the assistant's response, and expected_guard_fired awards full reward even when the model never emits the blocked text. Inspect only trace.last_message or phrase the task without placing the literal trigger in the exchange.

Useful? React with 👍 / 👎.

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5b22fdd. Configure here.

),
(
"Reply with exactly JUDGE_BLOCK and no other text.",
"judge_guard",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Judge trigger matches task prompt

Medium Severity

The judge rubric returns BLOCK when any message contains JUDGE_BLOCK, but the task prompt itself includes that token. judge_guard therefore rewrites from the user prompt rather than the model reply, so the example does not demonstrate judge-backed response classification.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 5b22fdd. Configure here.

@xeophon

xeophon commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

Superseded by #2178, which replaces the guard layer and example environment with the reworked interception surface (typed rules, prebuilt guards).

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.

1 participant