UI messages
ai.UIMessage is the message shape useChat stores and sends. The Go AI SDK models it as a typed struct and as a map form (ai.UIMessageChunk) that matches the JSON on the wire. For the chunks that build a message while it streams, see UI message chunks.
UIMessage
| Field | Type | Description |
|---|---|---|
ID | string | ID is a unique identifier for the message. |
Role | UIMessageRole | Role is system, user or assistant. |
Metadata | interface{} | Metadata is optional application metadata (omitted when nil). |
Parts | []UIMessagePart | Parts are the message parts. Parts decoded from JSON are pointers to the concrete part types (*TextUIPart, *ToolUIPart, ...). |
| Constant | Value | Description |
|---|---|---|
UIMessageRoleSystem | "system" | |
UIMessageRoleUser | "user" | |
UIMessageRoleAssistant | "assistant" |
Parts
ai.UIMessagePart is the interface every part implements. UIPartType() returns the type discriminator. Parts decoded from JSON are pointers to the concrete types.
TextUIPart
| Field | Type | Description |
|---|---|---|
Text | string | |
State | UIPartState | |
ProviderMetadata | map[string]interface{} |
ReasoningUIPart
| Field | Type | Description |
|---|---|---|
ID | string | |
Text | string | |
State | UIPartState | |
ProviderMetadata | map[string]interface{} |
| Constant | Value | Description |
|---|---|---|
UIPartStateStreaming | "streaming" | |
UIPartStateDone | "done" |
ToolUIPart
A static tool part has type tool-<name>. A dynamic tool part has type dynamic-tool and sets ToolName. ai.DynamicToolUIPart and ai.ToolOutputErrorUIPart are aliases for ToolUIPart.
| Field | Type | Description |
|---|---|---|
Type | string | Type is tool-<name> for static tools or dynamic-tool. |
ToolName | string | ToolName is set (and serialized) for dynamic tools only. |
ToolCallID | string | |
State | ToolUIPartState | |
Title | string | |
ToolMetadata | map[string]interface{} | |
ProviderExecuted | *bool | |
Input | interface{} | Input is the tool input. For input-streaming and output-error nil means absent; for other states nil is serialized as null. |
Output | interface{} | Output is the tool output (output-available). |
RawInput | interface{} | RawInput serves two purposes depending on State: - input-streaming: the accumulated raw (partial-JSON) tool input text received so far. Used to continue input streaming when a message is persisted and later resumed (see seedPartialToolCalls). - output-error: the deprecated raw input of an output-error part. Deprecated: for output-error, use Input instead. |
ErrorText | string | |
Preliminary | *bool | |
CallProviderMetadata | map[string]interface{} | |
ResultProviderMetadata | map[string]interface{} | |
Approval | *ToolUIPartApproval |
| Constant | Value | Description |
|---|---|---|
ToolStateInputStreaming | "input-streaming" | |
ToolStateInputAvailable | "input-available" | |
ToolStateApprovalRequested | "approval-requested" | |
ToolStateApprovalResponded | "approval-responded" | |
ToolStateOutputAvailable | "output-available" | |
ToolStateOutputError | "output-error" | |
ToolStateOutputDenied | "output-denied" |
ToolUIPartApproval
| Field | Type | Description |
|---|---|---|
ID | string | |
Approved | *bool | Approved is nil while approval is requested. |
Descriptor | interface{} | Descriptor is an application-defined approval descriptor. |
RequestReason | string | RequestReason is the reason the approval was requested (user-approval status with a reason). |
Reason | string | Reason is the approval response reason. |
IsAutomatic | *bool | |
Signature | string | |
InputSchemaInput | interface{} | InputSchemaInput is the tool input before schema parsing and input refinement (present only when it differs from Input). |
SourceURLUIPart
| Field | Type | Description |
|---|---|---|
SourceID | string | |
URL | string | |
Title | string | |
ProviderMetadata | map[string]interface{} |
SourceDocumentUIPart
| Field | Type | Description |
|---|---|---|
SourceID | string | |
MediaType | string | |
Title | string | |
Filename | string | |
ProviderMetadata | map[string]interface{} |
FileUIPart
| Field | Type | Description |
|---|---|---|
MediaType | string | |
Filename | string | |
URL | string | |
ProviderReference | map[string]string | |
ProviderMetadata | map[string]interface{} |
ReasoningFileUIPart
| Field | Type | Description |
|---|---|---|
MediaType | string | |
URL | string | |
ProviderMetadata | map[string]interface{} |
CustomContentUIPart
| Field | Type | Description |
|---|---|---|
Kind | string | |
ProviderMetadata | map[string]interface{} |
DataUIPart
Type is data-<name>. DataName() returns the name without the prefix.
| Field | Type | Description |
|---|---|---|
Type | string | |
ID | string | |
Data | interface{} |
StepStartUIPart
An empty struct with type step-start. It marks the start of a model step.
Type guards and accessors
| Function | Description |
|---|---|
ai.IsTextUIPart(part) | True for text parts. |
ai.IsReasoningUIPart(part) | True for reasoning parts. |
ai.IsReasoningFileUIPart(part) | True for reasoning-file parts. |
ai.IsFileUIPart(part) | True for file parts. |
ai.IsCustomContentUIPart(part) | True for custom parts. |
ai.IsDataUIPart(part) | True for data-* parts. |
ai.IsToolUIPart(part) | True for static and dynamic tool parts. |
ai.IsStaticToolUIPart(part) | True for tool-<name> parts. |
ai.IsDynamicToolUIPart(part) | True for dynamic-tool parts. |
ai.IsToolOutputErrorUIPart(part) | True for tool parts in the output-error state. |
ai.AsToolUIPart(part) (*ToolUIPart, bool) | Returns the tool part behind a value or pointer. |
ai.GetStaticToolName(part *ToolUIPart) string | The tool name of a static tool part. |
ai.GetToolName(part *ToolUIPart) string | The tool name of a static or dynamic tool part. |
ai.GetToolOrDynamicToolName(part *ToolUIPart) string | Alias for GetToolName. |
JSON and map conversion
| Function | Description |
|---|---|
ai.UnmarshalUIMessagePart(data []byte) (UIMessagePart, error) | Decodes one part into its concrete pointer type. |
ai.UIMessageFromChunk(message UIMessageChunk) (UIMessage, error) | Converts a map-shaped message, such as responseMessage in an end callback, into a UIMessage. |
ai.UIMessagesFromChunks(messages []UIMessageChunk) ([]UIMessage, error) | Converts a slice of map-shaped messages. |
ai.UIMessagesToChunks(messages []UIMessage) ([]UIMessageChunk, error) | Converts typed messages to map-shaped messages. |
UIMessage.ToChunk() (UIMessageChunk, error) | Converts one typed message to a map. |
ReadUIMessages
func ReadUIMessages(ctx context.Context, opts ReadUIMessagesOptions) (<-chan UIMessage, <-chan error)
Folds a chunk stream into a channel of progressively updated messages. Each value is the assistant message so far.
| Field | Type | Description |
|---|---|---|
Message | *UIMessage | Message is the last assistant message to continue when a conversation is resumed. Optional. |
Stream | <-chan UIMessageChunk | Stream is the UI message chunk stream to read. |
OnError | func(error) | OnError is called for processing errors (e.g. a delta for a missing part). Optional. |
TerminateOnError | bool | TerminateOnError stops reading and reports the first error on the error channel. |
Validation
func ValidateUIMessages(ctx context.Context, opts ValidateUIMessagesOptions) ([]UIMessage, error)
func SafeValidateUIMessages(ctx context.Context, opts ValidateUIMessagesOptions) SafeValidateUIMessagesResult
func ValidateUIMessagesForAgent(ctx context.Context, opts ValidateUIMessagesOptions) ([]UIMessage, error)
SafeValidateUIMessages returns a result instead of an error. ValidateUIMessagesForAgent converts terminal tool parts whose tools are not registered, for example tools from a disconnected MCP server, to dynamic tool parts instead of failing.
ValidateUIMessagesOptions
| Field | Type | Description |
|---|---|---|
Messages | interface{} | Messages are the messages to validate. Accepts []UIMessage, []UIMessageChunk, decoded JSON ([]interface{}), json.RawMessage, []byte or string JSON, or any value that marshals to a UI message array. nil means "not provided". |
MetadataSchema | schema.Schema | MetadataSchema validates each message's metadata. The validated value (with schema defaults applied) replaces the metadata. |
DataSchemas | map[string]schema.Schema | DataSchemas validate data parts by name (without the data- prefix). When set, a data part without a schema is an error. Validated values (with schema defaults applied) replace the part data. |
Tools | []types.Tool | Tools validate static tool parts against the current tool input (Parameters) and output (OutputSchema) schemas. A nil slice means no tools were provided (tool parts are not validated); a non-nil empty slice validates against an empty tool set. |
ExperimentalRefineToolInput | map[string]ToolInputRefiner | ExperimentalRefineToolInput reconstructs the approved input from an approval's inputSchemaInput before comparing it with the part input. |
SafeValidateUIMessagesResult
| Field | Type | Description |
|---|---|---|
Success | bool | |
Data | []UIMessage | |
Error | error |
Conversion to model messages
func ConvertToModelMessages(ctx context.Context, messages []UIMessage, opts ...ConvertToModelMessagesOptions) ([]types.Message, error)
Converts UI messages to the types.Message slice a model call takes. A failure returns a *ai.MessageConversionError; ai.IsMessageConversionError(err) tests for it.
| Field | Type | Description |
|---|---|---|
Tools | []types.Tool | Tools are used to convert tool outputs with Tool.ToModelOutput. |
IgnoreIncompleteToolCalls | bool | IgnoreIncompleteToolCalls drops tool parts that are not in a completed state (approval-responded, final output-available, output-error, output-denied). |
ConvertDataPart | func(part DataUIPart) types.ContentPart | ConvertDataPart converts data parts to text or file model message parts (types.TextContent / types.FileContent). Returning nil skips the part. Without it, data parts are ignored. |
Auto-resubmit predicates
| Function | Description |
|---|---|
ai.LastAssistantMessageIsCompleteWithToolCalls(messages []UIMessage) bool | True when the last message is an assistant message whose last step has client-executed tool calls and every one has reached a final output or an error, with no text still streaming. Mirrors the TypeScript helper of the same name. |
ai.LastAssistantMessageIsCompleteWithApprovalResponses(messages []UIMessage) bool | True when the last message is an assistant message whose last step has at least one tool call in the approval-responded state and every tool call in that step has reached a terminal state. Provider-executed calls count. Mirrors the TypeScript helper of the same name. |