![Thomas Steiner](https://web.dev/images/authors/thomassteiner.jpg) Thomas Steiner [GitHub](https://github.com/tomayac) [LinkedIn](https://www.linkedin.com/in/thomassteinerlinkedin) [Mastodon](https://toot.cafe/@tomayac) [Bluesky](https://bsky.app/profile/tomayac.com) [Homepage](https://blog.tomayac.com/)

<br />


Published: July 16, 2026

<br />

The Vercel [AI SDK](https://ai-sdk.dev/) is a provider-agnostic TypeScript
toolkit designed to help you build AI-powered applications and agents using
popular UI frameworks like Next.js, React, Svelte, Vue, Angular, and runtimes
like Node.js. While the majority of providers are cloud-based, this first guide
of a two parts series focuses on a community provider called [Browser
AI](https://ai-sdk.dev/providers/community-providers/browser-ai) created by
[Jakob Hoeg Mørk](https://www.jakobhoeg.dev/) (who was
[funded by Google](https://opencollective.com/chrome/projects/web-ai-fund/expenses/266878)).
Browser AI lets you use the [Prompt
API](https://developer.chrome.com/docs/ai/prompt-api) with Vercel's AI SDK. Part
two of the series then explains how to add a graphical user interface to your AI
application.

## Install the library

The [`@browser-ai/core`](https://www.npmjs.com/package/@browser-ai/core)
package is the AI SDK provider for the Prompt API. You can install it with npm.
The underlying Vercel AI SDK is automatically installed by the package as a peer
dependency.

```bash
npm install @browser-ai/core
```

## Basic usage

To use the provider:

1. Import the `browserAI` constructor from the `@browser-ai/core` package.
2. Import the [`generateText()`](https://ai-sdk.dev/docs/reference/ai-sdk-core/generate-text) or the [`streamText()`](https://ai-sdk.dev/docs/reference/ai-sdk-core/stream-text) functions from the Vercel AI SDK. Both functions generate text and call tools for a given prompt using a language model:

- The `generateText()` function is non-streaming and ideal for short outputs or for outputs where you can only continue once the whole output is received.
- The `streamText()` function streams text generations from a language model. You can use this function for interactive use cases such as chatbots and other real-time applications.

To create a model instance:

1. Call `browserAI()`. Note: As a best practice, always check the model's
   `availability()`, which allows you to use a fallback (see
   [Hybrid usage](https://developer.chrome.com/blog/prompt-api-with-vercel-ai.md.txt#hybrid-usage)) when the model is `'unavailable'`, or to show a progress update when the
   model is `'downloadable'` or `'downloading'`.

2. You can then call `generateText()` or `streamText()`. Refer to the
   Vercel AI SDK documentation for the full list of parameters, for example,
   rather than pass a `prompt` directly as in the following code sample, you
   can also pass a more complex `messages` object for multi shot prompting, or
   pass a `system` prompt.

> [!WARNING]
> **Warning:** Not all options exposed by the Vercel AI SDK are supported by the underlying `LanguageModel` interface from the Prompt API that the `@browser-ai/core` package calls into. For example, `topP` isn't configurable and you'll be alerted of the fact through a Console warning.

```javascript
import { browserAI } from '@browser-ai/core';
import { generateText, streamText } from 'ai';

(async () => {
  const model = browserAI();
  const availability = await model.availability();

  if (availability === 'unavailable') {
    console.log('Your browser cannot run the built-in AI model.');
    return;
  }

  if (availability === 'downloadable' || availability === 'downloading') {
    await model.createSessionWithProgress((progress) => {
      console.log(`Download progress: ${Math.round(progress * 100)}%`);
    });
  }

  // Non-streaming text generation.
  const { text } = await generateText({
    model,
    prompt: 'Tell me a short joke',
  });
  console.log(text);

  // Streaming text generation.
  const result = streamText({
    model,
    prompt: 'Tell me a long joke',
  });

  for await (const chunk of result.textStream) {
    console.log(chunk);
  }
})();
```

## Multimodal usage

The `@browser-ai/core` package supports multimodal input using a `type: 'file'`
object in the `messages` array's content objects.

`content` **object fields** (`type: 'file'`)

| **Field** | **Accepted value types** | **Description** |
|---|---|---|
| <br /> ``` type ``` <br /> | <br /> ``` 'file' ``` <br /> | Marks this content object as a file input |
| <br /> ``` data ``` <br /> | <br /> ``` string | Uint8Array | Buffer | ArrayBuffer | URL ``` <br /> | The file content, in one of several supported formats |

**When `data` is a `string`, it must be one of:**

| **Format** | **Description** |
|---|---|
| Base64-encoded content | Raw file bytes encoded as base64 |
| Base64 data URL | e.g. `data:image/png;base64,...` |
| http(s) URL | A remote URL the file will be fetched from |

See the following code snippet for an example:

```javascript
import { streamText } from 'ai';
import { browserAI } from '@browser-ai/core';

const base64ImageData = await getBase64ImageData();
const audioData = await getAudioBuffer();

const result = streamText({
  model: browserAI(),
  messages: [
    {
      role: 'user',
      content: [
        { type: 'text', text: "What's in this image?" },
        { type: 'file', mediaType: 'image/png', data: base64ImageData },
      ],
    },
    {
      role: 'user',
      content: [
        { type: 'text', text: 'Transcribe this audio file!' },
        { type: 'file', mediaType: 'audio/mp3', data: audioData },
      ],
    },
  ],
});

for await (const chunk of result.textStream) {
  console.log(chunk);
}
```

## Structured output

The Vercel AI SDK supports structured output through [zod](https://zod.dev/), a
TypeScript-first schema validation with static type inference. Check zod's
[Defining schemas](https://zod.dev/api) documentation for details.

To request a JSON object matching your schema, pass `output: Output.object({
schema })` to `generateText()` or `streamText()`:

- `generateText()` with `Output.object()` returns the final JSON object in the `output` field once generation is complete.
- `streamText()` with `Output.object()` provides a `partialOutputStream` async iterable where each intermediate result is guaranteed to parse correctly as JSON. For example, if your schema enforces an array of two numbers, you would receive `[]` as the first partial result, `[123]` as the second, and `[123, 456]` as the final result.

```javascript
import { browserAI } from '@browser-ai/core';
import { generateText, streamText, Output } from 'ai';
import z from 'zod';

const model = browserAI();

const schema = z.object({
  recipe: z.object({
    name: z.string(),
    ingredients: z.array(z.object({ name: z.string(), amount: z.string() })),
    steps: z.array(z.string()),
  }),
});

const prompt = 'Generate a lasagna recipe.';

// Non-streaming object generation.
const { output } = await generateText({
  model,
  output: Output.object({ schema }),
  prompt,
});

console.log(output);

// Streaming object generation.
const { partialOutputStream } = streamText({
  model,
  output: Output.object({ schema }),
  prompt,
});

for await (const partialObject of partialOutputStream) {
  console.log(partialObject);
}
```

## Hybrid usage

Where Vercel's AI SDK really shines is hybrid usage. It provides a higher level
abstraction layer on top of the underlying providers' lower level
implementations. When you use the Prompt API as the provider, you create a
`model` by calling the `browserAI` constructor.

```javascript
import { browserAI } from '@browser-ai/core';

const model = browserAI();
```

To use a different provider, for example, the
[Google Generative AI provider](https://ai-sdk.dev/providers/ai-sdk-providers/google-generative-ai),
you need to do the following:

1. Install the selected provider.

   ```bash
   npm install @ai-sdk/google
   ```
2. Instantiate the `model` using the provider's constructor, which, for
   cloud providers like Google Generative AI, typically involves passing an
   API key. In the case of the Google Generative AI provider, you can also
   pass a cloud model identifier, for example, `'gemini-2.5-flash'`. All the
   rest of the code, like your calls to `streamText()`, stay exactly the same.

   ```javascript
   import { createGoogleGenerativeAI } from '@ai-sdk/google';

   const API_KEY = 'YOUR_GOOGLE_AI_API_KEY';

   const google = createGoogleGenerativeAI({ apiKey: API_KEY });
   const model = google('gemini-2.5-flash');
   ```

### Cloud fallback

A classic hybrid use case is to use the Prompt API when it's available and to
fall back to a cloud provider in other circumstances. To check if the Prompt API
is available, the `@browser-ai/core` package provides the
`doesBrowserSupportBuiltInAI()` function. You can use this function to
dynamically instantiate the `model` as either a cloud-based model or a built-in
model.

```javascript
import { doesBrowserSupportBuiltInAI } from '@browser-ai/core';

const API_KEY = 'YOUR_GOOGLE_AI_API_KEY';

const model = await (async () => {
  if (doesBrowserSupportBuiltInAI()) {
    const { browserAI } = await import('@browser-ai/core');
    return browserAI();
  }
  const { createGoogleGenerativeAI } = await import('@ai-sdk/google');
  const google = createGoogleGenerativeAI({ apiKey: API_KEY });
  return google('gemini-2.5-flash');
})();
```

### Built-in fallback

Another hybrid use case is to preferably use a cloud provider when online, but
to fall back to the built-in provider if the Prompt API is supported.

```javascript
import { doesBrowserSupportBuiltInAI } from '@browser-ai/core';

const API_KEY = 'YOUR_GOOGLE_AI_API_KEY';

let model;

const switchProvider = async (forceCloud = false) => {
  model = await (async () => {
    if (navigator.onLine || forceCloud) {
      const { createGoogleGenerativeAI } = await import('@ai-sdk/google');
      const google = createGoogleGenerativeAI({ apiKey: API_KEY });
      return google('gemini-2.5-flash');
    }
    const { browserAI } = await import('@browser-ai/core');
    return browserAI();
  })();
};

if (doesBrowserSupportBuiltInAI()) {
  window.addEventListener('online', switchProvider);
  window.addEventListener('offline', switchProvider);
}
await switchProvider(true);
```

## Demo

The
[live demo](https://googlechrome.github.io/samples/vercel-ai-sdk-built-in-ai/dist/index.html)
lets you try both providers side by side. Select **Cloud API (Gemini 2.5
Flash)** or **Built-in AI** from the radio buttons, hit **Run** , and watch the
page fill in four sections in sequence: a short joke generated all at once with
`generateText()`, a long joke streamed token by token with `streamText()`, a
lasagna recipe returned as a complete JSON object, and then that same recipe
streamed as incrementally valid JSON using `partialOutputStream`. If you select
Built-in AI and your browser hasn't downloaded the model yet, a progress
indicator appears before the demos begin.

![Vercel AI Demo](https://developer.chrome.com/static/blog/prompt-api-with-vercel-ai/image/image1.png)

## Next step

Now that you know how to use the Prompt API with the Vercel AI SDK, the next
step is to make use of the [AI SDK
UI](https://ai-sdk.dev/docs/ai-sdk-ui/overview) and [AI
Elements](https://ai-sdk.dev/elements) to add a graphical user interface to your
app.

AI SDK UI is designed to help you build interactive chat, completion, and
assistant applications with ease. It is a framework-agnostic toolkit,
streamlining the integration of advanced AI functionalities into your
applications.

AI Elements is a component library and custom registry to help you build
AI-native applications faster. It provides prebuilt components like
conversations, messages, and more.

Read
[Use the Vercel AI SDK UI and AI Elements with the Prompt API](https://developer.chrome.com/blog/prompt-ui-ai-elements-with-vercel-ai.md.txt),
to learn how to add a GUI to your app.