---
title: convertToModelMessages
description: Convert useChat messages to ModelMessages for AI functions (API Reference)
---

# `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`.

```ts filename="app/api/chat/route.ts"
import { convertToModelMessages, streamText } from 'ai';
__PROVIDER_IMPORT__;

export async function POST(req: Request) {
  const { messages } = await req.json();

  const result = streamText({
    model: __MODEL__,
    messages: await convertToModelMessages(messages),
  });

  return result.toUIMessageStreamResponse();
}
```

## Import

<Snippet text={`import { convertToModelMessages } from "ai"`} prompt={false} />

## API Signature

### Parameters

<PropertiesTable
  content={[
    {
      name: 'messages',
      type: 'Message[]',
      description:
        'An array of UI messages from the useChat hook to be converted',
    },
    {
      name: 'options',
      type: '{ tools?: ToolSet, ignoreIncompleteToolCalls?: boolean, convertDataPart?: (part: DataUIPart) => TextPart | FilePart | undefined }',
      description:
        'Optional configuration object. Provide tools to enable multi-modal tool responses. Set ignoreIncompleteToolCalls to true to skip tool calls without results (default: false). Use convertDataPart to transform custom data parts into model-compatible content.',
    },
  ]}
/>

### Returns

A Promise that resolves to an array of [`ModelMessage`](/docs/reference/ai-sdk-core/model-message) objects.

<PropertiesTable
  content={[
    {
      name: 'Promise<ModelMessage[]>',
      type: 'Promise',
      description:
        'A Promise that resolves to 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.

```ts
import { tool } from 'ai';
__PROVIDER_IMPORT__;
import { z } from 'zod';

const screenshotTool = tool({
  inputSchema: z.object({}),
  execute: async () => 'imgbase64',
  toModelOutput: ({ output }) => [{ type: 'image', data: output }],
});

const result = streamText({
  model: __MODEL__,
  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:

```ts filename="app/api/chat/route.ts"
import { convertToModelMessages, streamText } 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: __MODEL__,
    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:

```ts
// Client side
sendMessage({
  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:

```ts
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.

```ts
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:

```ts
type MyUIMessage = UIMessage<
  unknown,
  {
    url: { url: string; content: string };
    config: { key: string; value: string };
  }
>;

// TypeScript knows the exact shape of part.data
convertToModelMessages<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 undefined to skip this part
  },
});
```
