Skip to content

Migrate all Stagehand templates to V4 - #101

Open
shrey150 wants to merge 31 commits into
devfrom
agent/update-templates-stagehand-v4
Open

Migrate all Stagehand templates to V4#101
shrey150 wants to merge 31 commits into
devfrom
agent/update-templates-stagehand-v4

Conversation

@shrey150

@shrey150 shrey150 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Stagehand is the SDK for browser agents.

  • migrate every Stagehand template in this repository to the V4 lifecycle: 35 TypeScript, 32 Python, and 1 Go
  • use published @browserbasehq/stagehand@4.0.0 and stagehand==4.0.0 for the core SDKs
  • replace removed agent APIs with bring-your-own agent frameworks plus Stagehand code mode
  • adopt browserbase.launch() / localBrowser.launch(), Stagehand.create({ browser }), browser.context, V4 { data, metadata } envelopes, locator(), and explicit Stagehand-then-browser cleanup
  • keep shipped examples focused on demonstrating their task; validate correctness out of band instead of embedding test graders in template code
  • update the docs and template index for V4

Companion PR: browserbase/create-browser-app#40

Agent migration: 12 templates

Eight TypeScript templates use Vercel AI SDK ToolLoopAgent with Stagehand code mode's stateful code_execute tool:

  • typescript/agent-with-human-in-loop
  • typescript/browser-agent-demo
  • typescript/business-lookup
  • typescript/company-address-finder
  • typescript/dynamic-form-filling
  • typescript/gemini-3-flash
  • typescript/gemini-cua
  • typescript/microsoft-cua

Four Python templates use Deep Agents with the Stagehand integration's stateful browser tools:

  • python/business-lookup
  • python/cerebras-docs-checker
  • python/company-address-finder
  • python/gemini-cua

The Exa TypeScript and Python templates use a smaller direct Stagehand workflow: focused Exa discovery, one role, act / extract / observe, exact résumé upload mechanics, and a human-review result that never submits.

The Go template's removed autonomous Sessions.Execute step is now an explicit V4 ObserveAct → typed Extract workflow. Its live output is judged only by the external E2E harness.

Package state

  • TypeScript core: published @browserbasehq/stagehand@4.0.0
  • Python core: published stagehand==4.0.0
  • TypeScript code mode: exact reviewed source commit 54302fc5f13be5ad8e717d8e1388502de22be2ed until @browserbasehq/stagehand-codemode is published
  • Python Deep Agents integrations: business-lookup, company-address-finder, cerebras-docs-checker, and gemini-cua track stagehand/main. Their server dependency is published stagehand==4.0.0
  • Go V4 SDK: published github.com/browserbase/stagehand/packages/sdk-go/v4@v4.0.2

The code-mode Git dependency needs two temporary measures until publication: the pnpm subdirectory selector must be path:packages/integrations (no leading slash), and pnpm overrides must resolve the upstream monorepo's workspace: / catalog: dependencies. These are present in all eight code-mode manifests.

Fresh out-of-band 79-entrypoint E2E re-audit — 2026-08-21

Important

This section supersedes every earlier E2E table. Runtime claims use only executions performed in this audit; no historical result is counted.

Review assessment

Ready for human review. The current result set covers all 79 entrypoints: 72 runnable entries pass, zero runnable entries fail, and seven are explicitly blocked by unavailable login credentials or Cerebras quota.

Published head: c87e1c0, tree 08fc487690981454330a636b9d659760a55f090d.

Runtime Inventory Fresh PASS Fresh BLOCKED Fresh FAIL
TypeScript 41 38 3 0
Python 37 33 4 0
Go 1 1 0 0
Total 79 72 7 0

The harness installed and invoked every runnable entrypoint against real services and configured credentials. It ran the complete 79-entrypoint inventory, retained every result, then reran every entrypoint affected by a final min-cut fix. The final set is therefore complete for the published tree, while preserving the original full-run evidence and flake history.

Each entrypoint has a separate scratchpad validator outside the repository. Those validators inspect real output and, where applicable, deterministic external truth or artifacts: current Hacker News titles, ZIP/PDF/image contents, proxy IPs, response URLs, UI/SSE state, and form postconditions. None of this audit judging ships in template code.

Focused review follow-up — 2026-08-21

The inventory counts below remain one result per entrypoint. These additional repetitions specifically test the latest review-driven simplifications on the published head:

