Skip to content

Add interception transport and replay - #2164

Open
xeophon wants to merge 1 commit into
mainfrom
agent/intercept-stream-replay
Open

Add interception transport and replay#2164
xeophon wants to merge 1 commit into
mainfrom
agent/intercept-stream-replay

Conversation

@xeophon

@xeophon xeophon commented Jul 29, 2026

Copy link
Copy Markdown
Member

Overview

Adds the transport used by model request and response hooks. Each rollout keeps its own trace, while model calls remain independent and do not use a rollout-wide lock.

What this PR adds

  • Per-rollout request routing and branch-local trace views.
  • Full buffering only when a response hook needs to inspect a streamed response.
  • Exact byte replay when a buffered response is unchanged.
  • Minimal text-only streams for rewritten responses.
  • Explicit idempotency-key replay for retried streamed requests.
  • Safe cleanup when clients disconnect or a rollout ends.

Stack

  1. This PR adds the model interception transport and buffered delivery.
  2. Add typed model interception #2165 adds the public @vf.on_request and @vf.on_response hooks.
  3. Make interception termination final #2166 makes vf.Terminate final for rollout and environment scoring.
  4. Connect harness tool interception hooks #2229 connects Bash, Claude Code, and Codex tool results to request hooks.
  5. Add interception example environments #2178 adds small example environments.

Note

High Risk
Changes core model-call paths (streaming buffer, commit timing, HTTP errors on terminate) and holds full SSE bodies in memory when response interceptors are active—incorrect parsing or replay could fork traces or leak provider output.

Overview
Adds model response interception on the interception server: registered handlers can rewrite assistant output to plain text or terminate the rollout, with decisions stored on Trace.interceptions and later turns refused via session.terminated.

RolloutSession runs interceptors against a PendingTurn.scoped_trace view (prefix + prompt tail + candidate response). intercept_response enforces text-only rewrites; terminate records reward and stop reason. TaskError now surfaces as HTTP 400.

Non-streaming paths call interceptors after sampling, optionally rewrite_response on native raw JSON before returning. Streaming with response interceptors buffers the full upstream SSE, parses it, runs interceptors, then returns either the original chunks or synthetic SSE from new dialect stream_events. Idempotency-Key retries replay the exact buffered body via StreamReplay.

All three dialects gain rewrite_response / stream_events; stream parsers set response.raw, require explicit stream completion (message_stop / [DONE]), and Anthropic completion is keyed off message_stop instead of message_start.

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

Note

Add interception transport and SSE replay to rollout sessions

  • Adds an interceptor pipeline to RolloutSession that can rewrite or terminate candidate messages and model responses mid-rollout, recording each action as an InterceptRecord on the Trace.
  • Extends InterceptionServer to invoke interceptors on both streaming and non-streaming paths; when a rewrite is returned, the native response is replaced in-place via new rewrite_response / stream_events dialect methods before being delivered to the client.
  • Adds idempotent SSE replay: streaming responses are cached by Idempotency-Key + request identity in StreamReplay and re-served verbatim on retry, with mismatched keys rejected.
  • Terminated sessions return HTTP 400 (streaming) or 409 (released), and subsequent turns short-circuit in RolloutSession.refused().
  • Risk: streaming interception buffers the entire upstream SSE body server-side before deciding whether to relay or synthesize a replacement, which increases latency and memory usage for intercepted streams.

Macroscope summarized 0f95a16.

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: e07e9bd265

ℹ️ 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/interception/server.py Outdated
Comment thread verifiers/v1/interception/server.py Outdated
@macroscopeapp

macroscopeapp Bot commented Jul 29, 2026

Copy link
Copy Markdown

Approvability

Verdict: Needs human review

This PR introduces substantial new interception and replay capability across multiple files with ~400+ lines of new logic. Additionally, unresolved review comments identify potential timeout issues and a memory leak in the stream replay mechanism.

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

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: 0f1de5fc73

ℹ️ 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/interception/server.py Outdated
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: 2b9b14d2a9

ℹ️ 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/interception/server.py Outdated
Comment thread verifiers/v1/interception/server.py Outdated
Comment thread verifiers/v1/interception/server.py Outdated
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: db1cf07543

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

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

ℹ️ 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/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: 66fe362d73

