
# Stream Protocols

AI SDK UI functions such as `useChat` and `useCompletion` support both text streams and data streams.
The stream protocol defines how the data is streamed to the frontend on top of the HTTP protocol.

This page describes both protocols and how to use them in the backend and frontend.

You can use this information to develop custom backends and frontends for your use case, e.g.,
to provide compatible API endpoints that are implemented in a different language such as Python.

For instance, here's an example using [FastAPI](https://github.com/vercel/ai/tree/main/examples/next-fastapi) as a backend.

## Text Stream Protocol

A text stream contains chunks in plain text, that are streamed to the frontend.
Each chunk is then appended together to form a full text response.

Text streams are supported by `useChat`, `useCompletion`, and `useObject`.
When you use `useChat` or `useCompletion`, you need to enable text streaming
by setting the `streamProtocol` options to `text`.

You can generate text streams with `streamText` in the backend.
When you call `toTextStreamResponse()` on the result object,
a streaming HTTP response is returned.

<Note>
  Text streams only support basic text data. If you need to stream other types
  of data such as tool calls, use data streams.
</Note>

### Text Stream Example

Here is a Next.js example that uses the text stream protocol:

```tsx filename='app/page.tsx' highlight="7"
'use client';

import { useCompletion } from '@ai-sdk/react';

export default function Page() {
  const { completion, input, handleInputChange, handleSubmit } = useCompletion({
    streamProtocol: 'text',
  });

  return (
    <form onSubmit={handleSubmit}>
      <input name="prompt" value={input} onChange={handleInputChange} />
      <button type="submit">Submit</button>
      <div>{completion}</div>
    </form>
  );
}
```

```ts filename='app/api/completion/route.ts' highlight="15"
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';

// Allow streaming responses up to 30 seconds
export const maxDuration = 30;

export async function POST(req: Request) {
  const { prompt }: { prompt: string } = await req.json();

  const result = streamText({
    model: openai('gpt-4o'),
    prompt,
  });

  return result.toTextStreamResponse();
}
```

## Data Stream Protocol

A data stream follows a special protocol that the AI SDK provides to send information to the frontend.

Each stream part has the format `TYPE_ID:CONTENT_JSON\n`.

<MDXImage
  srcLight="/images/data-stream-protocol.png"
  srcDark="/images/data-stream-protocol.png"
  width={3200}
  height={1712}
/>

<Note>
  When you provide data streams from a custom backend, you need to set the
  `x-vercel-ai-data-stream` header to `v1`.
</Note>

The following stream parts are currently supported:

### Text Part

The text parts are appended to the message as they are received.

Format: `0:string\n`

Example: `0:"example"\n`

<MDXImage
  srcLight="/images/text-part.png"
  srcDark="/images/text-part.png"
  width={3200}
  height={1148}
/>

### Reasoning Part

The reasoning parts are appended to the message as they are received. The reasoning part is available through `reasoning`.

Format: `g:string\n`

Example: `g:"I will open the conversation with witty banter."\n`

### Redacted Reasoning Part

The redacted reasoning parts contain reasoning data that has been redacted. This is available through `redacted_reasoning`.

Format: `i:{"data": string}\n`

Example: `i:{"data": "This reasoning has been redacted for security purposes."}\n`

### Reasoning Signature Part

The reasoning signature parts contain a signature associated with the reasoning. This is available through `reasoning_signature`.

Format: `j:{"signature": string}\n`

Example: `j:{"signature": "abc123xyz"}\n`

### Source Part

The source parts are appended to the message as they are received. The source part is available through `source`.

Format: `h:Source\n`

Example: `h:{"sourceType":"url","id":"source-id","url":"https://example.com","title":"Example"}\n`

### File Part

The file parts contain binary data encoded as base64 strings along with their MIME type. The file part is available through `file`.

Format: `k:{data:string; mimeType:string}\n`

Example: `k:{"data":"base64EncodedData","mimeType":"image/png"}\n`

### Data Part

The data parts are parsed as JSON and appended to the data array as they are received. The data is available through `data`.

Format: `2:Array<JSONValue>\n`

Example: `2:[{"key":"object1"},{"anotherKey":"object2"}]\n`

<MDXImage
  srcLight="/images/data-part.png"
  srcDark="/images/data-part.png"
  width={3200}
  height={1148}
/>

### Message Annotation Part

The message annotation parts are appended to the message as they are received. The annotation part is available through `annotations`.

Format: `8:Array<JSONValue>\n`

Example: `8:[{"id":"message-123","other":"annotation"}]\n`

### Error Part

The error parts are appended to the message as they are received.

Format: `3:string\n`

Example: `3:"error message"\n`

<MDXImage
  srcLight="/images/error-part.png"
  srcDark="/images/error-part.png"
  width={3200}
  height={1148}
/>

### Tool Call Streaming Start Part

A part indicating the start of a streaming tool call. This part needs to be sent before any tool call delta for that tool call. Tool call streaming is optional, you can use tool call and tool result parts without it.

Format: `b:{toolCallId:string; toolName:string}\n`

Example: `b:{"toolCallId":"call-456","toolName":"streaming-tool"}\n`

<MDXImage
  srcLight="/images/tool-call-streaming-start-part.png"
  srcDark="/images/tool-call-streaming-start-part.png"
  width={3200}
  height={1148}
/>

### Tool Call Delta Part

A part representing a delta update for a streaming tool call.

Format: `c:{toolCallId:string; argsTextDelta:string}\n`