Focused flow Fresh result External evidence
Accessibility-reference caveat removal 36/36 PASS: 3 runs for each of 12 TypeScript/Python entrypoints Real HTTP(S) hrefs, Amazon /dp/ URLs, four-PDF ZIPs, image magic bytes, link reports, and Reducto PDF output
Python Browserbase + Reducto 3/3 PASS Typed async sessions.downloads.list returned a fresh ZIP containing a PDF; Reducto returned the complete iPhone sales object
Python Business Lookup with extra prompt clauses removed 3/3 PASS Every structured field matched the current official SF Open Data record
Cartesia conversational radio selection without a string heuristic 3/3 PASS across four radio answers per run, plus one full-flow PASS Deterministic outer inspection confirmed the selected labels; the complete nine-field synthetic submission reached the confirmation page
Go Hacker News on published sdk-go/v4@v4.0.2 PASS go test ./... and the real observe → act → two typed extracts completed
Gemini CUA integration from stagehand@main PASS Current main built successfully and the real two-source eclipse workflow completed
TypeScript Model Router defaults PASS Smart Fetch forced a real browser fallback and routed extract; Website Link Tester completed 3 consecutive one-link runs after one initial invalid-URL structured-output miss

All 12 “never return an accessibility-tree reference” prompt/schema caveats were removed only after the corresponding entrypoint reached 3/3 with the caveat absent. TypeScript and Python were evaluated independently; no result was inferred across SDKs.

Fresh TypeScript passes (38)

agent-with-human-in-loop, amazon-global-price-comparison, amazon-product-scraping, basic-caching, basic-recaptcha, browser-agent-demo, browserbase-reducto, business-lookup, company-address-finder, company-value-prop-generator, council-events, download-financial-statements, dynamic-form-filling, exa-browserbase, extend-browserbase, form-filling, gemini-3-flash, gemini-cua, getting-started-with-browserbase, gift-finder, google-trends, image-url-download, job-application, license-verification, mfa-handling, microsoft-cua, nurse-verification, playwright-mfa-handling, playwright/basic-recaptcha, playwright/quickstart-playwright, polymarket-research, proxies, proxies-weather, puppeteer/quickstart-puppeteer, sec-filing-research, selenium/quickstart-selenium, smart-fetch-scraper, website-link-tester.

Fresh Python passes (33)

amazon-global-price-comparison, amazon-product-scraping, basic-caching, basic-recaptcha, browserbase-reducto, business-lookup, cartesia-form-filling, company-address-finder, company-value-prop-generator, council-events, download-financial-statements, exa-browserbase, extend-browserbase, form-filling, gemini-cua, getting-started-with-browserbase, gift-finder, google-trends, image-url-download, job-application, license-verification, mfa-handling, nurse-verification, playwright-mfa-handling, playwright/basic-recaptcha, playwright/quickstart-playwright, polymarket-research, proxies, proxies-weather, sec-filing-research, selenium/quickstart-selenium, smart-fetch-scraper, website-link-tester.

Go hackernews: PASS.

Fresh blockers

Entrypoints Count Fresh evidence / unblock
TypeScript + Python context and pickleball 4 SF_REC_PARK_EMAIL and SF_REC_PARK_PASSWORD are not configured as Coder User Secrets. Tests use BOOK_COURT=false; no reservation would be made.
TypeScript + Python manual-mfa-with-contexts 2 GITHUB_USERNAME and GITHUB_PASSWORD are not configured as Coder User Secrets.
Python cerebras-docs-checker 1 Crawl/repository discovery reached the model call, then the configured Cerebras credential returned HTTP 402/payment required. Billing/quota must be restored.

Do not paste credentials into the PR. Configure them through managed Coder User Secrets if fresh coverage of those paths is required.

Approved policy audit