ℹ️ 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/interception/server.py Outdated
Comment thread verifiers/v1/interception/server.py Outdated
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: 5b8f10ba4c

ℹ️ 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/interception/server.py Outdated
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: f0ef35cdcc

ℹ️ 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/interception/server.py Outdated
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: 1f070f3f32

ℹ️ 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/interception/server.py Outdated
@xeophon
xeophon force-pushed the agent/intercept-stream-replay branch from 1f070f3 to 4f66bdf Compare July 30, 2026 08:42
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: c6efe9569f

ℹ️ 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/interception/server.py Outdated
Comment thread verifiers/v1/interception/server.py Outdated
Comment thread verifiers/v1/interception/server.py Outdated
@xeophon
xeophon force-pushed the agent/intercept-stream-replay branch from 04588ac to 1630037 Compare July 30, 2026 12:41
@xeophon xeophon changed the title Make streamed model retries replay-safe Serialize model exchanges within a rollout Jul 30, 2026
@xeophon
xeophon force-pushed the agent/intercept-stream-replay branch from 0bdded4 to a1d4c18 Compare August 4, 2026 12:55
Comment thread verifiers/v1/session.py Outdated
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: 951858c06e

ℹ️ 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
Comment thread verifiers/v1/rollout.py Outdated
Comment thread verifiers/v1/interception/server.py Outdated
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: 387c952cca

ℹ️ 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/rollout.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: 308fc84a4c

ℹ️ 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/graph.py Outdated
@xeophon
xeophon force-pushed the agent/intercept-stream-replay branch from 308fc84 to 45455ce Compare August 4, 2026 19:56
Comment thread verifiers/v1/interception/server.py Outdated
Comment thread verifiers/v1/dialects/responses.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: 45455cec7e

ℹ️ 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
Comment thread verifiers/v1/interception/server.py
Comment thread verifiers/v1/interception/server.py
Comment thread verifiers/v1/interception/server.py
Comment thread verifiers/v1/session.py
@xeophon
xeophon force-pushed the agent/intercept-stream-replay branch from 45455ce to ded97e2 Compare August 5, 2026 08:10

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

ℹ️ 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
@xeophon
xeophon force-pushed the agent/intercept-stream-replay branch from ded97e2 to cb42110 Compare August 5, 2026 09:08
Comment thread verifiers/v1/session.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: cb4211033a

ℹ️ 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/interception/server.py
Comment thread verifiers/v1/session.py
@xeophon
xeophon force-pushed the agent/intercept-stream-replay branch from cb42110 to 3d927c7 Compare August 5, 2026 12:19

@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: 3d927c76f9

ℹ️ 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
Comment thread verifiers/v1/dialects/responses.py
Comment thread verifiers/v1/session.py
@xeophon
xeophon force-pushed the agent/intercept-stream-replay branch from 3d927c7 to 9e0aa3e Compare August 5, 2026 13:12
Comment thread verifiers/v1/interception/server.py
@xeophon
xeophon force-pushed the agent/intercept-stream-replay branch from 9e0aa3e to 0f95a16 Compare August 5, 2026 13:17
Comment thread verifiers/v1/dialects/anthropic.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: 0f95a16a63

ℹ️ 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 +690 to +694
if intercept_response:
chunks: list[bytes] = []
parser = dialect.stream_parser()
try:
async for chunk in reply.chunks:

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 Send keepalives while buffering intercepted streams

When a streamed request has response interception enabled and the upstream generation runs longer than the harness client's read or idle timeout, this branch consumes the entire provider stream before preparing any downstream response or keepalive. The client can time out and retry while the owner keeps buffering and later commits; without a stream replay key, that retry samples again and leaves a committed turn the harness never observed. The live relay below has a keepalive loop, but this buffered interception path needs the same liveness while it waits to run the hook.

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.

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 0f95a16. Configure here.

if stream_owner is not None:
stream_owner[1].set_result(
StreamReplay(content_type=content_type, body=wire)
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Stream replays grow without bound

Medium Severity

Successful idempotent stream replays stay in stream_replays until release(), so each buffered SSE body is retained for the rest of the rollout. Failed attempts are popped, but successes are not. Over many streaming turns this keeps every full response in memory, unlike the bounded last_response cache.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 0f95a16. Configure here.

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