Skip to content

Add interception example environments - #2178

Merged
xeophon merged 5 commits into
mainfrom
agent/intercept-rules
Aug 13, 2026
Merged

Add interception example environments#2178
xeophon merged 5 commits into
mainfrom
agent/intercept-rules

Conversation

@xeophon

@xeophon xeophon commented Jul 30, 2026

Copy link
Copy Markdown
Member

Overview

Adds four small environments that show the typed interception API at the point where each hook runs.

Examples

  • interception shows a deterministic response rewrite, a judge-backed response rewrite, a response stop, and an observer hook that records a metric while returning None.
  • grayscale-interception rewrites embedded base64 user images to grayscale before the harness or model stores them. It preserves transparency and passes unsupported or malformed image data through unchanged.
  • bash-interception shows two pre-execution outcomes: stop a proposed Bash command, or return a synthetic ToolMessage so the command is skipped and the model continues.
  • web-search-interception inspects provider-native Codex web-search citation URLs and stops when a returned source contains the configured word.

The examples use vf.Request, vf.Response, and vf.Trace directly, with short comments beside the relevant code.

Stack

These PRs are stacked in merge order. Each PR targets the one above it.

PR What it adds
#2164 Typed transport, native request/response rewriting, buffered inspection, and retry replay
#2165 Public @vf.intercept for vf.Request and vf.Response
#2166 Public @vf.stop for vf.Request, vf.Response, and vf.Trace
#2229 Opt-in harness tool hooks, enabled for Bash
#2178 Example environments for response, image, Bash, and native web-search interception

Note

Low Risk
Documentation-style example packages and dependency/lockfile registration only; no changes to core verifiers runtime behavior.

Overview
Adds four installable v1 example environments that demonstrate typed @vf.intercept and @vf.stop at different rollout boundaries, and wires them into the repo’s default examples uv group and lockfile.

interception covers response-side hooks: deterministic and judge-backed rewrites, a stop when the assistant says STOP, and an intercept that only records a metric. grayscale-interception rewrites base64 user images to grayscale on incoming vf.Request (with alpha preserved and bad data left alone). bash-interception shows pre-execution control—stop a proposed bash call vs inject a synthetic ToolMessage so the command never runs—with rewards checked via sentinel files. web-search-interception defaults to Codex and stops when native web-search citation URLs contain a blocked domain.