The published tree is 79/79 policy-aligned under the full review contract:

  1. V4 lifecycle, envelopes, cleanup, and idiomatic first-party SDK dependencies are used; handwritten Browserbase REST calls were removed.
  2. Explicit Stagehand workflows retain act / extract / observe as their primary semantics. No primitive was swapped for deterministic page actions merely to pass E2E.
  3. Direct page/locator methods are classified per entrypoint and limited to native-framework examples, agent/code-mode autonomy, exact file/download mechanics, intrinsic product checks, or a semantic-first correctness fallback.
  4. Code-mode and Deep Agent prompts are not forced toward semantic Stagehand primitives; deterministic code is intentional in those architectures.
  5. Shipped examples demonstrate their advertised workflow. Known-answer judging, live-page comparison, and E2E assertions remain in the external scratchpad harness.
  6. In-template validation remains only where evaluation is itself the product, including caching, CAPTCHA/authentication, proxy/geolocation, link testing, docs checking, ranking, and booking confirmation.
  7. TypeScript/Python counterparts preserve the same task intent and idioms. Simplifications are narrow and documented.
  8. Exa uses one supplied role, fills only supplied non-empty applicant values, reports missing required fields, uploads the exact résumé, stops for human review, and never submits.
  9. Consequential side effects are disabled in E2E unless the public test flow explicitly requires them.
  10. Python clients use Stagehand's default endpoint: zero api_url or STAGEHAND_API_URL overrides remain. Repository CLI copy uses browse, not bb.
  11. All 79 entrypoints have fresh evidence and one external validator; blockers and probabilistic behavior are reported without inferring success.
  12. Human review remains the merge gate; this automation did not merge the PR.

The per-entrypoint matrix also checks README/live-site task alignment: 70 entrypoints map to the current public catalog and nine are repository-only. Three public-copy caveats remain transparent: Exa's safe one-role review flow is narrower than “apply at scale”; Gemini CUA pages still use older CUA/V3 naming while these templates use V4 code mode; Image URL Download now uses the first-party Fetch API although the site still describes browser-session downloads.

Notable final outcomes

  • Nurse verification: both SDKs pass with semantic act / observe / extract; there is no locator/evaluate replacement or embedded judge.
  • Exa: both SDKs pass the simplified one-role, review-only flow.
  • Gemini: the illustrative live eclipse-research prompt is restored across the three variants. Output is checked only by the external harness; TypeScript performs a tool-free synthesis only when the agent exhausts tools without final text. Python Gemini CUA now follows stagehand/main, matching the other Deep Agents templates.
  • Contexts: create/delete now uses the first-party Browserbase SDK in TypeScript and Python. An explicit empty delete body is required by the current generated SDK/API behavior and was live-smoked.
  • Image download: semantic extract remains the discovery path; the Browserbase SDK Fetch API downloads assets. Exact DOM URL reading is used only after semantic candidates are empty or all un-fetchable.
  • Proxy and link flakes: TypeScript Proxies now falls back from ipinfo.io to a second public geolocation endpoint; Python Website Link Tester falls back to exact DOM href acquisition only after extract yields no usable link.
  • Review simplifications: redundant accessibility-reference caveats and Business Lookup's unproven call-limit/immediate-return clauses are removed. Cartesia radio interpretation now uses semantic Stagehand actions instead of a string-matching heuristic.
  • Model Router: Smart Fetch Scraper and Website Link Tester now omit explicit model names. Smart Fetch also contains close-socket cleanup warnings so a completed extraction is not converted into a task failure.
  • Cleanup-only failures: Form Filling and Polymarket preserve successful task outcomes while containing close-socket warnings during teardown.

Fresh flake record

The complete run observed transient failures rather than hiding them: one empty TypeScript cache observe, one Python Amazon structured parse miss, one TypeScript proxy endpoint fetch failure, one Python link-extraction miss, and cleanup socket failures after successful Form Filling/Polymarket outcomes. Focused reruns also observed one Amazon page-readiness timeout before extraction, intermittent Cartesia direct-click CDP failures, and one routed Website Link Tester extraction containing invalid URLs; the replacement Amazon run passed, Cartesia uses semantic observe → act only after direct semantic act cannot complete the interaction, and Website Link Tester then passed 3 consecutive routed runs. Unchanged reruns or the minimum scoped fixes above passed. Gemini and the Next.js HITL flow showed substantial latency variability; they passed but should not be treated as deterministic-duration examples.

Repository proof

Check Fresh result
Entrypoint E2E 72 PASS, 7 BLOCKED, 0 FAIL across 79 entries
External validators 79/79 validator wrappers present
Policy scan 79/79 aligned; zero explicit Stagehand endpoint overrides or handwritten Browserbase REST
Source checks README index, Prettier, ESLint, Ruff lint/format, and Python compilation pass
Go Real Hacker News entrypoint compiled and executed successfully in the E2E runtime; host go vet was unavailable on this devbox
Patch integrity git diff --check passes
Published head/tree c87e1c0 / 08fc487690981454330a636b9d659760a55f090d

