chore(docs): update style guide and make positioning changes to intro… - #2648
Conversation
# why `model: "auto"` shipped in #2328 but is undocumented. This adds a **Model Router** section to `/v3/configuration/models`, nested under **Model Gateway** right after **Setup**, plus a launch callout at the top of the page. # what changed `packages/docs/v3/configuration/models.mdx` only — no code, so no changeset. - **`(NEW) Model Router` callout** at the top of the page, above the Model Gateway one, linking to `#model-router`. Dropped `(NEW)` from the Model Gateway callout so only one feature is flagged as new. - **`### Model Router`** subsection: what it does, basic usage, Model Gateway billing (market-price tokens on your Browserbase key), and the 30–40% cost reduction vs. pinning one frontier model. - **`#### Requirements`** table covering the four API-only constraints the constructor enforces (`env: "BROWSERBASE"`, `disableAPI: false`, `experimental: false`, no `llmClient`), plus a warning that `"auto"` has no local fallback if the API is unavailable at init. - **`#### Per-call routing`**: `{ model: "auto" }` as a per-primitive override on top of a concrete default, including the object form (`{ modelName: "auto", temperature: 0.5 }`) and the note that overrides don't inherit the session provider/API key. - Agent support: works in default `dom`/`hybrid`, **not** with `mode: "cua"` (`"auto"` isn't in `AVAILABLE_CUA_MODELS`, so it throws `CuaModelRequiredError`). - Caching: local replay is skipped for `"auto"` sessions; the API's server-side cache handles it. - Troubleshooting accordion for both auto-specific errors, and an env-var table row. Behavior claims were taken from `modelUtils.ts`, `v3.ts`, `api.ts`, `AgentCache.ts`, and `tests/unit/auto-model.test.ts`. The routing heuristic itself is server-side and not in this repo, so the copy deliberately stays general about how a model gets picked — nothing here goes stale when the router changes. # open question Should omitting `model` entirely also route through Model Router? Today it doesn't — `resolveModelConfiguration()` falls back to `DEFAULT_MODEL_NAME = "openai/gpt-4.1-mini"` (`packages/core/lib/v3/v3.ts:101,115`), so an omitted `model` pins gpt-4.1-mini (run through Model Gateway if only a Browserbase key is set). That's a fixed model, not per-call routing. I left the omit path out of the docs for now. If the default should become `"auto"`, that's a core change and the docs can follow alongside it. # test plan - `mintlify broken-links` — no new broken links (the 5 reported are pre-existing and in other files) - JSX components balanced, code fences even, heading nesting verified, `#model-router` anchor resolves --------- Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
## Summary
- translate daemon socket `ECONNREFUSED` and `ENOENT` failures into a
human-readable error
- print the exact `browse open` command that restarts the requested
session
- document that API keys are forwarded to an already-running daemon and
that `browse stop` is idempotent
- preserve regression coverage for late environment variables and
exit-code-zero cleanup
## Root cause
The daemon client passed raw Unix socket errors through to users when
the daemon disappeared between the readiness check and the request.
Agents received `ECONNREFUSED` without a recovery command.
## Impact
Agents now get an actionable `daemon_not_running` failure with the exact
command needed to restart the session. Recovery command arguments are
shell-quoted, and a daemon disappearing between status and stop is
treated as an already-stopped session. Cleanup synchronizes with daemon
startup so it preserves a replacement daemon that starts during the stop
race. The bundled SKILL.md also makes the already-fixed env timing and
stop behavior explicit.
## E2E Test Matrix
| Command / flow | Observed output | Confidence / sufficiency |
| --- | --- | --- |
| `pnpm --filter browse build` | TypeScript compilation and oclif
manifest generation completed successfully. | Proves the exact local CLI
code under review builds; does not exercise a live browser. |
| `pnpm --filter browse test:cli` | 25 test files passed; 366/366 tests
passed. This includes deterministic daemon disappearance/restart races,
adversarial recovery-command shell quoting, malformed CDP log payloads,
and the complete CLI contract suite. | Proves the full CLI suite passes
against the completed local build on macOS; GitHub CI provides the
Ubuntu/Windows matrix. |
| `BROWSE_DAEMON_DIR=<temp dir> node packages/cli/bin/run.js stop
--session no-daemon-smoke` | Exited `0` and printed `{ "stopped": false,
"session": "no-daemon-smoke" }`. | Exercises the built CLI's real
absent-daemon stop path and confirms its documented successful no-op
behavior. |
| `pnpm --filter browse lint` | Full-package Prettier, ESLint, and
TypeScript checks completed successfully. | Reproduces the CI lint
pipeline locally and verifies the daemon changes, log reducer, tests,
and inherited CLI lint baseline. |
Linear:
[GRO-1908](https://linear.app/browserbase/issue/GRO-1908/cli-namespace-2027-dev-suggested-docs-updates)
<!-- This is an auto-generated description by cubic. -->
---
## Summary by cubic
Replaces raw socket errors with a clear `daemon_not_running` message and
prints the exact, shell-quoted `browse open` recovery command. `browse
stop` now treats a missing daemon as already stopped, validates
ownership before cleanup, and avoids tearing down a daemon that restarts
mid-race. Addresses Linear:
https://linear.app/browserbase/issue/GRO-1908/cli-namespace-2027-dev-suggested-docs-updates.
- **Bug Fixes**
- Map `ECONNREFUSED`/`ENOENT` to `daemon_not_running` and show the
precise, session-aware recovery command.
- Make `browse stop` idempotent and safe: if the daemon vanished (no
`--force`), return `{ stopped: false }`; acquire a lock and verify
daemon ownership before removing pid/socket/lock; preserve a replacement
daemon started during the stop race (handles PID reuse).
- Harden CDP log reduction: stricter parsing, ignore malformed payloads,
and require numeric response statuses.
- Docs: clarify `BROWSERBASE_API_KEY` is forwarded on every command and
`browse stop` is idempotent; add troubleshooting for the new error.
- Tests: cover the error message and shell-quoted recovery command
(round-tripped through `/bin/sh`), stop race cleanup and restart
preservation, PID reuse, and reduce-logs edge cases.
<sup>Written for commit 030c02a.
Summary will update on new commits.</sup>
<a
href="https://cubic.dev/pr/browserbase/stagehand/pull/2356?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: Shrey Pandya <shrey@browserbase.com>
Prepare the next browse release by versioning the package on `main`. What this PR does: - bumps `packages/cli/package.json` to `0.9.6` - updates the browse changelog - consumes the pending browse changesets After this PR merges, the `Release` workflow on `main` will publish `browse@0.9.6` from that exact commit using `pnpm pack` + `npm publish --provenance`. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
# why The CUA and hybrid agents dispatch every pointer action as mouse input. Mobile layouts commonly gate their handlers on touch/pointer events, so a synthesized mouse click never registers — e.g. on `adidas.co.il` (Browserbase `os: "mobile"`) a size selector highlights but keeps reporting "please choose a size", blocking add-to-cart. A trusted touch (`Input.dispatchTouchEvent`) works. Originates from #2384 by @alonle. # what changed - New `useTouch` option (explicit opt-in, default `false`). Forwarded to the server on the API execution path. - `page.tap(x, y)` and `locator.tap()`: trusted touch taps mirroring their click counterparts. - When `useTouch` is set: CUA routes single left clicks to tap (right/middle/multi-click, hover, and drag stay on mouse); hybrid `click`/`type`/`fillFormVision` tap for coordinate focus/activation. - Replay: taps record as `tap` steps and replay as touch. `tap` is not exposed to the LLM during live inference. # test plan - Unit: `touch-actuation` (7), `touch-tool-routing` (9), `touch-cua-routing` (7) — resolution, tool routing, recording. - E2E: `perform-understudy-method` (8) — asserts `pointerdown:touch`/`touchstart`/`touchend` delivery for both tap paths (event-level, since Chromium synthesizes a click from a tap and activation-only assertions can't tell touch from mouse). - Server: `start.test.ts` covers `useTouch` on `/sessions/start`. - Manual: with `useTouch: true` on a Browserbase `os: "mobile"` session, the agent completes the adidas.co.il size + add-to-cart flow. --------- Co-authored-by: alonl <alonl@wix.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
|
There was a problem hiding this comment.
1 issue found across 3 files
Confidence score: 5/5
- In
.cubic/docs-style-guide.md, the rewritten bullet currently reads awkwardly (“Connect top-level positioning that Playwright was not built for agents”), which could confuse contributors and lead to inconsistent guidance edits—restore the missing object or revert to the original phrasing to keep the style rule clear.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name=".cubic/docs-style-guide.md">
<violation number="1" location=".cubic/docs-style-guide.md:23">
P3: This bullet in the style guide itself reads awkwardly after the rewrite. "Connect top-level positioning that Playwright was not built for agents" drops the object of "connect" — the original phrasing was "Connect top-level positioning to the Browserbase narrative that..." — so it now reads as though "top-level positioning" is taken by the that-clause. Suggest restoring the object: "Connect top-level positioning to the fact that Playwright was not built for agents, but Stagehand is."</violation>
</file>
Architecture diagram
sequenceDiagram
participant Dev as Developer
participant SG as Style Guide (.cubic/docs-style-guide.md)
participant Docs as Documentation (MDX files)
participant Cubic as Cubic (PR review bot)
participant AIRules as AI Rules (TS/Python/Go templates)
participant Agent as Agent Tools (Cursor/Windsurf)
Note over Dev,Agent: Documentation Architecture for Stagehand v4
Dev->>SG: Reads positioning guidelines
Dev->>Docs: Updates introduction and AI rules content
Dev->>AIRules: Aligns project descriptions to SDK positioning
Dev->>Cubic: Submits docs PR
Cubic->>SG: Validates PR against style guide rules
SG-->>Cubic: Compliance status
alt Compliance OK
Cubic-->>Dev: Approve
else Violations
Cubic-->>Dev: Request changes
end
Agent->>AIRules: Loads rules for Stagehand projects
Agent->>Docs: References SDK docs for implementation
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| - Keep Stagehand distinct from Browserbase Agents. Stagehand is the SDK and browser driver; Agents is Browserbase's managed API product. Do not use the names interchangeably. | ||
| - Position computer use as one Stagehand capability, not Stagehand's identity. | ||
| - Connect top-level positioning to the Browserbase narrative that the web was not built for agents, but Browserbase is. Keep Stagehand copy focused on the developer's browser-agent workflow rather than the entire Browserbase platform. | ||
| - Connect top-level positioning that Playwright was not built for agents, but Stagehand is. Keep Stagehand copy focused on the developer's browser-agent workflow rather than the entire Browserbase platform. |
There was a problem hiding this comment.
P3: This bullet in the style guide itself reads awkwardly after the rewrite. "Connect top-level positioning that Playwright was not built for agents" drops the object of "connect" — the original phrasing was "Connect top-level positioning to the Browserbase narrative that..." — so it now reads as though "top-level positioning" is taken by the that-clause. Suggest restoring the object: "Connect top-level positioning to the fact that Playwright was not built for agents, but Stagehand is."
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .cubic/docs-style-guide.md, line 23:
<comment>This bullet in the style guide itself reads awkwardly after the rewrite. "Connect top-level positioning that Playwright was not built for agents" drops the object of "connect" — the original phrasing was "Connect top-level positioning to the Browserbase narrative that..." — so it now reads as though "top-level positioning" is taken by the that-clause. Suggest restoring the object: "Connect top-level positioning to the fact that Playwright was not built for agents, but Stagehand is."</comment>
<file context>
@@ -16,28 +16,24 @@ If a PR materially adds or changes a hero, tagline, product description, quantit
- Keep Stagehand distinct from Browserbase Agents. Stagehand is the SDK and browser driver; Agents is Browserbase's managed API product. Do not use the names interchangeably.
- Position computer use as one Stagehand capability, not Stagehand's identity.
-- Connect top-level positioning to the Browserbase narrative that the web was not built for agents, but Browserbase is. Keep Stagehand copy focused on the developer's browser-agent workflow rather than the entire Browserbase platform.
+- Connect top-level positioning that Playwright was not built for agents, but Stagehand is. Keep Stagehand copy focused on the developer's browser-agent workflow rather than the entire Browserbase platform.
- Lead with one primary idea per page or section. Do not compress every Browserbase product pillar into Stagehand copy.
-- Do not lead Stagehand positioning with Search, Fetch, or other supporting Browserbase products.
</file context>
| - Connect top-level positioning that Playwright was not built for agents, but Stagehand is. Keep Stagehand copy focused on the developer's browser-agent workflow rather than the entire Browserbase platform. | |
| - Connect top-level positioning to the fact that Playwright was not built for agents, but Stagehand is. Keep Stagehand copy focused on the developer's browser-agent workflow rather than the entire Browserbase platform. |
…into-v4-spike # Conflicts: # packages/cli/CHANGELOG.md # packages/cli/package.json # packages/cli/skills/browse/SKILL.md # packages/cli/src/lib/cloud/reduce-logs.ts # packages/cli/src/lib/driver/daemon/client.ts # packages/cli/tests/driver-foundation.test.ts # packages/core/lib/v3/agent/tools/click.ts # packages/core/lib/v3/agent/tools/fillFormVision.ts # packages/core/lib/v3/agent/tools/type.ts # packages/core/lib/v3/api.ts # packages/core/lib/v3/handlers/v3CuaAgentHandler.ts # packages/core/lib/v3/types/public/api.ts # packages/core/lib/v3/types/public/options.ts # packages/core/lib/v3/v3.ts # packages/core/tests/integration/perform-understudy-method.spec.ts # packages/server-v3/src/lib/InMemorySessionStore.ts # packages/server-v3/src/lib/SessionStore.ts # packages/server-v3/src/routes/v1/sessions/start.ts # packages/server-v3/tests/integration/v3/start.test.ts
…active voice useTouch documents an option no shipped surface consumes here — the touch-tap port to v4 is a deliberate follow-up, so the v3 reference page reverts to the v4-spike version. Model Router prose recast per the docs prose guide (active voice).
Co-authored-by: Miguel <36487034+miguelg719@users.noreply.github.com>
…4-spike chore: reconcile main into v4-spike ahead of the squash-merge
Adds a readonly `sessionId` to `StagehandBrowser` for Browserbase-backed handles (`browserbase.launch` / `browserbase.connect`); undefined for local browsers. The id was already threaded internally through the worker init metadata — this only surfaces it. **Why:** integration examples that persist sessions for reconnect-after-restart (Eve native tools in #2666, managed deep agents in #2653) currently have to recover the id out-of-band — stamping a `userMetadata` marker at launch and querying `sessions.list` — because the handle doesn't expose it. With this, that workaround collapses to `browser.sessionId`. **Scope:** two files (`browser/index.ts`, `browser/factories.ts`) + changeset. No behavior change; purely additive surface. Gate: build, typecheck, 186/186 unit tests. **Port parity:** TS is the contract — Python/Go should mirror (`session_id` on the Python browser handle) in follow-ups; the Python managed-deepagents example has the same workaround to delete. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Added a readonly `sessionId` to `StagehandBrowser` handles for Browserbase-backed browsers (`browserbase.launch` / `browserbase.connect`). It’s undefined for local browsers and makes reconnect-after-restart flows simpler. - **New Features** - Access the Browserbase session id via `browser.sessionId`; avoids metadata markers + `sessions.list`. - Purely additive API; no behavior changes. <sup>Written for commit 33bb054. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/browserbase/stagehand/pull/2672?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. -->
…2673) Python port of #2672 (TS is the contract; this mirrors it exactly): readonly `session_id` property on `StagehandBrowser`, populated from the worker init metadata for Browserbase launch/connect, `None` for local browsers. Kills the out-of-band session-id recovery in the managed deep-agents example (#2653), same as #2672 does for the Eve example (#2666). Gate: ruff format/check, ty check, 457 passed / 1 skipped. <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Add a read-only session_id property to StagehandBrowser in `sdk-python`, populated from worker init metadata for Browserbase and None for local. This lets clients persist the Browserbase session ID for reconnects without out-of-band recovery. <sup>Written for commit dad895e. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/browserbase/stagehand/pull/2673?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. -->
Go port of #2672 (TS contract) alongside the Python port #2673: nil-safe `SessionID()` accessor on `Browser`, sourced from the worker session metadata the handle already carries; empty string for local browsers. Gate: gofmt clean, go vet clean, package tests pass (examples build failure in `go test ./...` is pre-existing on v4-spike; `scripts/check-examples.sh` passes). <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Added a nil-safe `SessionID()` method to the Go SDK `Browser` to get the Browserbase session ID. It returns an empty string for local browsers or when the handle is nil. <sup>Written for commit 72f3cb2. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/browserbase/stagehand/pull/2674?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. -->
# why - for security # what changed - bumped mintlify to newer version with less transitive dep vulns <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Upgrade Mintlify tooling to reduce transitive vulnerabilities and align with the latest peer dependencies. Updates `mint` to 4.2.788 and refreshes related `@mintlify/*` packages; no app code changes. - **Dependencies** - Bumped `mint` to `4.2.788`. - Updated `@mintlify/cli`, `@mintlify/common`, `@mintlify/mdx`, `@mintlify/models`, `@mintlify/prebuild`, `@mintlify/previewing`, `@mintlify/scraping`, `@mintlify/validation` to their latest versions. - Mintlify now depends on `@base-ui/react` instead of `@radix-ui/react-*` via `@mintlify/mdx`. - Pulled in security fixes via transitive upgrades (e.g., `axios@1.18.0`, `tar@7.5.21`, `adm-zip@0.6.0`, `js-yaml@4.3.1`, `postcss@8.5.23`). - Updated `pnpm-workspace.yaml` catalog and minimumReleaseAgeExclude, and refreshed `pnpm-lock.yaml`. <sup>Written for commit 0c478e5. Summary will update on new commits.</sup> <a href="https://cubic.dev/pr/browserbase/stagehand/pull/2669?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. -->
5f00fe1 to
566ddeb
Compare
There was a problem hiding this comment.
5 issues found across 9 files (changes from recent commits).
Confidence score: 3/5
- In
packages/docs/v4/first-steps/introduction.mdx, both the Pythonactive_page()and TypeScriptactivePage()samples can hitNone/undefinedwhen no tab is active, so copied examples can fail at runtime (and TS can fail strict compile) — add an active-page guard before dereferencing in both snippets. - In
packages/docs/v4/first-steps/introduction.mdx, the updated architecture bullet swaps a concrete description for an unverified speed claim, which can set incorrect performance expectations for readers — restore factual architecture wording or qualify the claim with evidence. - Docs-prose compliance is currently inconsistent across
packages/docs/v3/configuration/models.mdxandpackages/docs/v4/first-steps/introduction.mdx(banned em dash usage and metaphor-heavy phrasing), which increases editorial churn and drift from the style guide — rewrite these lines in explicit, policy-aligned language.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/docs/v4/first-steps/introduction.mdx">
<violation number="1" location="packages/docs/v4/first-steps/introduction.mdx:116">
P2: This TypeScript sample does not compile with strict null checks and throws when the context has no active tab, because `activePage()` can return `undefined`. Check for an active page before calling its methods.</violation>
<violation number="2" location="packages/docs/v4/first-steps/introduction.mdx:127">
P2: This Python sample fails when the context has no active tab, because `active_page()` may return `None` and the next line dereferences it. Add the same active-page guard used by the Go example.</violation>
<violation number="3" location="packages/docs/v4/first-steps/introduction.mdx:159">
P2: Custom agent: **Stagehand docs prose guide**
The new bullet replaces a factual architecture description with an unsubstantiated performance claim ("so remote browsers feel as fast as local ones"). The prose guide requires describing documented behavior precisely and not implying certainty beyond what the documented feature supports. A search of the docs shows no other page substantiates this speed parity claim. Rewrite this to documented behavior only: for example, state that Stagehand's runtime executes in the browser next to the page and leave performance claims out unless they are documented elsewhere.</violation>
<violation number="4" location="packages/docs/v4/first-steps/introduction.mdx:164">
P1: Custom agent: **Stagehand docs prose guide**
The 'Built for agent harnesses' bullet uses metaphorical phrasing ('Stagehand is the hands. Bring your own agent as the brain') rather than explicit engineer-style language. The prose guide's Voice rule requires explicit language over clever phrasing and states engineers should write like an engineer stating a fact, not a keynote speaker. Rewrite with a direct description of the division of labor, for example: 'Stagehand provides the browser controls; connect your own agent framework (LangChain, CrewAI, Mastra, or a custom loop).'</violation>
</file>
<file name="packages/docs/v3/configuration/models.mdx">
<violation number="1">
P1: Custom agent: **Stagehand docs prose guide**
The added callout prose uses an em dash (—), which the docs prose guide explicitly bans: "Do not use em dashes in prose, frontmatter, tables, or authored code comments." Replace the em dash with a colon or period. For example: "**(NEW) Model Gateway**: Use your Browserbase API key..."</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| - **Extraction is typed:** [`extract`](/v4/basics/extract) validates results against a schema you define and hands back fully typed data. | ||
| - **Models are flexible:** Use a supported provider by name or supply your own client-side LLM callback. | ||
| - **Metrics are built in:** Read per-method token usage and inference timing with [`metrics()`](/v4/reference/stagehand). | ||
| - **Built for agent harnesses:** Stagehand is the hands. Bring your own agent as the brain (LangChain, CrewAI, Mastra, or a custom loop). |
There was a problem hiding this comment.
P1: Custom agent: Stagehand docs prose guide
The 'Built for agent harnesses' bullet uses metaphorical phrasing ('Stagehand is the hands. Bring your own agent as the brain') rather than explicit engineer-style language. The prose guide's Voice rule requires explicit language over clever phrasing and states engineers should write like an engineer stating a fact, not a keynote speaker. Rewrite with a direct description of the division of labor, for example: 'Stagehand provides the browser controls; connect your own agent framework (LangChain, CrewAI, Mastra, or a custom loop).'
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/docs/v4/first-steps/introduction.mdx, line 164:
<comment>The 'Built for agent harnesses' bullet uses metaphorical phrasing ('Stagehand is the hands. Bring your own agent as the brain') rather than explicit engineer-style language. The prose guide's Voice rule requires explicit language over clever phrasing and states engineers should write like an engineer stating a fact, not a keynote speaker. Rewrite with a direct description of the division of labor, for example: 'Stagehand provides the browser controls; connect your own agent framework (LangChain, CrewAI, Mastra, or a custom loop).'</comment>
<file context>
@@ -99,15 +106,62 @@ fmt.Println(len(observed.Data), "candidate actions")
- **Extraction is typed:** [`extract`](/v4/basics/extract) validates results against a schema you define and hands back fully typed data.
- **Models are flexible:** Use a supported provider by name or supply your own client-side LLM callback.
- **Metrics are built in:** Read per-method token usage and inference timing with [`metrics()`](/v4/reference/stagehand).
+- **Built for agent harnesses:** Stagehand is the hands. Bring your own agent as the brain (LangChain, CrewAI, Mastra, or a custom loop).
## Built for modern development
</file context>
| - **Built for agent harnesses:** Stagehand is the hands. Bring your own agent as the brain (LangChain, CrewAI, Mastra, or a custom loop). | |
| - **Built for agent harnesses:** Stagehand provides the browser controls; connect your own agent framework (LangChain, CrewAI, Mastra, or a custom loop). |
|
|
||
| <Tab title="Python"> | ||
| ```python | ||
| page = await stagehand.browser.context.active_page() |
There was a problem hiding this comment.
P2: This Python sample fails when the context has no active tab, because active_page() may return None and the next line dereferences it. Add the same active-page guard used by the Go example.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/docs/v4/first-steps/introduction.mdx, line 127:
<comment>This Python sample fails when the context has no active tab, because `active_page()` may return `None` and the next line dereferences it. Add the same active-page guard used by the Go example.</comment>
<file context>
@@ -99,15 +106,62 @@ fmt.Println(len(observed.Data), "candidate actions")
+
+<Tab title="Python">
+```python
+page = await stagehand.browser.context.active_page()
+
+await page.goto("https://example.com")
</file context>
| page = await stagehand.browser.context.active_page() | |
| page = await stagehand.browser.context.active_page() | |
| if page is None: | |
| raise RuntimeError("Stagehand has no active page") |
| <Tabs> | ||
| <Tab title="TypeScript"> | ||
| ```typescript | ||
| const page = await stagehand.browser.context.activePage(); |
There was a problem hiding this comment.
P2: This TypeScript sample does not compile with strict null checks and throws when the context has no active tab, because activePage() can return undefined. Check for an active page before calling its methods.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/docs/v4/first-steps/introduction.mdx, line 116:
<comment>This TypeScript sample does not compile with strict null checks and throws when the context has no active tab, because `activePage()` can return `undefined`. Check for an active page before calling its methods.</comment>
<file context>
@@ -99,15 +106,62 @@ fmt.Println(len(observed.Data), "candidate actions")
+<Tabs>
+<Tab title="TypeScript">
+```typescript
+const page = await stagehand.browser.context.activePage();
+
+await page.goto("https://example.com");
</file context>
| const page = await stagehand.browser.context.activePage(); | |
| const page = await stagehand.browser.context.activePage(); | |
| if (!page) { | |
| throw new Error("Stagehand has no active page"); | |
| } |
| - **First-class TypeScript, Python, and Go SDKs:** Each client is generated from the same protocol, so every method and option matches across supported languages. | ||
| - **The AI primitives live on Stagehand:** `act`, `extract`, and `observe` are methods on [`stagehand`](/v4/reference/stagehand). They run on the browser's active page by default, or on a page you pass. Deterministic controls like `goto`, `click`, and `type` stay on [`page`](/v4/reference/page). | ||
| - **Precise control:** Mix AI-powered actions with deterministic `page` APIs. You decide exactly how much AI to use. | ||
| - **Runtime lives in the browser:** Stagehand runs next to the page, so remote browsers feel as fast as local ones. |
There was a problem hiding this comment.
P2: Custom agent: Stagehand docs prose guide
The new bullet replaces a factual architecture description with an unsubstantiated performance claim ("so remote browsers feel as fast as local ones"). The prose guide requires describing documented behavior precisely and not implying certainty beyond what the documented feature supports. A search of the docs shows no other page substantiates this speed parity claim. Rewrite this to documented behavior only: for example, state that Stagehand's runtime executes in the browser next to the page and leave performance claims out unless they are documented elsewhere.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/docs/v4/first-steps/introduction.mdx, line 159:
<comment>The new bullet replaces a factual architecture description with an unsubstantiated performance claim ("so remote browsers feel as fast as local ones"). The prose guide requires describing documented behavior precisely and not implying certainty beyond what the documented feature supports. A search of the docs shows no other page substantiates this speed parity claim. Rewrite this to documented behavior only: for example, state that Stagehand's runtime executes in the browser next to the page and leave performance claims out unless they are documented elsewhere.</comment>
<file context>
@@ -99,15 +106,62 @@ fmt.Println(len(observed.Data), "candidate actions")
-- **First-class TypeScript, Python, and Go SDKs:** Each client is generated from the same protocol, so every method and option matches across supported languages.
-- **The AI primitives live on Stagehand:** `act`, `extract`, and `observe` are methods on [`stagehand`](/v4/reference/stagehand). They run on the browser's active page by default, or on a page you pass. Deterministic controls like `goto`, `click`, and `type` stay on [`page`](/v4/reference/page).
+- **Precise control:** Mix AI-powered actions with deterministic `page` APIs. You decide exactly how much AI to use.
+- **Runtime lives in the browser:** Stagehand runs next to the page, so remote browsers feel as fast as local ones.
+- **First-class TypeScript, Python, and Go SDKs:** Every method and option matches across supported languages.
- **Extraction is typed:** [`extract`](/v4/basics/extract) validates results against a schema you define and hands back fully typed data.
</file context>
| - **Runtime lives in the browser:** Stagehand runs next to the page, so remote browsers feel as fast as local ones. | |
| - **Runtime lives in the browser:** Stagehand runs next to the page. |
There was a problem hiding this comment.
1 issue found across 4 files (changes from recent commits).
Confidence score: 5/5
- In
packages/docs/v4/configuration/browser.mdx, the comma splice in the plan-restriction sentence can make the guidance read as a run-on, which may briefly confuse readers about support instructions—replace the comma with a period or semicolon to clarify the meaning.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="packages/docs/v4/configuration/browser.mdx">
<violation number="1" location="packages/docs/v4/configuration/browser.mdx:329">
P3: This comment has a comma splice, which makes the plan restriction read as a run-on. Use a period or semicolon before the support instruction.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| keepAlive: true, // Available on Startup plan | ||
| browserSettings: { | ||
| verified: false, // this is a Scale Plan feature - reach out to support@browserbase.com to enable | ||
| verified: false, // this is a Scale Plan feature, reach out to support@browserbase.com to enable |
There was a problem hiding this comment.
P3: This comment has a comma splice, which makes the plan restriction read as a run-on. Use a period or semicolon before the support instruction.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/docs/v4/configuration/browser.mdx, line 329:
<comment>This comment has a comma splice, which makes the plan restriction read as a run-on. Use a period or semicolon before the support instruction.</comment>
<file context>
@@ -326,7 +326,7 @@ const browser = await browserbase.launch({
keepAlive: true, // Available on Startup plan
browserSettings: {
- verified: false, // this is a Scale Plan feature - reach out to support@browserbase.com to enable
+ verified: false, // this is a Scale Plan feature, reach out to support@browserbase.com to enable
blockAds: true,
solveCaptchas: true,
</file context>
| verified: false, // this is a Scale Plan feature, reach out to support@browserbase.com to enable | |
| verified: false, // This is a Scale Plan feature. Reach out to support@browserbase.com to enable it. |
e478943
into
alyssamaruyama/stg-2801-add-go-snippets-to-missing-reference-docs
… and ai rules
why
Stagehand is changing, and so is the way that we talk about it.
what changed
Some of these things are updating the docs, cubic MD, that reviews PRs to our docs to make sure that they're aligned, and then also making some raw positioning changes to our documentation.
test plan
Summary by cubic
Updates docs to Stagehand v4 positioning and expands the intro with Playwright-style API examples alongside AI primitives, plus Model Router docs (
model: "auto"). Also exposes the Browserbase session ID on TS, Python, and Go SDK browser handles to simplify reconnect flows (GRO-1708).New Features
StagehandBrowser.sessionIdfor Browserbase-backed browsers; undefined for local.StagehandBrowser.session_id; None for local.Browser.SessionID(); empty string for local.Refactors
pageAPI section with TS/Python/Go samples; clarify two layers (AI primitives + deterministicpageAPIs); update “Why developers choose Stagehand.”mintand@mintlify/*to current versions.Written for commit 7888660. Summary will update on new commits.