Stored message formats

The message formats Assistant Cloud stores, converts, and reads for thread titles.

Assistant Cloud stores a format name with every message. The format preserves the writer's message shape, while a message read can request a compatible AI SDK shape.

The stored formats

FormatWriterStored shape
aui/v0The assistant-ui cloud history adapter and external-store runtime copies.An assistant-ui thread message with content, attachments, status, and metadata.
ai-sdk/v6The aiSDKV6FormatAdapter.An AI SDK UI message without its message id.
ai-sdk/v5Older AI SDK message writers.The older AI SDK message row, retained as a readable format.

The aui/v0 shape

aui/v0 is the complete assistant-ui message shape. It is stored with format: "aui/v0".

Message fields

FieldRequiredShape
idNoLocal message ID. The encoder does not store it at the top level.
createdAtNoISO date string. The encoder does not store it at the top level.
roleYesassistant, user, or system.
statusNoThe assistant-ui message status.
contentYesArray of message parts.
attachmentsNoArray of attachment wrappers.
metadataYesState, annotations, data, steps, and custom values.

Message parts

TypeFields
texttext, optional id, providerMetadata, and parentId.
reasoningtext, optional id, unstable_summary, timing, providerMetadata, and parentId.
source with sourceType: "url"id, url, optional title, providerMetadata, and parentId.
source with sourceType: "document"id, title, mediaType, optional filename, providerMetadata, and parentId.
tool-calltoolCallId, toolName, one of args or argsText, and optional result, artifact, modelContent, providerMetadata, isPreliminary, isError, interrupt, timing, mcp, approval, parentId, nested messages, and unstable_interactions.
imageimage, optional id, filename, and providerMetadata.
filedata, mimeType, optional id, filename, sourceType, providerMetadata, and parentId.
dataname, data, optional id.
audioaudio: { data, format }, where format is mp3 or wav.
generative-uispec, optional id and parentId.

For text, reasoning, image, file, and data parts, the host-supplied id keys the part when it is non-empty and no other part of the same type in the message shares it, preserving component state when parts are reordered or updated with the same id. Every part with a missing or empty id, or an id shared by another part of the same type, is keyed by its type and position. The format preserves optional ids on attachment content parts too.

Attachments and metadata

ItemFields
Attachment wrapperid, type, name, optional contentType, status, and content.
Attachment texttext, optional id, providerMetadata, and parentId.
Attachment imageimage, optional id, filename, and providerMetadata.
Attachment filedata, mimeType, optional id, filename, sourceType, providerMetadata, and parentId.
Attachment audioaudio: { data, format }, where format is mp3 or wav.
Attachment dataname, data, optional id.
metadata.unstable_stateOptional JSON value.
metadata.unstable_annotationsArray of JSON values.
metadata.unstable_dataArray of JSON values.
metadata.stepsArray whose entries may have usage.inputTokens and usage.outputTokens.
metadata.customJSON object for application values.

Encode a message

The encoder drops the top level id and createdAt, because the server supplies those values. It rewrites a running status as { type: "incomplete", reason: "cancelled" }.

Attachments are stored only on a user message and only when that message has attachments. A tool call stores args when JSON.stringify(args) equals argsText; otherwise it stores argsText. A tool result that cannot serialize as JSON is omitted, and one that loses data is stored as its JSON form. A non JSON artifact is dropped. A non JSON data value is written after a warning. Nested tool messages keep their own ID and ISO createdAt.

Runtimes that keep their transcript in their own backend, including LangGraph, LangChain, ADK, and custom external stores, copy eligible messages as aui/v0. Each copy has parent_id: null, uses the runtime message ID as external_id, and uses the preceding copied message ID as parent_external_id. Empty IDs and IDs longer than 255 characters are skipped.

AG-UI stores the final agent state in metadata.unstable_state and activity in data parts named agui-activity/<type>. AG-UI and A2A store A2UI surfaces as present tool calls whose artifact.a2ui carries the operations. A2A stores task artifacts in metadata.custom.a2a.artifacts without inline file bytes.

