Skip to content

[STG-1852] feat: support hosted model.providerOptions for bedrock and vertex#2031

Open
shrey150 wants to merge 7 commits intomainfrom
shrey/stg-provideroptions-hosted
Open

[STG-1852] feat: support hosted model.providerOptions for bedrock and vertex#2031
shrey150 wants to merge 7 commits intomainfrom
shrey/stg-provideroptions-hosted

Conversation

@shrey150
Copy link
Copy Markdown
Contributor

@shrey150 shrey150 commented Apr 23, 2026

Linear: https://linear.app/browserbase/issue/STG-1852/support-hosted-provideroptions-for-bedrock-and-vertex-models

Summary

  • add public model.providerOptions support for Bedrock and Vertex while keeping legacy top-level Vertex fields working
  • normalize provider-specific auth for local runs and serialize it into hosted providerConfig payloads for Stagehand API
  • resend the session model config on hosted actions so provider-native auth survives past init()
  • cover the new path with API client, schema, normalizer, and public API tests

Testing

  • pnpm --dir packages/core run build
  • pnpm --dir packages/core run lint
  • pnpm --dir packages/core exec vitest run dist/esm/tests/unit/model-provider-options.test.js dist/esm/tests/unit/api-client-model-config.test.js dist/esm/tests/unit/api-provider-config-schema.test.js dist/esm/tests/unit/public-api/llm-and-agents.test.js dist/esm/tests/unit/llm-middleware.test.js
  • set -a && source /Users/shrey/Developer/scratchpad/.stagehand-bedrock-local.env && set +a && BROWSERBASE_CONFIG_DIR='' pnpm run repro in /Users/shrey/Developer/scratchpad/stagehand-provideroptions-local
    • extracted NYT headline via public Stagehand constructor: The ‘Make America Healthy Again’ Movement Is Cooling on Trump and Republicans

Related


Summary by cubic

Adds model.providerOptions for bedrock/... and vertex/..., serializes provider auth into hosted modelClientOptions.providerConfig, re-sends the session model config on all hosted actions (including navigate), and normalizes hosted model config on the server. Docs include Bedrock/Vertex examples and drop the Vertex experimental requirement when using hosted client options. Meets Linear STG-1852.

  • New Features

    • Serialize SDK model.providerOptions to hosted modelClientOptions.providerConfig with new API schemas (ProviderConfig, ModelClientOptions) and validation.
    • Bedrock: accept region, accessKeyId, secretAccessKey, sessionToken; promote to local runtime; start sessions without x-model-api-key when auth is provided.
    • Vertex: support legacy project/location/headers and providerOptions; normalize headers (including Headers); allow serializable googleAuthOptions; allow hosted Vertex configs in API mode when client options are provided.
    • Auto-resend the session model config on hosted act/extract/observe/navigate when no per-call model is given; navigate options now accept a model.
    • Server (packages/server-v3): normalize hosted model and agent configs via normalizeApiModelConfig, mapping providerConfig to SDK providerOptions and accepting string models.
  • Bug Fixes

    • Stricter allowlists and type checks for hosted provider options; reject mismatched providerConfig.provider vs modelName.
    • Bedrock: require region; enforce AWS key pairs (accessKeyId with secretAccessKey); sessionToken requires both; headers must be string maps.
    • Vertex: googleAuthOptions must be an object with supported keys only; credential fields must be strings; scopes must be string or string[]; empty headers are not treated as hosted config.

Written for commit 6f62d1f. Summary will update on new commits. Review in cubic

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 23, 2026

🦋 Changeset detected

Latest commit: 6f62d1f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@browserbasehq/stagehand Minor
@browserbasehq/stagehand-evals Patch
@browserbasehq/stagehand-server-v3 Patch
@browserbasehq/stagehand-server-v4 Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Comment thread packages/core/lib/v3/types/public/api.ts
@shrey150 shrey150 marked this pull request as ready for review April 23, 2026 20:26
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 10 files

Confidence score: 3/5

  • There is moderate merge risk: two medium-severity issues (6/10) with high confidence suggest concrete user-facing behavior problems rather than pure housekeeping.
  • In packages/core/lib/v3/types/public/api.ts, validation issues raised from SessionStartRequestSchema can be attached to incorrect paths because nested helpers use object-scoped ctx; this can mislead clients/UI about which fields actually failed.
  • In packages/core/lib/v3/modelProviderOptions.ts, error text interpolates unsanitized modelName, which can leak raw input into user-facing messages and reduce safety/consistency of error handling.
  • Pay close attention to packages/core/lib/v3/types/public/api.ts and packages/core/lib/v3/modelProviderOptions.ts - incorrect validation paths and unsanitized error-message interpolation are the main regression risks.
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/core/lib/v3/types/public/api.ts">

