Skip to main content

UI message chunks

The UI message stream is a sequence of JSON chunks sent as Server-Sent Events. Each chunk is an ai.UIMessageChunk, a map[string]interface{} with a type key. The chunk set matches the TypeScript AI SDK UIMessageChunk union, so useChat from @ai-sdk/react reads the stream without an adapter.

Functions that produce the stream are in Stream transport helpers. Functions that fold chunks back into messages are in UI messages.

All field names are camelCase. A field marked optional is omitted when it has no value. Several chunks accept providerMetadata (a map[string]interface{} keyed by provider name); it appears on a chunk when the provider returned metadata for it.

Wire format​

Every chunk is one SSE event, data: <json>\n\n. After the last chunk the stream writes data: [DONE]\n\n. The response carries the headers from ai.UIMessageStreamHeaders(): Content-Type: text/event-stream, Cache-Control: no-cache, Connection: keep-alive, X-Vercel-AI-UI-Message-Stream: v1 and X-Accel-Buffering: no.

Message lifecycle​

A stream for one assistant message looks like this:

start
start-step
text-start, text-delta..., text-end
tool-input-start, tool-input-delta..., tool-input-available
tool-output-available
finish-step
finish

A tool-calling run repeats the start-step to finish-step block for each model step.

start​

Begins the message. Sent once, when SendStart is not false.

FieldTypeDescription
messageIdstringOptional. ID of the assistant message. Set from ResponseMessageID or GenerateMessageID.
messageMetadataobjectOptional. Result of the MessageMetadata callback for the start part.

finish​

Ends the message. Sent once, when SendFinish is not false.

FieldTypeDescription
finishReasonstringWhy generation ended: stop, length, content-filter, tool-calls, user-approval, error or other.
messageMetadataobjectOptional. Result of the MessageMetadata callback for the finish part.

abort​

The stream was aborted.

FieldTypeDescription
reasonstringOptional. Why the stream was aborted.

message-metadata​

Updates the message metadata mid-stream. Emitted when the MessageMetadata callback returns a value for a part other than start and finish. A client merges the value into the message metadata.

FieldTypeDescription
messageMetadataobjectThe metadata to merge.

start-step​

Begins one model call. Carries no fields. A client adds a step-start part to the message.

finish-step​

Ends one model call. Carries no fields.

reset-step​

Discards the parts added since the last start-step because the step is being retried. A client truncates the message to the last step-start part and clears in-flight text, reasoning and tool state. The Go UI stream does not emit this chunk itself. ai.ReadUIMessages and the workflow chat transport client handle it, so a stream from a retrying workflow agent reads correctly.

error​

A stream error.

FieldTypeDescription
errorTextstringError message. UIMessageStreamOptions.OnError and UIMessageStreamResultOptions.OnError map the Go error to this text. The default text is "An error occurred."

Text​

Text is streamed as a start, one or more deltas and an end, all sharing an id.

TypeFields
text-startid (string), providerMetadata (optional)
text-deltaid (string), delta (string), providerMetadata (optional)
text-endid (string), providerMetadata (optional)

Reasoning​

Reasoning chunks have the same shape as text chunks. They are sent only when SendReasoning is not false (the default is true).

TypeFields
reasoning-startid (string), providerMetadata (optional)
reasoning-deltaid (string), delta (string), providerMetadata (optional)
reasoning-endid (string), providerMetadata (optional)

Sources, files and custom content​

source-url​

Sent only when SendSources is true (the default is false).

FieldTypeDescription
sourceIdstringSource ID.
urlstringSource URL.
titlestringOptional. Source title.
providerMetadataobjectOptional.

source-document​

Sent only when SendSources is true.

FieldTypeDescription
sourceIdstringSource ID.
mediaTypestringIANA media type of the document.
titlestringOptional. Document title.
filenamestringOptional. File name.
providerMetadataobjectOptional.

file​

A model-generated file.

