
# Open Responses Provider

The [Open Responses](https://www.openresponses.org/) provider connects AI SDK
Core to language model servers that implement an Open Responses-compatible
`POST` endpoint. Open Responses is an open specification based on the OpenAI
Responses API.

Use `@ai-sdk/open-responses` for third-party or self-hosted endpoints that
implement this protocol, such as LM Studio. If you call OpenAI directly and
need OpenAI-specific provider options or built-in tools, use the
[`@ai-sdk/openai` provider](/providers/ai-sdk-providers/openai) instead.

## Setup

The Open Responses provider is available in the `@ai-sdk/open-responses` module. You can install it with

<InstallPackages packages="@ai-sdk/open-responses" />

## Provider Instance

Create an Open Responses provider instance using `createOpenResponses`:

```ts
import { createOpenResponses } from '@ai-sdk/open-responses';

const openResponses = createOpenResponses({
  name: 'lmstudio',
  url: 'http://localhost:1234/v1/responses',
});
```

The `name` and `url` options are required:

- **name** _string_

  Provider name. Used in the model's provider identifier and as the key for
  provider options.

- **url** _string_

  Full URL for the Open Responses API `POST` endpoint. Pass the endpoint URL,
  such as `http://localhost:1234/v1/responses`, not only its base URL.

You can use the following optional settings to customize the Open Responses provider instance:

- **apiKey** _string_

  API key that is sent as a bearer token in the `Authorization` header.

- **headers** _Record&lt;string,string&gt;_

  Custom headers to include in the requests.

- **fetch** _(input: RequestInfo, init?: RequestInit) => Promise&lt;Response&gt;_

  Custom [fetch](https://developer.mozilla.org/en-US/docs/Web/API/fetch) implementation.
  Defaults to the global `fetch` function.

- **strictResponseInput** _boolean_

  Serializes assistant history using strict OpenAI Responses input schemas.
  Assistant messages without an item ID are sent as easy input messages, while
  messages with a genuine provider item ID are sent as complete output items.
  Defaults to `false`.

### Endpoint Examples

For a local LM Studio server that does not require authentication:

```ts
import { createOpenResponses } from '@ai-sdk/open-responses';

const lmstudio = createOpenResponses({
  name: 'lmstudio',
  url: 'http://localhost:1234/v1/responses',
});
```

For the OpenAI Responses API:

```ts
import { createOpenResponses } from '@ai-sdk/open-responses';

const openAIResponses = createOpenResponses({
  name: 'openai',
  url: 'https://api.openai.com/v1/responses',
  apiKey: process.env.OPENAI_API_KEY,
});
```

You can use the same setup with another compatible service by changing the
`name`, `url`, authentication, and model ID.

## Language Models

The Open Responses provider instance is a function that you can invoke to create a language model:

```ts
const model = openResponses('your-model-id');
```

The model ID is passed to the endpoint unchanged.

You can use Open Responses models with the `generateText` and `streamText` functions,
and they support structured data generation with [`Output`](/docs/reference/ai-sdk-core/output)
(see [AI SDK Core](/docs/ai-sdk-core)).

### Generate Text

```ts
import { createOpenResponses } from '@ai-sdk/open-responses';
import { generateText } from 'ai';

const openResponses = createOpenResponses({
  name: 'lmstudio',
  url: 'http://localhost:1234/v1/responses',
});

const { text } = await generateText({
  model: openResponses('your-model-id'),
  prompt: 'Invent a new holiday and describe its traditions.',
});

console.log(text);
```

### Stream Text

```ts
import { createOpenResponses } from '@ai-sdk/open-responses';
import { streamText } from 'ai';

const openResponses = createOpenResponses({
  name: 'lmstudio',
  url: 'http://localhost:1234/v1/responses',
});

const result = streamText({
  model: openResponses('your-model-id'),
  prompt: 'Invent a new holiday and describe its traditions.',
});

for await (const textPart of result.textStream) {
  process.stdout.write(textPart);
}
```

## Reasoning and Provider Options

Use the top-level [`reasoning`](/docs/ai-sdk-core/reasoning) setting to control
reasoning effort. The provider maps supported values to the Open Responses
`reasoning.effort` field.

The provider also supports `reasoningEffort` and `reasoningSummary` through
`providerOptions`. The provider option key must match the `name` passed to
`createOpenResponses`:

```ts
import {
  createOpenResponses,
  type OpenResponsesLanguageModelOptions,
} from '@ai-sdk/open-responses';
import { generateText } from 'ai';

const lmstudio = createOpenResponses({
  name: 'lmstudio',
  url: 'http://localhost:1234/v1/responses',
});

const { text, reasoningText } = await generateText({
  model: lmstudio('your-reasoning-model-id'),
  reasoning: 'high',
  providerOptions: {
    lmstudio: {
      reasoningEffort: 'max',
      reasoningSummary: 'detailed',
    } satisfies OpenResponsesLanguageModelOptions,
  },
  prompt: 'Explain why the sky appears blue.',
});

console.log(reasoningText);
console.log(text);
```

`reasoningEffort` accepts any string and is passed through unchanged to the
endpoint's `reasoning.effort` field. Use it for endpoint-native values that are
not part of the top-level `reasoning` setting, such as `'max'`. When both are
set, `providerOptions` `reasoningEffort` takes precedence over the top-level
`reasoning` value.

`reasoningSummary` accepts `'auto'`, `'concise'`, or `'detailed'` and can be
combined with either reasoning effort setting. Reasoning support and accepted
effort values depend on the endpoint and model; unsupported values may be
rejected or ignored by the endpoint.

## File Inputs

The provider supports image and non-image file inputs in user messages. Images
are sent as `input_image` parts, while other media types, such as PDFs, are
sent as `input_file` parts.

You can provide a file as inline data:

```ts
import { createOpenResponses } from '@ai-sdk/open-responses';
import { readFileSync } from 'node:fs';
import { generateText } from 'ai';

const openResponses = createOpenResponses({
  name: 'lmstudio',
  url: 'http://localhost:1234/v1/responses',
});

const { text } = await generateText({
  model: openResponses('your-file-capable-model-id'),
  messages: [
    {
      role: 'user',
      content: [
        {
          type: 'text',
          text: 'Summarize this document.',
        },
        {
          type: 'file',
          data: readFileSync('./document.pdf'),
          mediaType: 'application/pdf',
          filename: 'document.pdf',
        },
      ],
    },
  ],
});

console.log(text);
```

You can also set `data` to a `URL`. The endpoint and model must support the
file's media type. Provider file references, such as OpenAI file IDs, and
file data in `{ type: 'text', text: '...' }` format are not supported by this
provider.

## Experimental Extensions

Open Responses implementations can add namespaced tools, items, and streaming
events. Use `Experimental_OpenResponsesExtension` to encode and decode an
implementation's extension wire formats. Unregistered provider tools are
omitted from requests with an `unsupported` warning.

This API is experimental and may change in a future release.

The AI SDK provider-tool ID uses dot notation (`acme.document_search`), while
Open Responses wire types use colon notation (`acme:document_search`). The
namespace in `id` must match the namespace in every registered wire type.

```ts
import {
  createOpenResponses,
  type Experimental_OpenResponsesExtension,
} from '@ai-sdk/open-responses';
import { generateText, tool } from 'ai';
import { z } from 'zod';

const documentSearchExtension: Experimental_OpenResponsesExtension = {
  id: 'acme.document_search',
  toolType: 'acme:document_search',
  itemTypes: ['acme:document_search_receipt'],
  encodeTool: ({ name, args }) => ({
    name,
    index: args.index as string,
  }),

  decodeItem: ({ item }) => [
    {
      type: 'tool-call',
      toolCallId: item.call_id as string,
      toolName: item.name as string,
      input: JSON.stringify(item.query),
      providerExecuted: true,
    },
    {
      type: 'tool-result',
      toolCallId: item.call_id as string,
      toolName: item.name as string,
      result: item.result!,
    },
  ],
};

const acme = createOpenResponses({
  name: 'acme',
  url: 'https://api.acme.example/v1/responses',
  experimental_extensions: [documentSearchExtension],
});

const documentSearch = tool({
  type: 'provider',
  id: 'acme.document_search',
  args: { index: 'documentation' },
  isProviderExecuted: true,
  inputSchema: z.object({ text: z.string() }),
  outputSchema: z.object({
    documents: z.array(
      z.object({
        id: z.string(),
        title: z.string(),
      }),
    ),
  }),
});

const result = await generateText({
  model: acme('your-model-id'),
  prompt: 'Find the extension documentation.',
  tools: { documentSearch },
});
```

Set `providerExecuted` on each decoded `tool-call` or `tool-input-start` part.
It can vary by item or event.

An extension codec can define:

- `encodeTool`: Encodes a provider tool. Returning `undefined` omits the tool
  with an `unsupported` warning. A `toolChoice` that selects the omitted tool is
  also omitted.
- `encodeToolChoice`: Encodes a specific `toolChoice`. The default is
  `{ type: toolType }`.
- `decodeItem`: Maps a completed item to AI SDK content parts. `mode` is either
  `'generate'` or `'stream'`.
- `encodeInputItem`: Encodes tool-call or tool-result history when the original
  wire item is unavailable. Returned items must include `id`, `status`, and a
  registered namespaced `type`.
- `decodeEvent`: Maps a streaming event to AI SDK stream parts. Its `state` map
  lasts for one response stream.

Tool, item, and event capabilities are independent. An item-only extension, for
example, defines `itemTypes` and `decodeItem` without `toolType` or `encodeTool`.
Capability fields must be provided in pairs.

Each decoded item adds an `open-responses.extension-replay` custom part that
stores the original JSON in provider metadata. Other decoded parts reference
that custom part instead of copying the item. Passing `result.response.messages`
to a later call replays the original item once, including opaque fields. This
also preserves items that decode only to response-only source parts.

The adapter validates only the extension discriminator fields. Validate other
item and event fields in the codec before returning AI SDK parts. The original
item is stored in provider metadata and may appear in persisted messages,
telemetry, logs, or UI payloads.

Extension callbacks cannot be serialized across workflow step boundaries.
Create the provider inside the workflow step. Serializing a model configured
with extensions throws a `SerializationError`.

## Limitations

- Stop sequences, `topK`, and `seed` are not supported and are ignored with warnings.
- The provider supports language models only. It does not provide embedding or
  image generation models.
- AI SDK function tools and registered Open Responses extensions are supported.
  Other provider-specific tools and options require a dedicated provider
  implementation.


## Navigation

- [AI Gateway](/providers/ai-sdk-providers/ai-gateway)
- [xAI Grok](/providers/ai-sdk-providers/xai)
- [OpenAI](/providers/ai-sdk-providers/openai)
- [Azure OpenAI](/providers/ai-sdk-providers/azure)
- [Anthropic](/providers/ai-sdk-providers/anthropic)
- [Open Responses](/providers/ai-sdk-providers/open-responses)
- [Claude Platform on AWS](/providers/ai-sdk-providers/anthropic-aws)
- [Amazon Bedrock](/providers/ai-sdk-providers/amazon-bedrock)
- [Groq](/providers/ai-sdk-providers/groq)
- [Fal](/providers/ai-sdk-providers/fal)
- [AssemblyAI](/providers/ai-sdk-providers/assemblyai)
- [GMI Cloud](/providers/ai-sdk-providers/gmicloud)
- [TypeSafe](/providers/ai-sdk-providers/typesafe-ai)
- [DeepInfra](/providers/ai-sdk-providers/deepinfra)
- [Deepgram](/providers/ai-sdk-providers/deepgram)
- [Black Forest Labs](/providers/ai-sdk-providers/black-forest-labs)
- [Gladia](/providers/ai-sdk-providers/gladia)
- [Google](/providers/ai-sdk-providers/google)
- [Hume](/providers/ai-sdk-providers/hume)
- [Google Vertex AI](/providers/ai-sdk-providers/google-vertex)
- [Rev.ai](/providers/ai-sdk-providers/revai)
- [Baseten](/providers/ai-sdk-providers/baseten)
- [Hugging Face](/providers/ai-sdk-providers/huggingface)
- [QuiverAI](/providers/ai-sdk-providers/quiverai)
- [Fish Audio](/providers/ai-sdk-providers/fish-audio)
- [Mistral AI](/providers/ai-sdk-providers/mistral)
- [Z.AI](/providers/ai-sdk-providers/zai)
- [Together.ai](/providers/ai-sdk-providers/togetherai)
- [Cohere](/providers/ai-sdk-providers/cohere)
- [Fireworks](/providers/ai-sdk-providers/fireworks)
- [Voyage AI](/providers/ai-sdk-providers/voyage)
- [DeepSeek](/providers/ai-sdk-providers/deepseek)
- [Moonshot AI](/providers/ai-sdk-providers/moonshotai)
- [Alibaba](/providers/ai-sdk-providers/alibaba)
- [MiniMax](/providers/ai-sdk-providers/minimax)
- [Cerebras](/providers/ai-sdk-providers/cerebras)
- [Replicate](/providers/ai-sdk-providers/replicate)
- [Prodia](/providers/ai-sdk-providers/prodia)
- [Perplexity](/providers/ai-sdk-providers/perplexity)
- [Luma](/providers/ai-sdk-providers/luma)
- [ByteDance](/providers/ai-sdk-providers/bytedance)
- [Kling AI](/providers/ai-sdk-providers/klingai)
- [ElevenLabs](/providers/ai-sdk-providers/elevenlabs)
- [Cartesia](/providers/ai-sdk-providers/cartesia)


[Full Sitemap](/sitemap.md)