Comparison limitation

A literal fresh V3/V4 runtime A/B was not practical for all 79 entrypoints: some V3 APIs/models are superseded, six flows require unavailable login secrets, one credential is out of quota, and some tasks have consequential side effects. Task intent was compared against origin/dev and the live public catalog. Every runtime claim above comes only from fresh V4 executions in this audit.


Note

High Risk
Repo-wide SDK rewrite (TS/Python/Go) plus new BYO-agent orchestration, MCP/code-mode, and credential model (AI_GATEWAY_API_KEY). Scope and API-surface change are large even though these are example templates.

Overview
Migrates all Stagehand templates (TS, Python, Go) from V3 session APIs to Stagehand V4 (@browserbasehq/stagehand@4.0.0, stagehand==4.0.0, Go sdk-go/v4@v4.0.2).

Lifecycle: examples now browserbase.launch() / Stagehand.create({ browser }), use { data, metadata } results, and close Stagehand then the browser. Docs and the root template index point at V4; primitives use Browserbase Model Gateway (BROWSERBASE_API_KEY only).

Agents: V3 agent() / CUA / Sessions.Execute are gone. Eight TS templates use Vercel AI SDK ToolLoopAgent + Stagehand code mode (code_execute, git-pinned @browserbasehq/stagehand-codemode until publish). Four Python templates use LangChain Deep Agents over MCP (run / snapshot / screenshot) and AI_GATEWAY_API_KEY. Go Hacker News is an explicit Observe → Act → typed Extract flow.

Non-agent examples are rewritten to the same V4 primitives (Amazon, caching, reCAPTCHA, Reducto downloads, Cartesia form fill, etc.), with Python requiring 3.11–3.13.

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

@socket-security

socket-security Bot commented Aug 9, 2026

Copy link
Copy Markdown

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report

@shrey150
shrey150 marked this pull request as ready for review August 10, 2026 19:20
@shrey150
shrey150 requested a review from a team as a code owner August 10, 2026 19:20
Comment thread typescript/amazon-product-scraping/index.ts Outdated
Comment thread typescript/amazon-product-scraping/index.ts Outdated
Comment thread typescript/browserbase-reducto/index.ts
Comment thread python/cartesia-form-filling/stagehand_form_filler.py Outdated
Comment thread typescript/exa-browserbase/index.ts Outdated
Comment thread typescript/exa-browserbase/index.ts Outdated
@shrey150 shrey150 changed the title Update TypeScript templates to Stagehand V4 Migrate all Stagehand templates to V4 Aug 11, 2026
Comment thread go/hackernews/main.go Outdated
Comment thread python/cartesia-form-filling/stagehand_form_filler.py Outdated
Comment thread python/cartesia-form-filling/stagehand_form_filler.py Outdated
Comment thread python/exa-browserbase/main.py Outdated
Comment thread typescript/pickleball/index.ts
Comment thread typescript/exa-browserbase/index.ts Outdated
Comment thread typescript/exa-browserbase/index.ts Outdated
Comment thread python/amazon-product-scraping/main.py
Comment thread typescript/mfa-handling/index.ts
Comment thread typescript/exa-browserbase/index.ts Outdated
Comment thread python/exa-browserbase/main.py
Comment thread python/exa-browserbase/main.py
Comment thread python/exa-browserbase/main.py
Comment thread python/image-url-download/main.py
Comment thread python/amazon-product-scraping/main.py Outdated
Comment thread python/context/main.py Outdated
Comment thread python/gemini-cua/main.py
Comment thread python/image-url-download/main.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 using default effort 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.

Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.

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

Comment thread typescript/image-url-download/index.ts
Comment thread typescript/proxies/index.ts
Comment thread go/hackernews/README.md Outdated
3. Run `go mod download`.
4. Run `go run .`.

The V4 Go SDK is temporarily pinned to an exact Stagehand source commit. Replace it with the published V4 Go module once that package is released.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fast-follow: fix upstream Stagehand V4 Go release tagging

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 8c89b3f — switched go.mod and imports to the published github.com/browserbase/stagehand/packages/sdk-go/v4 v4.0.2, refreshed go.sum, and removed the temporary README warning. go test ./... and the real Hacker News entrypoint both pass.