FieldTypeDescription
mediaTypestringIANA media type.
urlstringThe file URL, or a data: URL when the provider returned inline bytes.
providerMetadataobjectOptional.

reasoning-file​

A file generated as part of reasoning. Same fields as file. Sent only when SendReasoning is not false.

custom​

Provider-specific content that has no standard part type.

FieldTypeDescription
kindstringProvider-defined content kind.
providerMetadataobjectOptional.

Tool calls​

tool-input-start​

The model started writing a tool call. Sent when the provider streams tool input.

FieldTypeDescription
toolCallIdstringTool call ID.
toolNamestringTool name.
providerExecutedboolOptional. True when the provider runs the tool.
dynamicboolOptional. True for dynamic tools.
titlestringOptional. Tool title.
toolMetadataobjectOptional. Tool metadata from types.Tool.Metadata.
providerMetadataobjectOptional.

tool-input-delta​

A piece of the raw JSON tool input.

FieldTypeDescription
toolCallIdstringTool call ID.
inputTextDeltastringThe next piece of input text.

tool-input-available​

The complete, parsed tool input. This chunk is sent even when the provider did not stream the input.

FieldTypeDescription
toolCallIdstringTool call ID.
toolNamestringTool name.
inputanyParsed tool input.
providerExecutedboolOptional.
dynamicboolOptional.
titlestringOptional.
toolMetadataobjectOptional.
providerMetadataobjectOptional.

tool-input-error​

The model produced a tool call that is invalid (unknown tool or input that fails validation).

FieldTypeDescription
toolCallIdstringTool call ID.
toolNamestringTool name.
inputanyThe raw input.
errorTextstringError message, mapped by OnError.
providerExecutedboolOptional.
dynamicboolOptional.
titlestringOptional.
toolMetadataobjectOptional.
providerMetadataobjectOptional.

Tool results​

tool-output-available​

The tool returned a result.

FieldTypeDescription
toolCallIdstringTool call ID.
outputanyTool output.
providerExecutedboolOptional.
dynamicboolOptional.
preliminaryboolOptional. True for a preliminary result from a streaming tool. A later chunk replaces it.
toolMetadataobjectOptional.
providerMetadataobjectOptional.

tool-output-error​

The tool failed.

FieldTypeDescription
toolCallIdstringTool call ID.
errorTextstringError message, mapped by OnError. Provider-executed tools report the raw error text.
providerExecutedboolOptional.
dynamicboolOptional.
toolMetadataobjectOptional.
providerMetadataobjectOptional.

tool-output-denied​

The user denied the tool call, so the tool did not run.

FieldTypeDescription
toolCallIdstringTool call ID.

Tool approval​

See Tool approval helpers for the server-side flow.

tool-approval-request​

The tool needs approval before it runs. The client shows a prompt and answers with a tool approval response.

FieldTypeDescription
approvalIdstringApproval ID.
toolCallIdstringID of the tool call that needs approval.
isAutomaticboolOptional. True when a ToolApproval function decided without asking the user.
signaturestringOptional. HMAC signature, present when ExperimentalToolApprovalSecret is set.
inputSchemaInputanyOptional. The tool input before schema parsing and input refinement, when it differs from the parsed input.
reasonstringOptional. Why approval is requested.

tool-approval-response​

The approval decision. The stream emits this chunk for automatic decisions. Clients send the same shape back on the next request, as a tool part approval.

FieldTypeDescription
approvalIdstringApproval ID.
approvedboolWhether the call is approved.
reasonstringOptional. Reason for the decision.
providerExecutedboolOptional.

Data chunks​

data-<name>​

A custom data part. The type is data- followed by a name you choose, for example data-weather. Write one with UIMessageStreamWriter.Write.

FieldTypeDescription
idstringOptional. When set, a later chunk with the same type and ID replaces the data of the earlier part instead of adding a new part.
dataanyThe payload.
transientboolOptional. When true, the part is sent to the client but not stored in the message. It does not reach OnEnd callbacks.