Example: `c:{"toolCallId":"call-456","argsTextDelta":"partial arg"}\n`

<MDXImage
  srcLight="/images/tool-call-delta-part.png"
  srcDark="/images/tool-call-delta-part.png"
  width={3200}
  height={1148}
/>

### Tool Call Part

A part representing a tool call. When there are streamed tool calls, the tool call part needs to come after the tool call streaming is finished.

Format: `9:{toolCallId:string; toolName:string; args:object}\n`

Example: `9:{"toolCallId":"call-123","toolName":"my-tool","args":{"some":"argument"}}\n`

<MDXImage
  srcLight="/images/tool-call-part.png"
  srcDark="/images/tool-call-part.png"
  width={3200}
  height={1148}
/>

### Tool Result Part

A part representing a tool result. The result part needs to be sent after the tool call part for that tool call.

Format: `a:{toolCallId:string; result:object}\n`

Example: `a:{"toolCallId":"call-123","result":"tool output"}\n`

<MDXImage
  srcLight="/images/tool-result-part.png"
  srcDark="/images/tool-result-part.png"
  width={3200}
  height={1148}
/>

### Start Step Part

A part indicating the start of a step.

It includes the following metadata:

- `messageId` to indicate the id of the message that this step belongs to.

Format: `f:{messageId:string}\n`

Example: `f:{"messageId":"step_123"}\n`

### Finish Step Part

A part indicating that a step (i.e., one LLM API call in the backend) has been completed.

This part is necessary to correctly process multiple stitched assistant calls, e.g. when calling tools in the backend, and using steps in `useChat` at the same time.

It includes the following metadata:

- [`FinishReason`](/docs/reference/ai-sdk-ui/use-chat#on-finish-finish-reason)
- [`Usage`](/docs/reference/ai-sdk-ui/use-chat#on-finish-usage) for that step.
- `isContinued` to indicate if the step text will be continued in the next step.

The finish step part needs to come at the end of a step.

Format: `e:{finishReason:'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other' | 'unknown';usage:{promptTokens:number; completionTokens:number;},isContinued:boolean}\n`

Example: `e:{"finishReason":"stop","usage":{"promptTokens":10,"completionTokens":20},"isContinued":false}\n`

### Finish Message Part

A part indicating the completion of a message with additional metadata, such as [`FinishReason`](/docs/reference/ai-sdk-ui/use-chat#on-finish-finish-reason) and [`Usage`](/docs/reference/ai-sdk-ui/use-chat#on-finish-usage). This part needs to be the last part in the stream.

Format: `d:{finishReason:'stop' | 'length' | 'content-filter' | 'tool-calls' | 'error' | 'other' | 'unknown';usage:{promptTokens:number; completionTokens:number;}}\n`

Example: `d:{"finishReason":"stop","usage":{"promptTokens":10,"completionTokens":20}}\n`

<MDXImage
  srcLight="/images/finish-message-part.png"
  srcDark="/images/finish-message-part.png"
  width={3200}
  height={1148}
/>

The data stream protocol is supported
by `useChat` and `useCompletion` on the frontend and used by default.
`useCompletion` only supports the `text` and `data` stream parts.

On the backend, you can use `toDataStreamResponse()` from the `streamText` result object to return a streaming HTTP response.

### Data Stream Example

Here is a Next.js example that uses the data stream protocol:

```tsx filename='app/page.tsx' highlight="7"
'use client';

import { useCompletion } from '@ai-sdk/react';

export default function Page() {
  const { completion, input, handleInputChange, handleSubmit } = useCompletion({
    streamProtocol: 'data', // optional, this is the default
  });

  return (
    <form onSubmit={handleSubmit}>
      <input name="prompt" value={input} onChange={handleInputChange} />
      <button type="submit">Submit</button>
      <div>{completion}</div>
    </form>
  );
}
```

```ts filename='app/api/completion/route.ts' highlight="15"
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';

// Allow streaming responses up to 30 seconds
export const maxDuration = 30;

export async function POST(req: Request) {
  const { prompt }: { prompt: string } = await req.json();

  const result = streamText({
    model: openai('gpt-4o'),
    prompt,
  });

  return result.toDataStreamResponse();
}
```


## Navigation

- [Overview](/v4/docs/ai-sdk-ui/overview)
- [Chatbot](/v4/docs/ai-sdk-ui/chatbot)
- [Chatbot Message Persistence](/v4/docs/ai-sdk-ui/chatbot-message-persistence)
- [Chatbot Tool Usage](/v4/docs/ai-sdk-ui/chatbot-tool-usage)
- [Generative User Interfaces](/v4/docs/ai-sdk-ui/generative-user-interfaces)
- [Completion](/v4/docs/ai-sdk-ui/completion)
- [Object Generation](/v4/docs/ai-sdk-ui/object-generation)
- [OpenAI Assistants](/v4/docs/ai-sdk-ui/openai-assistants)
- [Streaming Custom Data](/v4/docs/ai-sdk-ui/streaming-data)
- [Error Handling](/v4/docs/ai-sdk-ui/error-handling)
- [Smooth streaming japanese text](/v4/docs/ai-sdk-ui/smooth-stream-japanese)
- [Smooth streaming chinese text](/v4/docs/ai-sdk-ui/smooth-stream-chinese)
- [Stream Protocols](/v4/docs/ai-sdk-ui/stream-protocol)


[Full Sitemap](/sitemap.md)