An unsupported message part throws Message part type not supported by aui/v0: <type>. An unsupported attachment part throws Attachment part type not supported by aui/v0: <type>.

Decode a message

The decoder injects the server message ID and created_at, and exposes the stored parent_id as parentId. The history adapter decodes leniently. It drops unreadable parts and nested messages, then skips unreadable or orphaned rows. A nested tool message without an ID receives one synthesized from the containing message ID, tool call ID, and its indexes. A message with no status decodes as { type: "complete", reason: "unknown" }.

The ai-sdk/v6 shape

ai-sdk/v6 stores a UI message without its id. On read, the adapter adds the server message ID and the server parent ID as parentId.

Its telemetry reader examines assistant messages only. It opens a step for each step-start part, concatenates text parts into output text, and reads a tool's arguments from input or args and its result from output or result. A tool-<name> part is a frontend tool, while a dynamic-tool part with toolName is an MCP tool. Tool calls mark their step as tool-calls, and sampling calls are attached by tool call ID from metadata.samplingCalls. Tool artifacts, interactions, and approval responses use metadata.__aui_toolArtifacts, metadata.__aui_toolInteractions, and metadata.__aui_toolApprovalResponses.

Usage comes from metadata.usage, or from the sum of metadata.steps[].usage when that is absent. The reader sums usage across assistant messages and reads the model ID from message metadata. It reports completed when any text or tool call exists, and incomplete otherwise.

The ai-sdk/v5 shape

ai-sdk/v5 is the older AI SDK row with role and parts. It remains readable and can be converted to ai-sdk/v6. Its tool parts carry toolCallId, toolName, state, input, optional output, and optional errorText.

When converted from aui/v0, a tool call has output-error when isError is true, output-available when result is present, and input-available otherwise. isError wins when both are present. Any result other than undefined counts as present, including false, 0, an empty string and null. During a v5 to v6 conversion, output-error becomes an error result and tries to parse errorText as JSON.

During a server conversion from aui/v0 to ai-sdk/v5 or ai-sdk/v6, tool artifact and unstable_interactions move to the corresponding __aui_toolArtifacts and __aui_toolInteractions metadata keys. A v6 row spreads metadata.custom into its metadata. Data parts become data-<name> parts, and document sources become source-document parts. Generative UI becomes a data-generative-ui part, images and audio become file parts, and unknown parts become data-<type> parts.

Read a compatible format

Pass format to GET /v1/threads/{thread_id}/messages or GET /v1/projects/threads/{thread_id}/messages to request a compatible row.

Read messages as AI SDK v6
const { messages } = await cloud.threads.messages.list(
  "thread_0qzof3jPoDwr7K3agyJN3D4U",
  { format: "ai-sdk/v6" },
);
console.log(messages);
curl
curl "https://backend.assistant-api.com/v1/threads/thread_0qzof3jPoDwr7K3agyJN3D4U/messages?format=ai-sdk%2Fv6" \
  -H "Authorization: Bearer $ASSISTANT_API_KEY" \
  -H "Aui-User-Id: user_123" \
  -H "Aui-Workspace-Id: workspace_123"
Requested formatStored formatResult
ai-sdk/v6aui/v0Converted to ai-sdk/v6.
ai-sdk/v6ai-sdk/v5Converted to ai-sdk/v6.
ai-sdk/v5aui/v0Converted to ai-sdk/v5.
Any other pairAny stored formatReturned in its stored format.

If a stored row cannot be parsed or converted, the list skips that row and logs a warning. It does not fail the whole response.

Extract text for a thread title

Thread title generation reads only messages whose role is user or assistant. A user message with no extracted text is omitted; an assistant message with no extracted text remains as an empty message. The title model then uses the first user and first assistant message, and only their text.

FormatText source
aui/v0content parts whose type is text, joined in order.
ai-sdk/v5parts whose type is text, joined in order.
ai-sdk/v6parts whose type is text, joined in order.