<violation number="1" location="packages/core/lib/v3/types/public/api.ts:524">
P2: Validation error paths are incorrect when triggered from `SessionStartRequestSchema`. The `ctx` is scoped to the `SessionStartRequest` object, but `addBedrockAuthIssues` and `getProviderConfigMismatchMessage` add issues with paths like `["providerConfig", "options", "region"]`. Since the data lives at `modelClientOptions.providerConfig.options.region`, error consumers won't be able to locate the offending field.

Consider prefixing the paths with `"modelClientOptions"` when calling from `SessionStartRequestSchema`, or having `validateProviderConfig` accept a path prefix parameter.</violation>
</file>

<file name="packages/core/lib/v3/modelProviderOptions.ts">

<violation number="1" location="packages/core/lib/v3/modelProviderOptions.ts:156">
P2: Custom agent: **Exception and error message sanitization**

User-facing error message reflects unsanitized raw `modelName` input via string interpolation.</violation>
</file>
Architecture diagram
sequenceDiagram
    participant User
    participant SDK as Stagehand SDK (V3)
    participant Lib as modelProviderOptions
    participant API as Stagehand API Client
    participant Hosted as Stagehand Hosted API

    Note over User,Hosted: Session Initialization Flow

    User->>SDK: new Stagehand({ model: { providerOptions, ... } })
    SDK->>Lib: normalizeClientOptionsForModel()
    Note right of Lib: NEW: Normalizes Bedrock/Vertex auth<br/>into runtime options
    Lib-->>SDK: normalizedOptions

    SDK->>API: init({ modelClientOptions: normalizedOptions })
    API->>Lib: toApiModelClientOptions()
    Note right of Lib: NEW: Serializes SDK options to<br/>API "providerConfig" wire format
    Lib-->>API: apiModelClientOptions
    
    API->>API: CHANGED: Store sessionModelConfig
    Note right of API: Retains provider-native auth for<br/>subsequent hosted actions

    alt NEW: Bedrock/Vertex with provider auth
        API->>Hosted: POST /session/start (body: { modelClientOptions })
        Note left of Hosted: Request sent WITHOUT x-model-api-key header
    else Standard API Key Auth
        API->>Hosted: POST /session/start (header: x-model-api-key)
    end
    Hosted-->>API: 200 OK (sessionId)

    Note over User,Hosted: Execution Flow (e.g., act / extract / observe)

    User->>SDK: act({ input })
    SDK->>API: act({ input })
    
    API->>API: NEW: ensureModelConfig()
    Note right of API: Injects stored sessionModelConfig if<br/>no per-call model override exists
    
    API->>Hosted: POST /act (body: { model: sessionModelConfig, ... })
    Note left of Hosted: Ensures provider-native auth persists<br/>on every hosted action
    Hosted-->>API: Action Results
    API-->>SDK: Results
    SDK-->>User: Results
Loading

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread packages/core/lib/v3/types/public/api.ts
Comment thread packages/core/lib/v3/modelProviderOptions.ts
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

2 issues found across 8 files (changes from recent commits).

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/core/lib/v3/llm/LLMProvider.ts">

<violation number="1" location="packages/core/lib/v3/llm/LLMProvider.ts:111">
P2: `isStringRecord({})` returns `true` due to vacuous truth on `Array.prototype.every`, so `headers: {}` alone will bypass the Vertex experimental-mode gate. Add an `Object.keys(value).length > 0` check (as you already do for `googleAuthOptions`) to ensure the headers object is non-empty.</violation>
</file>

<file name="packages/core/lib/v3/types/public/api.ts">

<violation number="1" location="packages/core/lib/v3/types/public/api.ts:1240">
P2: Inconsistent `model` field type: every other `model` field in this file accepts `z.union([ModelConfigSchema, z.string()])`, allowing users to pass a plain string model name (e.g. `'openai/gpt-5-nano'`). This field only accepts the object form, so callers who pass a string will get a validation error. It also lacks the `.meta()` description present on all sibling fields.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread packages/core/lib/v3/llm/LLMProvider.ts
Comment thread packages/core/lib/v3/types/public/api.ts Outdated
@shrey150
Copy link
Copy Markdown
Contributor Author

Re: cubics review summaries and (#2031 (review)) — addressed the valid inline findings in 47826d5a: SessionStartRequest providerConfig issues now use the correct modelClientOptions-prefixed paths, empty Vertex headers no longer satisfy the hosted-provider gate, and NavigateOptionsSchema.model now accepts the same string-or-object contract as the sibling schemas. I left the raw modelName error-message note as-is for the reason in the inline reply: it is a plain-text invalid-argument message, not an HTML/rendering sink, and keeping the quoted model identifier is useful for debugging invalid inputs.

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.

1 participant