Skip to content

Fix MCP session lifecycle and replay safety - #2134

Open
xeophon wants to merge 39 commits into
agent/fix-agentic-judge-restricted-runtimefrom
agent/fix-mcp-session-lifecycle
Open

Fix MCP session lifecycle and replay safety#2134
xeophon wants to merge 39 commits into
agent/fix-agentic-judge-restricted-runtimefrom
agent/fix-mcp-session-lifecycle

Conversation

@xeophon

@xeophon xeophon commented Jul 26, 2026

Copy link
Copy Markdown
Member

Overview

Centralize null and bash harness MCP handling into one lifecycle-aware client and make transport failures explicit, replay-safe, and diagnosable.

Details

  • own the MCP transport in a dedicated task so SDK cancellation scopes stay with their owner
  • preserve outer cancellation while bounding cancellation-time session teardown
  • distinguish replay-safe connection failures from calls whose delivery is unknown
  • prevent automatic replay when a non-idempotent tool call may have reached the server
  • emit structured diagnostics for the parent harness and retry policy
  • remove the duplicated null-harness MCP client by sharing the null and bash program

Note

Medium Risk
MCP delivery-unknown handling and restricted-runtime reuse change failure and isolation behavior on eval retries and multi-agent Docker; NeMo Gym adds a large optional dependency tree (Ray, wandb) for Python 3.12+.

Overview
Adds NeMo Gym v1 support: a NeMoGymTaskset that seeds/verifies against Gym resource servers while verifiers harnesses run the agent loop, optional NeMoGymEnv to start packaged servers, a verifiers[nemo-gym] extra, docs, and the nemo-gym-weather-v1 example.

MCP harness programs are merged into one shared minimal/program.py (bash gated by --bash). Transport runs in a dedicated task; failures emit VF_MCP_ERROR= JSON that the parent maps to MCPTransportError or MCPDeliveryUnknownError. Retries skip replay when delivery is unknown unless RetryConfig explicitly allows MCPDeliveryUnknownError.

Restricted runtimes can be reused across rollouts: runtime.rollout() replaces prepare_setup, kills stray processes, resets caches, and toggles network policy via _apply_network_policy. Rollouts enter that context; agentic-judge shared Docker uses a blocklist in e2e.

Also exports mcp_session on the launch path, tightens builtin_harness_ids to packages with a harness module, and propagates network_allow/network_block into judge tasks.

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

Note

Fix MCP session lifecycle and replay safety in harness program

  • Replaces separate bash and null harness programs with a shared minimal program that manages MCP HTTP transports with retry logic, emitting structured VF_MCP_ERROR= markers for the parent harness to parse.
  • Adds two new error types — MCPTransportError and MCPDeliveryUnknownError — so callers can distinguish clean transport failures from cases where a non-replayable mutation may have already been accepted by the server.
  • Updates automatic retry logic in retries.py to skip replays when MCPDeliveryUnknownError is present, unless explicitly opted into via retry config.
  • Adds execution_prepared tracking and a rollout() context manager to the runtime base class, enabling Docker and Prime runtimes to toggle between unrestricted trusted-setup policy and restricted execution network policy per rollout.
  • Adds a NeMo Gym taskset and environment that manage the lifecycle of a NeMo Gym MCP resources server per worker, with MCP session seeding, tool discovery, and reward evaluation via the server.
  • Risk: automatic retries for MCP-based tools now require explicit opt-in when any delivery uncertainty exists, which may change retry behavior for existing MCP-backed tasksets.

Macroscope summarized 53b52ed.

Comment thread verifiers/v1/retries.py Outdated
Comment thread verifiers/v1/harnesses/mcp_client.py Outdated
@macroscopeapp

macroscopeapp Bot commented Jul 26, 2026

Copy link
Copy Markdown

Approvability

Verdict: Unable to determine

Macroscope's correctness review was unable to post its findings for this PR. Approvability cannot proceed without a successful correctness review.

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: 67e0acc36c

ℹ️ 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/retries.py Outdated
@xeophon
xeophon force-pushed the agent/fix-mcp-session-lifecycle branch from fffc408 to 18109b8 Compare July 27, 2026 13:28
@xeophon
xeophon requested a review from mikasenghaas July 27, 2026 13:30
Comment thread verifiers/v1/harnesses/mcp_client.py Outdated

@mikasenghaas mikasenghaas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

do we have some data/ experiments to backup the robustness improvs around mcp?

Comment thread verifiers/v1/harnesses/bash/program.py Outdated
Comment thread verifiers/v1/harnesses/minimal/program.py
Comment thread verifiers/v1/harnesses/mcp_client.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: 9789a1d4b4

ℹ️ 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/harness.py
Comment thread verifiers/v1/harnesses/minimal/program.py
Comment thread verifiers/v1/harness.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: fc39d94a2c

ℹ️ 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/harnesses/minimal/program.py
Comment thread verifiers/v1/harnesses/minimal/program.py
@xeophon
xeophon force-pushed the agent/fix-mcp-session-lifecycle branch from fc39d94 to d9c602c Compare July 29, 2026 09:18

@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 2 potential issues.

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 d9c602c. Configure here.

Comment thread verifiers/v1/harness.py Outdated
Comment thread verifiers/v1/harnesses/minimal/program.py
@xeophon
xeophon requested a review from mikasenghaas July 29, 2026 14:44

@mikasenghaas mikasenghaas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

not super convinced

Comment thread verifiers/v1/errors.py
Comment on lines +59 to +64
class MCPTransportError(HarnessError):
"""A harness-owned MCP session lost its transport; the message is structured JSON."""


class MCPDeliveryUnknownError(MCPTransportError):
"""An MCP transport failed after a non-replayable operation may have been accepted."""

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lets not try to reinvent finegrained error cls and lets just have the error that is raised in the harness bubble up. we just wrap with harness error to have a rough idea of the "location" of the error

Comment thread verifiers/v1/harness.py
Comment on lines +158 to +172
if (
isinstance(payload, dict)
and payload.get("delivery")
in {"operation_not_started", "response_unknown"}
and isinstance(payload.get("replay_safe"), bool)
):
error_cls = (
MCPDeliveryUnknownError
if payload["delivery"] == "response_unknown"
and not payload["replay_safe"]
else MCPTransportError
)
mcp_error = error_cls(diagnostic)
if isinstance(mcp_error, MCPDeliveryUnknownError):
raise mcp_error

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

then we can also remove those shenannigans

m.name
for m in pkgutil.iter_modules(harnesses.__path__)
if m.ispkg
and importlib.util.find_spec(f"{harnesses.__name__}.{m.name}.harness")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

bit ugly to break with our one folder = one harness convention but ig this is the lesser evil than duplicated code?

its trace is retryable (all captures count, not just the most recent)."""
its trace is retryable (all captures count, not just the most recent).
A possibly-delivered MCP mutation vetoes replay unless explicitly included."""
replay_unknown = (

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

hmmm im not sure im loving this. in between who and who is this error raised? if its between harness + tool server we should fix in the harness and not patch here. retrying is really last resort in my mind

@xeophon
xeophon force-pushed the agent/fix-mcp-session-lifecycle branch from b20f3fb to 53b52ed Compare July 31, 2026 21:17
@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.

@xeophon
xeophon changed the base branch from main to agent/fix-agentic-judge-restricted-runtime July 31, 2026 21:18
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