Here’s a full breakdown of the AI SDK data stream protocol, which is used by tools, frontends (like useChat), and custom backends—even in non-JS environments:
When you stream from the backend (e.g., your Python/FastAPI server), you must use the Data Stream Protocol. Make sure to set the HTTP header:
x-vercel-ai-data-stream: v1
Then emit individual lines as follows—each line starts with a part-type identifier and JSON payload, terminated by \n:
| Part | Identifier | Purpose | 
|---|---|---|
| Text | 0: | Streamed text fragments (appends to chat) | 
| Reasoning | g: | The model's internal reasoning | 
| Redacted reasoning | i: | Reasoning redacted for UI display | 
| Reasoning signature | j: | Cryptographic signature | 
| Source | h: | Citation to sources or metadata | 
| File | k: | Base64-encoded binary data with MIME | 
| Data | 2: | JSON objects appended to dataarray inuseChat | 
| Message annotations | 8: | UI metadata annotations | 
| Error | 3: | Errors during generation or tools | 
| Tool call start | b: | Initiates a streaming tool call | 
| Tool call delta | c: | Deltas of tool arguments during streaming | 
| Tool call | 9: | Full tool call invocation | 
| Tool result | a: | Tool execution result | 
| Step start | f: | Used for multi-step flows | 
| Step finish | e: | Indicates step completion | 
| Message finish | d: | End of entire message | 
Every part must follow the format:
<identifier>:<JSON>\n
Example for a tool call:
b:{"toolCallId":"call-1","toolName":"myTool"}\n
c:{"toolCallId":"call-1","argsTextDelta":"..."}\n
9:{"toolCallId":"call-1","toolName":"myTool","args":{...}}\n
a:{"toolCallId":"call-1","result":{...}}\n
This protocol aligns with the official spec ([sdk.vercel.ai][1], [sdk.vercel.ai][2], [aihero.dev][3], [sdk.vercel.ai][4], [sdk.vercel.ai][5], [reddit.com][6]).
Even if your back end is Python, Go, etc., you can implement this protocol by:
- Set header: x-vercel-ai-data-stream: v1
- Stream part-by-part: emit lines per the protocol
- Leverage SDK front-end: useChat({ api: '/your/stream-endpoint' })
The Vercel AI UI client understands these parts and handles rendering automatically ([reddit.com][7]).
Using useChat, the client:
- Appends text from 0:parts to the assistant message
- Collects structured data from 2:intochat.data
- Manages tool invocations via b:,9:,a:parts
- Tracks reasoning, files, annotations, etc., automatically
References:
- https://sdk.vercel.ai/docs/ai-sdk-ui/stream-protocol?utm_source=chatgpt.com "AI SDK UI: Stream Protocols"
- https://sdk.vercel.ai/docs/ai-sdk-ui/streaming-data?utm_source=chatgpt.com "AI SDK UI: Streaming Custom Data"
- https://www.aihero.dev/streaming-text-with-vercel-ai-sdk?utm_source=chatgpt.com "Streaming Text With Vercel's AI SDK"
- https://sdk.vercel.ai/docs/ai-sdk-core/generating-text?utm_source=chatgpt.com "AI SDK Core: Generating Text"
- https://sdk.vercel.ai/docs/ai-sdk-core/tools-and-tool-calling?utm_source=chatgpt.com "AI SDK Core: Tool Calling"
- https://www.reddit.com/r/nextjs/comments/1dz2vqj?utm_source=chatgpt.com "How to intercept text stream from server action using Vercel AI SDK"
- https://www.reddit.com/r/nextjs/comments/1ibeu6g?utm_source=chatgpt.com "Streaming with the AI SDK from a custom backend API"