Each package is a small editable environments/* project with README and taskset; root pyproject.toml lists them in examples and [tool.uv.sources].

Reviewed by Cursor Bugbot for commit 96f1468. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add interception example environments for request, response, image, bash, and web-search hooks

  • Introduces four new example environments (interception, grayscale-interception, bash-interception, web-search-interception) demonstrating @vf.intercept and @vf.stop decorators across different rollout boundaries.
  • Adds core interception infrastructure: RolloutSession gains typed request/response interceptors and stop hooks; Rollout.open and Rollout.step run interceptors before model/harness calls and can rewrite or halt execution early.
  • All three LLM dialects (Anthropic, Chat, Responses) gain rewrite_request, rewrite_response, and stream_events methods so rewritten content is reflected in native wire formats and SSE streams.
  • BashHarness and its program runner gain opt-in tool interception via SUPPORTS_TOOL_INTERCEPTION and --tool-interception-url, enabling before/after hooks on bash tool calls.
  • A new InterceptRecord model is added to Trace so request and response rewrites are captured and queryable after rollout.
  • Risk: Rollout.open now returns False when a stop fires during interception (previously only returned False for harness failures), which changes existing semantics for callers that infer session health from the return value.

Macroscope summarized 96f1468.

Comment thread verifiers/v1/intercepts/rules.py Outdated
Comment thread verifiers/v1/dialects/anthropic.py Outdated

@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: d41b94349e

ℹ️ 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 thread verifiers/v1/dialects/chat.py Outdated
Comment thread verifiers/v1/intercepts/rules.py Outdated
@macroscopeapp

macroscopeapp Bot commented Jul 30, 2026

Copy link
Copy Markdown

Approvability

Verdict: Needs human review

2 blocking correctness issues found. This PR introduces a complete request/response interception framework with significant new core library code across dialects, session handling, rollout, and harness components. As a substantial new feature introducing new capabilities and workflows, it warrants human review. Additionally, unresolved High and Medium severity findings regarding edge cases in the example interceptors require attention.

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

Comment thread verifiers/v1/session.py
Comment thread verifiers/v1/interception/server.py Outdated

@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: 7aae47f960

ℹ️ 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 thread verifiers/v1/dialects/responses.py Outdated
Comment thread verifiers/v1/intercepts/rules.py Outdated
@xeophon
xeophon force-pushed the agent/intercept-rules branch from 7aae47f to b1f77a4 Compare July 30, 2026 09:39
@xeophon
xeophon force-pushed the agent/intercept-terminal branch from 3bd972d to 257ddbc Compare July 30, 2026 09:39
Comment thread verifiers/v1/dialects/chat.py Outdated
@xeophon
xeophon force-pushed the agent/intercept-terminal branch from 257ddbc to f9f354e Compare July 30, 2026 09:47
@xeophon
xeophon force-pushed the agent/intercept-rules branch from b1f77a4 to 3113425 Compare July 30, 2026 09:47
Comment thread verifiers/v1/dialects/anthropic.py Outdated

@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: 311342505e

ℹ️ 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 thread environments/interception_v1/pyproject.toml Outdated
@xeophon
xeophon force-pushed the agent/intercept-rules branch from 3113425 to 4b92fe4 Compare July 30, 2026 09:56
@xeophon
xeophon force-pushed the agent/intercept-terminal branch 2 times, most recently from e0271d7 to ee897f4 Compare July 30, 2026 10:01
@xeophon
xeophon force-pushed the agent/intercept-rules branch 3 times, most recently from 8dad0d9 to b12342b Compare July 30, 2026 10:25
@xeophon
xeophon force-pushed the agent/intercept-terminal branch from fd9617b to 63c88b9 Compare July 30, 2026 10:25

@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: b12342b8be

ℹ️ 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 thread verifiers/v1/session.py Outdated
@xeophon
xeophon force-pushed the agent/intercept-rules branch from b12342b to ecb3b4b Compare July 30, 2026 10:36
@xeophon
xeophon force-pushed the agent/intercept-terminal branch from 63c88b9 to b9cb943 Compare July 30, 2026 10:36
Comment thread environments/bash_interception_v1/bash_interception_v1/taskset.py Outdated
Comment thread environments/interception/interception/taskset.py
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

2 similar comments
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

Comment thread environments/bash_interception_v1/bash_interception_v1/taskset.py Outdated
Comment thread environments/bash_interception_v1/bash_interception_v1/taskset.py Outdated
Comment thread environments/grayscale_interception/grayscale_interception/taskset.py Outdated
Comment thread environments/web_search_interception/web_search_interception/taskset.py Outdated
Comment thread verifiers/v1/interception/tool_hook.py Outdated

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

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 41741ae. Configure here.

Comment thread environments/web_search_interception/web_search_interception/taskset.py Outdated

@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: 41741aec7a

ℹ️ 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 thread environments/interception/interception/taskset.py Outdated
Comment thread environments/interception/interception/taskset.py Outdated
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 11, 2026
Comment thread environments/grayscale_interception/grayscale_interception/taskset.py Outdated
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 11, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Aug 11, 2026

@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: 7dbd7b9b8b

ℹ️ 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 thread environments/grayscale_interception/grayscale_interception/taskset.py Outdated

@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: 04e3c3bf86

ℹ️ 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 thread environments/interception/interception/taskset.py
Comment thread environments/bash_interception/bash_interception/taskset.py
Comment thread environments/bash_interception/bash_interception/taskset.py

@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: d0bf72b38c

ℹ️ 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 thread environments/bash_interception/bash_interception/taskset.py
if image.has_transparency_data
else None
)
grayscale_image = ImageOps.grayscale(image)

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 grayscale_interception/taskset.py:40

When a multi-frame image (e.g., animated GIF, APNG, or animated WebP) is sent as a data URL, ImageOps.grayscale(image) converts only the first frame and image_data_url serializes that single static frame. All subsequent frames and animation timing are silently discarded, so the model receives a static first frame instead of a grayscale version of the supplied animated image. Consider checking getattr(image, "is_animated", False) and either preserving frame iteration/timing metadata through the grayscale conversion or documenting that only static images are supported.

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

When a multi-frame image (e.g., animated GIF, APNG, or animated WebP) is sent as a data URL, `ImageOps.grayscale(image)` converts only the first frame and `image_data_url` serializes that single static frame. All subsequent frames and animation timing are silently discarded, so the model receives a static first frame instead of a grayscale version of the supplied animated image. Consider checking `getattr(image, "is_animated", False)` and either preserving frame iteration/timing metadata through the grayscale conversion or documenting that only static images are supported.

Comment on lines +12 to +14
def grayscale(self, request: vf.Request) -> vf.Request | None:
# The last request message is the new user input, before the harness stores it.
message = request.messages[-1]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟠 High grayscale_interception/taskset.py:12

grayscale accesses request.messages[-1] without first checking that messages is non-empty, so a request with an empty messages list raises IndexError instead of being returned unchanged. Add an if not request.messages: guard before the indexing, as is done in the analogous Bash interceptor.

Suggested change
def grayscale(self, request: vf.Request) -> vf.Request | None:
# The last request message is the new user input, before the harness stores it.
message = request.messages[-1]
def grayscale(self, request: vf.Request) -> vf.Request | None:
if not request.messages:
return None
# The last request message is the new user input, before the harness stores it.
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @environments/grayscale_interception/grayscale_interception/taskset.py around lines 12-14:

`grayscale` accesses `request.messages[-1]` without first checking that `messages` is non-empty, so a request with an empty `messages` list raises `IndexError` instead of being returned unchanged. Add an `if not request.messages:` guard before the indexing, as is done in the analogous Bash interceptor.

mikasenghaas
mikasenghaas previously approved these changes Aug 13, 2026

@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: 96f1468746

ℹ️ 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".

@macroscopeapp

macroscopeapp Bot commented Aug 13, 2026

Copy link
Copy Markdown

Macroscope skipped reviewing this pull request. Per-PR cost limit exceeded (workspace setting).

Reviews on this PR have cost $95.21 so far. This review would add an estimated $4.84, bringing the total to $100.04 — above your per-PR limit of $100.00.

Tip

To get this pull request reviewed, you can:

  1. Comment @macroscope-app on this PR to request a manual review (monthly spend limits still apply).
  2. Exclude large or generated files from review by adding a pattern to your .macroscope/ignore.md — note that creating this file replaces Macroscope's built-in default ignores rather than extending them.
  3. Raise your cost limit in your workspace billing settings.

Turn off this reminder going forward

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.

2 participants