Skip to content

feat(core): support OpenAI Chat Completions via openaiEndpointFormat#2347

Open
miguelg719 wants to merge 3 commits into
mainfrom
miguelgonzalez/openai-chat-api-mode
Open

feat(core): support OpenAI Chat Completions via openaiEndpointFormat#2347
miguelg719 wants to merge 3 commits into
mainfrom
miguelgonzalez/openai-chat-api-mode

Conversation

@miguelg719

@miguelg719 miguelg719 commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • add openaiEndpointFormat to public model configuration
  • select OpenAI Chat Completions when openaiEndpointFormat is chat
  • preserve Responses API as the default
  • omit the Responses-only store option for Chat providers, including finalization calls
  • add a patch changeset

Usage

const stagehand = new Stagehand({
  model: {
    modelName: "openai/databricks-claude-opus-4-6",
    apiKey: process.env.DATABRICKS_TOKEN,
    baseURL: "https://example.databricks.com/serving-endpoints",
    openaiEndpointFormat: "chat",
  },
});

The option names the wire format used against the OpenAI-compatible endpoint at baseURL — deliberately not apiMode (too generic) or openaiEndpoint (reads like it holds a URL, and sits right next to baseURL).

Databricks verification

  • basic Chat Completions request: 200
  • request with store: false reproduced the 400: extra inputs are not permitted
  • two-turn tool call and tool-result replay without store: 200 on both turns

Testing

  • focused llm-provider and agent suites: 19 passed
  • TypeScript typecheck
  • ESLint on touched TypeScript files
  • Prettier check on touched files

@changeset-bot

changeset-bot Bot commented Jul 10, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7562df8

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

This PR includes changesets to release 3 packages
Name Type
@browserbasehq/stagehand Patch
@browserbasehq/stagehand-evals Patch
@browserbasehq/stagehand-server-v3 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

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 4 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Re-trigger cubic

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

All reported issues were addressed across 8 files

Confidence score: 5/5

  • Safe to merge after the addressed issues were fixed.
Architecture diagram
sequenceDiagram
    participant Client as Agent / Test
    participant AgentHandler as V3AgentHandler
    participant BuildOpts as buildAgentProviderOptions()
    participant LLMProv as LLMProvider
    participant GetModel as getAISDKLanguageModel()
    participant OpenAISDK as OpenAI SDK
    participant ProviderOpts as Provider Options

    Note over Client,OpenAISDK: NEW: OpenAI Chat API mode support

    Client->>AgentHandler: execute(instruction, options)
    AgentHandler->>AgentHandler: wrap model with clientOptions (apiMode, baseURL, etc.)

    Note over AgentHandler,LLMProv: Model creation
    AgentHandler->>LLMProv: getClient(modelId, clientOptions)
    LLMProv->>GetModel: getAISDKLanguageModel(subProvider, subModelName, clientOptions)

    alt apiMode == "chat" AND subProvider == "openai"
        GetModel->>GetModel: Extract apiMode, strip from clientOptions
        GetModel->>OpenAISDK: createOpenAI() or openai
        GetModel->>OpenAISDK: provider.chat(subModelName)
        OpenAISDK-->>GetModel: language model (provider = "openai.chat")
    else default (responses or other provider)
        GetModel->>GetModel: use toAISDKClientOptions, find creator
        GetModel->>OpenAISDK: provider.responses() or other method
        OpenAISDK-->>GetModel: language model (provider = "openai.responses")
    end

    GetModel-->>LLMProv: LanguageModelV2
    LLMProv-->>AgentHandler: LLMClient with model

    Note over AgentHandler,ProviderOpts: Agent execution with provider options
    AgentHandler->>BuildOpts: buildAgentProviderOptions(modelId, provider, thinkingEffort)
    BuildOpts->>ProviderOpts: openAIStoreProviderOptions(provider)
    
    alt provider == "openai.responses"
        ProviderOpts-->>BuildOpts: { openai: { store: false } }
    else provider == "openai.chat"
        ProviderOpts-->>BuildOpts: {} (no store option)
    end

    BuildOpts-->>AgentHandler: providerOptions (including google, anthropic, openai)

    AgentHandler->>OpenAISDK: generateText({ model, messages, providerOptions })
    alt Responses API
        OpenAISDK-->>AgentHandler: response with store: false applied
    else Chat API
        OpenAISDK-->>AgentHandler: response (store option omitted)
    end

    AgentHandler-->>Client: execute result
Loading

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread .changeset/openai-chat-api-mode.md
Comment thread packages/core/lib/v3/agent/utils/handleDoneToolCall.ts
The option only applies to OpenAI-compatible providers and selects the
wire format ('responses' | 'chat'), not a URL. The generic 'apiMode'
name gave no hint of either, and sitting next to 'baseURL' in the same
options object invited confusion with an endpoint address.
@miguelg719 miguelg719 changed the title feat(core): support OpenAI chat API mode feat(core): support OpenAI Chat Completions via openaiEndpointFormat Jul 16, 2026
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