📄 ai-sdk/docs/reference/ai-sdk-ui/convert-to-model-messages

File: convert-to-model-messages.md | Updated: 11/15/2025

Source: https://ai-sdk.dev/docs/reference/ai-sdk-ui/convert-to-model-messages

AI SDK

Menu

v5 (Latest)

AI SDK 5.x

AI SDK by Vercel

AI SDK 6 Beta

Foundations

Overview

Providers and Models

Prompts

Tools

Streaming

Getting Started

Navigating the Library

Next.js App Router

Next.js Pages Router

Svelte

Vue.js (Nuxt)

Node.js

Expo

Agents

Agents

Building Agents

Workflow Patterns

Loop Control

AI SDK Core

Overview

Generating Text

Generating Structured Data

Tool Calling

Model Context Protocol (MCP) Tools

Prompt Engineering

Settings

Embeddings

Image Generation

Transcription

Speech

Language Model Middleware

Provider & Model Management

Error Handling

Testing

Telemetry

AI SDK UI

Overview

Chatbot

Chatbot Message Persistence

Chatbot Resume Streams

Chatbot Tool Usage

Generative User Interfaces

Completion

Object Generation

Streaming Custom Data

Error Handling

Transport

Reading UIMessage Streams

Message Metadata

Stream Protocols

AI SDK RSC

Advanced

Reference

AI SDK Core

AI SDK UI

useChat

useCompletion

useObject

convertToModelMessages

pruneMessages

createUIMessageStream

createUIMessageStreamResponse

pipeUIMessageStreamToResponse

readUIMessageStream

InferUITools

InferUITool

AI SDK RSC

Stream Helpers

AI SDK Errors

Migration Guides

Troubleshooting

Copy markdown

convertToModelMessages()

===========================================================================================================================

The convertToModelMessages function is used to transform an array of UI messages from the useChat hook into an array of ModelMessage objects. These ModelMessage objects are compatible with AI core functions like streamText.

app/api/chat/route.ts

import { openai } from '@ai-sdk/openai';import { convertToModelMessages, streamText } from 'ai';
export async function POST(req: Request) {  const { messages } = await req.json();
  const result = streamText({    model: openai('gpt-4o'),    messages: convertToModelMessages(messages),  });
  return result.toUIMessageStreamResponse();}

Import


import { convertToModelMessages } from "ai"

API Signature


Parameters

messages:

Message[]

An array of UI messages from the useChat hook to be converted

options:

{ tools?: ToolSet, convertDataPart?: (part: DataUIPart) => TextPart | FilePart | undefined }

Optional configuration object. Provide tools to enable multi-modal tool responses, and convertDataPart to transform custom data parts into model-compatible content.

Returns

An array of ModelMessage objects.

ModelMessage[]:

Array

An array of ModelMessage objects

Multi-modal Tool Responses


The convertToModelMessages function supports tools that can return multi-modal content. This is useful when tools need to return non-text content like images.

import { tool } from 'ai';import { z } from 'zod';
const screenshotTool = tool({  parameters: z.object({}),  execute: async () => 'imgbase64',  toModelOutput: result => [{ type: 'image', data: result }],});
const result = streamText({  model: openai('gpt-4'),  messages: convertToModelMessages(messages, {    tools: {      screenshot: screenshotTool,    },  }),});

Tools can implement the optional toModelOutput method to transform their results into multi-modal content. The content is an array of content parts, where each part has a type (e.g., 'text', 'image') and corresponding data.

Custom Data Part Conversion


The convertToModelMessages function supports converting custom data parts attached to user messages. This is useful when users need to include additional context (URLs, code files, JSON configs) with their messages.

Basic Usage

By default, data parts in user messages are filtered out during conversion. To include them, provide a convertDataPart callback that transforms data parts into text or file parts that the model can understand:

app/api/chat/route.ts

import { openai } from '@ai-sdk/openai';import { convertToModelMessages, streamText, UIMessage } from 'ai';
type CustomUIMessage = UIMessage<  never,  {    url: { url: string; title: string; content: string };    'code-file': { filename: string; code: string; language: string };  }>;
export async function POST(req: Request) {  const { messages } = await req.json();
  const result = streamText({    model: openai('gpt-4o'),    messages: convertToModelMessages<CustomUIMessage>(messages, {      convertDataPart: part => {        // Convert URL attachments to text        if (part.type === 'data-url') {          return {            type: 'text',            text: `[Reference: ${part.data.title}](${part.data.url})\n\n${part.data.content}`,          };        }
        // Convert code file attachments        if (part.type === 'data-code-file') {          return {            type: 'text',            text: `\`\`\`${part.data.language}\n// ${part.data.filename}\n${part.data.code}\n\`\`\``,          };        }
        // Other data parts are ignored      },    }),  });
  return result.toUIMessageStreamResponse();}

Use Cases

Attaching URL Content Allow users to attach URLs to their messages, with the content fetched and formatted for the model:

// Client sidesendMessage({  parts: [    { type: 'text', text: 'Analyze this article' },    {      type: 'data-url',      data: {        url: 'https://example.com/article',        title: 'Important Article',        content: '...',      },    },  ],});

Including Code Files as Context Let users reference code files in their conversations:

convertDataPart: part => {  if (part.type === 'data-code-file') {    return {      type: 'text',      text: `\`\`\`${part.data.language}\n${part.data.code}\n\`\`\``,    };  }};

Selective Inclusion Only data parts for which you return a text or file model message part are included, all other data parts are ignored.

const result = convertToModelMessages<  UIMessage<    unknown,    {      url: { url: string; title: string };      code: { code: string; language: string };      note: { text: string };    }  >>(messages, {  convertDataPart: part => {    if (part.type === 'data-url') {      return {        type: 'text',        text: `[${part.data.title}](${part.data.url})`,      };    }
    // data-code and data-node are ignored  },});

Type Safety

The generic parameter ensures full type safety for your custom data parts:

type MyUIMessage = UIMessage<  unknown,  {    url: { url: string; content: string };    config: { key: string; value: string };  }>;
// TypeScript knows the exact shape of part.dataconvertToModelMessages<MyUIMessage>(messages, {  convertDataPart: part => {    if (part.type === 'data-url') {      // part.data is typed as { url: string; content: string }      return { type: 'text', text: part.data.url };    }    return null;  },});

On this page

convertToModelMessages()

Import

API Signature

Parameters

Returns

Multi-modal Tool Responses

Custom Data Part Conversion

Basic Usage

Use Cases

Type Safety

Deploy and Scale AI Apps with Vercel.

Vercel delivers the infrastructure and developer experience you need to ship reliable AI-powered applications at scale.

Trusted by industry leaders:

  • OpenAI
  • Photoroom
  • leonardo-ai Logoleonardo-ai Logo
  • zapier Logozapier Logo

Talk to an expert