input=upload_response,
instructions=instructions,
settings=settings,
response = await asyncio.to_thread(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Shouldn't this use stagehand.extract instead of a direct API call?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Clarified in 8c89b3f by renaming this to reducto_client. This call is intentionally Reducto's PDF extraction API after the file has been downloaded; stagehand.extract extracts from the active browser page and would remove the template's Reducto workflow. The complete Browserbase download → PDF → Reducto result passed 3/3.

Comment thread python/browserbase-reducto/main.py Outdated
) -> int:
started = time.monotonic()
while time.monotonic() - started < retry_for_seconds:
response = await asyncio.to_thread(client.sessions.downloads.list, session_id)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Check if there is a more idiomatic way to interact with our downloads API

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 8c89b3f — Python now uses AsyncBrowserbase with the typed await api.sessions.downloads.list(session_id) ZIP endpoint and await response.read(). No raw HTTP or explicit API URL is needed. The updated path passed 3/3 live runs with a real PDF in each ZIP.


SERVER_NAME = "stagehand_browser"

STAGEHAND_DEEPAGENTS_SOURCE = (

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fast follow: publish codemode MCP so that external integrations (like templates or eve external PR) can consume it without having to pin to a GitHub commit / repo

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed as an upstream fast-follow. There is not yet a published codemode MCP package for this template to consume, so this PR retains the reviewed source dependency until that first-class package exists; no additional template-side workaround is warranted.

Comment thread python/business-lookup/main.py Outdated
tools=tools,
system_prompt=(
BROWSER_INSTRUCTIONS
+ "\nUse no more than eight browser-tool calls. Once you find the exact record, "

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Have we empirically checked that specifying the tool calls in-context is followed or actually affects the MCP run? Furthermore, does specifying to return the structured response immediately also have the same outcome? If not, we should remove both instructions

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 78e6d02 — removed both the eight-tool-call limit and the “return immediately” clause. The simpler prompt passed 3/3 live runs, and an external validator matched every returned field against the current official SF Open Data record each time, so those instructions had no demonstrated correctness benefit.


# Use Stagehand's natural language API to fill the field
if field.field_type == FieldType.RADIO:
matched_option = self._match_radio_option(answer, field.options or [])

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Shouldn't stagehand.act be able to handle this without a heuristic? The _match_radio_option function seems like an unnecessary heuristic that we should abstract away via model inference through stagehand.act

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 78e6d02 — removed _match_radio_option entirely. Radio answers now go through semantic stagehand.act; only if the direct action fails at the interaction layer do we use semantic observeact. A scratch validator passed 3/3 across four conversational answers per run (including “Yes, I have no issues…” and “No, I haven’t…”), and the complete nine-field synthetic submission also passed with the real confirmation page.

Comment thread python/gemini-cua/agent_runtime.py Outdated
SERVER_NAME = "stagehand_browser"

STAGEHAND_DEEPAGENTS_SOURCE = (
"git+https://github.com/browserbase/stagehand.git@2785d0d1fb9f254a51b9f223f1f1a250094c8e79"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This shouldn't need to be pinned to a specific commit hash - we can have it point to stagehand main

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 78e6d02STAGEHAND_DEEPAGENTS_SOURCE now tracks stagehand@main, matching the other Python Deep Agents templates. A real Gemini CUA run built the integration from current main and completed the two-source eclipse workflow successfully.

Comment thread typescript/smart-fetch-scraper/index.ts Outdated
},
});
const stagehand = await Stagehand.create({
browser: browser,
model: { modelName: "google/gemini-2.5-flash" },

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Let's omit model name so we can use Model Router

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in c87e1c0 — removed the explicit Gemini model so Stagehand uses Model Router. A fresh run forced the Fetch API’s 53-character response into the real browser fallback; routed extract completed and returned structured data. That run also exposed the existing close-socket cleanup race, so cleanup now follows the warning-only guards used by the other templates and the entrypoint exits successfully.

Comment thread typescript/website-link-tester/index.ts Outdated
});
const stagehand = await Stagehand.create({
browser,
model: { modelName: "google/gemini-2.5-pro" },

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Let's remove model name so we can use Model Router

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in c87e1c0 — removed the explicit Gemini model so Stagehand uses Model Router. With MAX_LINKS=1, the real homepage link discovery and destination verification completed 3 consecutive routed runs. One earlier routed extraction returned invalid URL values and is recorded in the PR flake section. The Fetch API redesign remains intentionally deferred to a fast follow.

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