evals: add the stagehand_code code-mode exposure - #2591
Merged
Conversation
|
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 1 file
Architecture diagram
sequenceDiagram
participant HAR as External Harness
participant PREP as prepareLLMExposure()
participant INIT as initStagehand()
participant SDK as Stagehand v4 SDK
participant BROWSER as Local/Browserbase Browser
participant AGENT as Agent (LLM)
Note over HAR,AGENT: NEW: v4 Code-Mode Exposure Flow
HAR->>PREP: prepareLLMExposure(plan, env, logger, profile?)
alt profile not provided
PREP->>PREP: Resolve profile based on env (LOCAL or BROWSERBASE)
else invalid profile
PREP->>PREP: Throw EvalsError
end
PREP->>INIT: initStagehand(modelName, environment)
INIT-->>PREP: Return {stagehand, page}
PREP->>PREP: Extract stagehand from v4
Note over PREP: Build LLMExposure with code_handles kind
PREP-->>HAR: Return LLMExposure
HAR->>AGENT: Pass exposure to agent
loop Agent uses run tool
AGENT->>AGENT: Execute code against SDK (page.goto, stagehand.act, etc.)
SDK->>BROWSER: Browser actions
BROWSER-->>SDK: Results
SDK-->>AGENT: Return values
end
opt Final state capture
HAR->>HAR: captureFinalState()
HAR->>HAR: Take screenshot (best-effort)
HAR->>HAR: Get current URL (best-effort)
end
opt Cleanup
HAR->>HAR: cleanup()
HAR->>HAR: stagehand.close() (RPC client)
HAR->>HAR: browser.close() (browser process)
end
Note over PREP: Surface model pinned to openai/gpt-4.1-mini
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
shriyatheunicorn
force-pushed
the
stg-2671-v4-code-exposure
branch
from
August 5, 2026 07:14
6191a09 to
3c4764c
Compare
shriyatheunicorn
force-pushed
the
stg-2671-v4-code-exposure
branch
from
August 5, 2026 08:11
3c4764c to
3633309
Compare
shriyatheunicorn
force-pushed
the
stg-2671-v4-code-exposure
branch
from
August 5, 2026 08:28
3633309 to
75c3d64
Compare
shriyatheunicorn
force-pushed
the
stg-2671-v4-code-exposure
branch
2 times, most recently
from
August 5, 2026 19:06
64bf897 to
f728be5
Compare
shriyatheunicorn
force-pushed
the
stg-2671-v4-code-exposure
branch
from
August 5, 2026 22:40
f728be5 to
7a41c66
Compare
shriyatheunicorn
force-pushed
the
stg-2671-v4-code-exposure
branch
from
August 6, 2026 02:16
7a41c66 to
d52e9cf
Compare
shriyatheunicorn
force-pushed
the
stg-2671-v4-code-exposure
branch
from
August 6, 2026 02:46
d52e9cf to
d750c9c
Compare
miguelg719
force-pushed
the
stg-2671-v4-code-exposure
branch
from
August 6, 2026 22:18
d750c9c to
2c5b548
Compare
Base automatically changed from
stg-2671-llm-exposure-contract
to
evals-v4-root
August 6, 2026 23:12
shriyatheunicorn
force-pushed
the
stg-2671-v4-code-exposure
branch
from
August 6, 2026 23:12
2c5b548 to
49c3c34
Compare
miguelg719
force-pushed
the
stg-2671-v4-code-exposure
branch
from
August 6, 2026 23:17
49c3c34 to
a152da0
Compare
shriyatheunicorn
force-pushed
the
stg-2671-v4-code-exposure
branch
from
August 8, 2026 04:49
a152da0 to
e579140
Compare
This was referenced Aug 9, 2026
miguelg719
approved these changes
Aug 9, 2026
miguelg719
added a commit
that referenced
this pull request
Aug 9, 2026
## Summary Corrects the base-target mistake from #2590 by landing its merged agent-mount contract on v4-spike. This branch is exactly current v4-spike plus the #2590 squash commit: - AgentMount is the lifecycle-free agent delivery binding - ToolStartResult owns the single runtime lifecycle and captureEvidence - contract tests cover independent surface/mount modalities After merge, #2591 and the remaining stack will be rebased directly onto v4-spike. ## Verification - pnpm --filter @browserbasehq/stagehand-evals typecheck - contract and downstream stack suites validated during restack <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Promotes the agent-mount tool-surface contract to `v4-spike`, adding type-safe agent delivery bindings and best-effort evidence capture, independent of `CoreTool.surface`. Types and tests only; no runtime changes. - **New Features** - `ToolStartResult` adds optional `agentMount` and `captureEvidence(): Promise<ProbeEvidence>`. - New `AgentMount` union (`via: handles | mcp | cli`) with `promptInstructions`; plus `AgentRunToolSpec`. - Constants: `AGENT_RUN_TOOL_SERVER`, `AGENT_RUN_TOOL_NAME`, `AGENT_RUN_TOOL_RESERVED_HANDLES`. Enums: `ToolSurface` adds `stagehand_code`; `CoreTool.family` adds `stagehand`. - Tests (`packages/evals/tests/core/tool-contract.test.ts`) validate surface/delivery independence, handle mounts, and evidence capture. <sup>Written for commit fd74210. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/browserbase/stagehand/pull/2635?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> Co-authored-by: shriyatheunicorn <shriavj@gmail.com>
miguelg719
added a commit
that referenced
this pull request
Aug 9, 2026
The surface now owns its agent mount: prompt instructions (carried over verbatim from the per-surface block inside the claude_code tool adapter), a code_handles declaration, and captureEvidence() returning the terminal screenshot, URL, and aria tree. Behavior is unchanged until the adapter consumes mounts generically in #2596. Part of the nondeterministic-evals stack (#2591 → #2611). <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Make `playwright_code` agent-mountable so the v4 harness can consume it generically, with handle exposure, prompt wiring, runTool config, and best-effort evidence capture. No behavior change; supports STG-2671’s non-deterministic suite. - **New Features** - Added `agentMount` with handle access (`page`, `context`, `browser`), prompt instructions (incl. first-action guidance), and `runTool` config (async snippet scope: `page`, `context`, `browser`, `startUrl`, `task`, `console`; return JSON-serializable values; deny message references `AGENT_RUN_TOOL_NAME`). - Added `captureEvidence` typed as `ProbeEvidence` (screenshot, URL, `ariaTree` via `page.represent({ includeIframes: true })` with best-effort per modality); track active page on `"page"` events; ensured initial page exists; unified cleanup. <sup>Written for commit 9cf16fb. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/browserbase/stagehand/pull/2592?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
miguelg719
added a commit
that referenced
this pull request
Aug 9, 2026
Same shape as #2592 for the CDP surface: prompt instructions carried over verbatim, code_handles declaration, captureEvidence() for the terminal screenshot, URL, and aria tree. Behavior is unchanged until the adapter consumes mounts generically in #2596. Part of the nondeterministic-evals stack (#2591 → #2611). <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Expose `cdp_code` as an `LLMExposure` with an agent-mountable `cdp` runtime, clearer prompt instructions, and richer final-state evidence. Linked to Linear STG-2671 (part 5/6). Requires the `LLMExposure` contract (1/6). - **New Features** - Agent mount: `handles.cdp`; prompt includes `AGENT_RUN_TOOL_NAME`, a first navigate/load recipe, run-tool description and code param, and a deny message; `captureEvidence` collects screenshot, URL, and `ariaTree`. - Runtime: `send`/`browser` plus `on`/`off`/`once`/`waitForEvent`/`wait` with session scoping, timeouts, safe teardown, and unhandled-rejection guards; exposes `targetId`/`sessionId`; `createAgentRuntime(logger)` initializes it. - Representation: adds `representation` capability; `page.represent()` returns the accessibility tree with metadata; evidence includes `ariaTree`. - Page management: `syncPages` keeps session pages current before `listPages`/`activePage`; bootstrap only creates a target if none exist. <sup>Written for commit e641edf. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/browserbase/stagehand/pull/2595?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
miguelg719
added a commit
that referenced
this pull request
Aug 9, 2026
…er (#2596) Replaces the per-surface logic inside the adapter with one generic mount consumer: any surface declaring an agent mount gets its handles mounted as the single local-MCP run tool, with the surface's own prompt instructions. Net deletion — the bespoke playwright_code/cdp_code blocks move behind the contract, and adding a surface no longer means editing the adapter. Part of the nondeterministic-evals stack (#2591 → #2611). Requires the three mount declarations below it. Verified across the stack: tsc and oxlint per part, evals vitest, live core runs on Browserbase for --tool stagehand_code, playwright_code, and cdp_code (3/3 each, prompt exit), one long-horizon row (webvoyager x claude_code x stagehand_code, 3/3), and the paired webvoyager acceptance run (stagehand_code 2/3 vs playwright_code 3/3, both cells traced to Braintrust). <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Consume LLM exposure mounts generically in the `claude_code` adapter so all code surfaces expose their handles as a single MCP run tool. This aligns with STG-2671 and adds optional evidence capture while removing surface-specific logic. - **New Features** - Generic agent mount consumption across `playwright_code`, `cdp_code`, and `stagehand_code`; prompt text, run-tool copy/deny messages, and `task`/`console` bindings come from the mount. - Optional `captureEvidence()` for grading (timeout `EVAL_CAPTURE_EVIDENCE_TIMEOUT_MS`); standardized identifiers via `AGENT_RUN_TOOL_NAME` and `AGENT_RUN_TOOL_SERVER`. - **Refactors** - One mount consumer replaces bespoke surface code; snippets run with handle names plus `startUrl`/`task`/`console`. Re-exports `waitForCdpEvent`. - Shared tool/target lifecycle via `startAgentToolRuntime` with idempotent cleanup (timeout `EVAL_AGENT_MOUNT_CLEANUP_TIMEOUT_MS`); startup profiles: `browse_cli`/`stagehand_code` own the browser, `playwright_code`/`cdp_code` expect runner-provided CDP. Improved `browse_cli` build-artifacts error. <sup>Written for commit 5a1a4ea. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/browserbase/stagehand/pull/2596?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
miguelg719
added a commit
that referenced
this pull request
Aug 9, 2026
## Summary The remaining merge blockers for the #2591→#2611 stack, implemented per the review conclusions (verifier fallback accepted on empirical evidence; GAIA removal decided; Odysseys rubric item dropped as irrelevant). - **Gate insurance for the verifier fallback**: verifier-failed rows (`verifierError` set, `_success` self-reported) now count as **ungraded runs** on their arm. The per-arm verifiability line reports them, and when `EVAL_MAX_UNVERIFIABLE_CRITERIA` is configured, *any* ungraded run fails the batch. This changes no grading behavior — it converts "the fallback hasn't fired in hundreds of runs" into "if it ever fires, the batch fails loudly instead of publishing self-graded rows." - **GAIA fully removed** (dataset, suite builder, `index.eval.ts` fan-out, category overrides, legacy-only sets, help text, README). `b:gaia` → "Unknown benchmark", instead of a half-present suite pointing at a broken `--legacy` path. - **Planner**: a stagehand-harness selection that reduces to *nothing runnable* (suite name, agent category, dataset shorthand) errors with harness guidance instead of planning zero cases; broad targets still omit suites and plan the rest. - **Codex step budget**: tool steps (command executions + MCP tool calls) capped via stream abort — `EVAL_CODEX_MAX_STEPS`, falling back to the pre-migration `AGENT_EVAL_MAX_STEPS`, default 50. Runs get a citable, reproducible action budget. - **Per-dataset prompt constraints restored** from the retired suite modules: OnlineMind2Web's stay-on-site rule (validity: tasks were passable by googling the answer) and the navigate guidance for WebTailBench/Odysseys. - **Tag hygiene**: `dom/hybrid/cua` stripped from external-harness testcases so Braintrust tag filters don't pool them with historical Stagehand agent rows. - **stagehand_code screenshot fix** (ported from the facade worktree): v4 SDK returns `Uint8Array`; `Buffer.isBuffer` consumers silently dropped screenshots. Now normalized to `Buffer`. ## Deliberately not here - **Pre-navigation to `startUrl`**: pending an explicit protocol decision (self-navigation as the documented norm vs. pre-goto for cross-era comparability). - **The facade's `>=` relaxation of the codex observation guard**: kept strict `===` — the relaxation reintroduces positional misattribution; the underlying trailing-capture undercount needs an attempted-run count in the recorder (follow-up with the facade work). - MCP tool surfaces and the Playwright facade: follow-up stack. ## Verification typecheck clean · 416/416 unit tests (3 GAIA-era tests updated to the new behavior, 1 new gate test) · oxfmt clean <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Hardens external-harness evals for merge: enforces strict verifier gating, removes GAIA and the legacy runner/flag, adds a Codex step budget, restores dataset prompt guidance, fixes screenshot handling, and bounds setup-failure cleanup timeouts. Also cleans up docs/payloads, fixes a Codex abort-listener leak in long batches, tightens a dry-run test assertion, and removes the `--provider` flag (provider now derived from the model id). - **New Features** - Verifier gate: verifier-failed rows now count as ungraded; any ungraded run fails a gated batch. Per-arm report shows ungraded counts. Respects EVAL_MAX_UNVERIFIABLE_CRITERIA. - Codex step budget: cap tool steps via EVAL_CODEX_MAX_STEPS (fallback AGENT_EVAL_MAX_STEPS, default 50) with stream abort and clear stop reason. - Restored dataset guidance in prompts: OnlineMind2Web stay-on-site rule; navigation hints for WebTailBench and Odysseys. - Planner: selecting `stagehand` harness that leaves nothing runnable now errors with guidance instead of planning zero cases. - **Refactors** - GAIA fully removed; `b:gaia` now reports “Unknown benchmark.” `b:osworld` also reports “Unknown benchmark.” - Removed legacy runner and `--legacy` flag; deleted legacy files and commands. Dry-run payload drops skippedTasks; preview/help text, `ARCHITECTURE.mmd`, and README updated. - Removed `--provider` and provider-based model filtering; provider metadata is inferred from `provider/model`. Dropped EVAL_PROVIDER env, config/help surfaces, and related tests. - Tag hygiene: strip `dom`, `hybrid`, `cua` from external-harness testcases to keep Braintrust filters separated from legacy Stagehand runs. - `stagehand_code` screenshot bytes normalized to `Buffer` to fix dropped screenshots with the v4 SDK. - Codex runner: detach the abort forwarder after each run to avoid accumulating listeners in long batches. - External-harness adapters: apply the normal teardown timeout (EVAL_AGENT_MOUNT_CLEANUP_TIMEOUT_MS) to setup-failure cleanup to prevent wedging rows. - Docs: dry-run diagram lists the actual payload fields (target, normalizedTarget, tasks, envOverrides, runOptions, matrix, error?). - Tests: broad dry-run now asserts the unique planned task set to avoid model-multiplicity noise. <sup>Written for commit 66bc69d. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/browserbase/stagehand/pull/2649?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. --> --- **Update (second commit)**: the legacy runner is removed outright. `--legacy` could no longer run anything on this branch (a/e/o need the v4 harness context it never builds; the agent modules and suite targets it resolves are gone), so the escape hatch was routing users to a guaranteed failure. Deleted: `cli-legacy.ts`, `index.eval.ts`, `args.ts`, `tui/commands/legacy.ts`, the `evals:old` script, the `--legacy` flag, `LEGACY_ONLY_BENCHMARKS` (`b:osworld` now reports "Unknown benchmark"), and the legacy-skip plumbing in the run command, dry-run payload, and preview. Net −1,885 lines. Gates re-run green (typecheck, 416/416, oxfmt).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The agent-facing half of the stagehand_code code-mode surface:
prepareLLMExposure initializes a v4 Stagehand client via initStagehand
and declares a code_handles agent mount — stagehand/page/z in the
snippet scope, surface-owned prompt instructions and run-tool copy,
final-state evidence capture (screenshot + URL + aria tree), and cleanup
that closes the browser as well as the client (stagehand.close() alone
leaves the browser running). Nothing consumes the mount here; the
claude_code adapter does in #2596 and codex in #2609.
Bottom of the nondeterministic-evals stack (#2591 → #2611, with the
merge-readiness fixes in #2649 and the MCP tool surfaces in #2650
stacked on top).
evals-v4-root, which has since merged (via #2570 → #2494) intov4-spike. Rebase onto currentv4-spikeand retarget. One knownreconciliation: v4-spike removed the
EVAL_VERIFIER_MODELoverridefrom
verifierAdapter(2af557b) as redundant with V3Evaluator's ownconstructor options; this stack's later PRs still carry it — drop it
during the rebase rather than reintroducing it.
Summary by cubic
Adds the
stagehand_codecode-mode tool and registers it in the core tool registry, wiring a v4@browserbasehq/stagehandclient with scoped handles, run-tool execution, artifact capture, and full teardown. Enables the v4 code-mode surface for STG-2671 with a fixed SDK model and local/Browserbase startup profiles.StagehandCodeTool(id: stagehand_code) with session, navigation, evaluation, screenshot, viewport, wait, click, hover, scroll, type, press, tabs, and representation.selector,coords,focused.stagehand,page, andz; scoped prompt instructions; run-tool description, code param description, and deny message. Snippets also getstartUrl,task, andconsolein scope.tool_launch_localandtool_create_browserbase; connection mode derived; model fixed toopenai/gpt-4.1-mini.listCoreTools/getCoreTool; tests assertstagehand_codeis retrievable and that prompt guidance includes awaited locator actions.Written for commit e579140. Summary will update on new commits.