Options​

UIMessageStreamOptions​

Options for ai.CreateUIMessageStreamWithOptions.

FieldTypeDescription
Executefunc(writer UIMessageStreamWriter)
OnErrorfunc(error) string
OriginalMessages[]UIMessageChunk
OnStepEndUIMessageStreamOnStepEndCallback
OnStepFinishUIMessageStreamOnStepFinishCallbackDeprecated: use OnStepEnd.
OnEndUIMessageStreamOnEndCallback
OnFinishUIMessageStreamOnFinishCallbackDeprecated: use OnEnd.
GenerateMessageIDIDGenerator

UIMessageStreamResultOptions​

Options for ai.CreateUIMessageStream, ai.ToUIMessageStream and the response helpers.

FieldTypeDescription
OriginalMessages[]UIMessageChunk
GenerateMessageIDIDGenerator
ResponseMessageIDstring
Tools[]types.Tool
MessageMetadatafunc(part map[string]interface{}) map[string]interface{}
SendReasoning*bool
SendSources*bool
SendStart*bool
SendFinish*bool
OnStepEndUIMessageStreamOnStepEndCallback
OnStepFinishUIMessageStreamOnStepFinishCallbackDeprecated: use OnStepEnd.
OnEndUIMessageStreamOnEndCallback
OnFinishUIMessageStreamOnFinishCallbackDeprecated: use OnEnd.
OnErrorfunc(error) string

UIMessageStreamResponseInit​

Options for the response helpers that take an init value.

FieldTypeDescription
Statusint
StatusTextstring
Headersmap[string]stringHeaders sets a single value per header key. Use Header instead when a header (e.g. Set-Cookie) needs multiple values.
Headerhttp.HeaderHeader carries repeated header values (e.g. multiple Set-Cookie entries), which map[string]string cannot represent. Values here are added in addition to Headers, so both can be set together.
ConsumeSSEStreamfunc(io.Reader) error
KeepAliveMs*time.DurationKeepAliveMs, when set, makes the SSE pipeline flush an opening ": stream-open\n\n" comment immediately (so headers reach the client right away even if the first real chunk is slow) and send a ": keep-alive\n\n" comment whenever this duration elapses without any other write, resetting on every chunk. Must be a positive duration; zero or negative disables it the same as a nil value. Mirrors TS createSseStreamWithKeepAlive's keepAliveMs option (TS #21672).

UIMessageStreamOutcome​

The operation-level result of a stream. Declare one with UIMessageStreamWriter.SetOutcome.

FieldTypeDescription
StatusUIMessageStreamOutcomeStatus
ErrorerrorError is set when Status is UIMessageStreamOutcomeFailed.
ConstantValueDescription
UIMessageStreamOutcomeCompleted"completed"
UIMessageStreamOutcomeFailed"failed"
UIMessageStreamOutcomeAborted"aborted"
UIMessageStreamOutcomeUnknown"unknown"

Writer​

ai.UIMessageStreamWriter is passed to UIMessageStreamOptions.Execute.

MethodDescription
Write(part UIMessageChunk)Appends a chunk.
Merge(stream <-chan UIMessageChunk)Forwards every chunk from another stream.
SetOutcome(outcome UIMessageStreamOutcome)Declares the outcome. The first outcome that is not unknown wins.

Conversion functions​

FunctionDescription
ai.ToUIMessageChunk(part provider.StreamChunk, opts UIMessageStreamResultOptions) (UIMessageChunk, bool)Converts one provider stream chunk. The boolean is false when the part produces no UI chunk.
ai.ToUIMessageStream(ctx, stream provider.TextStream, opts ...UIMessageStreamResultOptions)Converts a whole provider stream to a chunk channel.
ai.IsUIMessageStreamError(err error) boolReports whether err is an *ai.UIMessageStreamError.

ai.UIMessageStreamError is the error type reported through OnError when a chunk refers to a part that does not exist, for example a text-delta with no matching text-start.