930aaeb
CopilotKitDocs
  • Docs
  • Integrations
  • Reference
Get Started
QuickstartCoding Agents
Concepts
ArchitectureGenerative UI OverviewOSS vs Enterprise
Agentic Protocols
OverviewAG-UIAG-UI MiddlewareMCPA2A
Build Chat UIs
Prebuilt Components
CopilotChatCopilotSidebarCopilotPopup
Custom Look and Feel
CSS CustomizationSlots (Subcomponents)Fully Headless UIReasoning Messages
Multimodal AttachmentsVoice
Build Generative UI
Controlled
Tool-based Generative UITool RenderingState RenderingReasoning
Your Components
Display ComponentsInteractive Components
Declarative
A2UIDynamic Schema A2UIFixed Schema A2UI
Open-Ended
MCP Apps
Adding Agent Powers
Frontend ToolsShared State
Human-in-the-Loop
HITL OverviewPausing the Agent for InputHeadless Interrupts
Sub-AgentsAgent ConfigProgrammatic Control
Agents & Backends
Built-in Agent
Backend
Copilot RuntimeFactory ModeAG-UI
Runtime Server AdapterAuthentication
AG2
Shared state
Reading agent stateWriting agent state
Readables
Observe & Operate
InspectorVS Code Extension
Troubleshooting
Common Copilot IssuesError Debugging & ObservabilityDebug ModeAG-UI Event InspectorHook ExplorerError Observability Connectors
Enterprise
CopilotKit PremiumHow the Enterprise Intelligence Platform WorksHow Threads & Persistence WorkObservabilitySelf-Hosting IntelligenceThreads
Deploy
AWS AgentCore
What's New
Full MCP Apps SupportLangGraph Deep Agents in CopilotKitA2UI Launches with full AG-UI SupportCopilotKit v1.50Generative UI Spec SupportA2A and MCP Handshake
Migrate
Migrate to V2Migrate to 1.8.2
Other
Contributing
Code ContributionsDocumentation Contributions
Anonymous Telemetry
AG2Multimodal Attachments

Multimodal Attachments

Let users send images, audio, video, and documents to the AI alongside their messages.

You have a working CopilotChat and want users to attach files — images, PDFs, audio, video — that the AI can see and respond to. By the end of this guide, your chat will support drag-and-drop file attachments with previews, lightbox viewing, and multimodal AI responses.

Quick start#

Add attachments to your CopilotChat component:

import { CopilotChat } from "@copilotkit/react-core/v2";

<CopilotChat
  agentId="my-agent"
  attachments={{ enabled: true }} // [!code highlight]
/>

That's it. Users can now click the attachment button or drag-and-drop files into the chat. The files are sent as part of the message content to your agent.

Configuration#

The attachments prop accepts an AttachmentsConfig object:

<CopilotChat
  attachments={{
    enabled: true,
    accept: "image/*",              // MIME filter (default: "*/*")
    maxSize: 10 * 1024 * 1024,      // 10MB limit (default: 20MB)
  }}
/>
OptionTypeDefaultDescription
enabledboolean—Enable file attachments in the chat input.
acceptstring"*/*"MIME type filter. Supports patterns like "image/*", ".pdf,.docx", or comma-separated lists.
maxSizenumber20 * 1024 * 1024Maximum file size in bytes.
onUpload(file: File) => AttachmentUploadResult | Promise<...>—Custom upload handler. See Custom upload handler.
onUploadFailed(error: AttachmentUploadError) => void—Called when a file fails validation or upload. See Handling upload errors.

Supported file types#

Attachments are categorized by modality based on their MIME type:

ModalityMIME typesPreviewAI support
Imageimage/*Thumbnail with lightboxSupported by most vision-capable models (GPT-4o, Claude, etc.)
Audioaudio/*Audio playerModel-dependent
Videovideo/*Thumbnail with play button + lightboxModel-dependent
DocumentEverything elseFile icon + name; PDF and text get lightbox previewSent as file content — model support varies
Info

Not all models support all modalities. For example, OpenAI's GPT-4o supports images but not audio file parts. If the model doesn't support a file type, you'll get a RUN_ERROR event. Use the onError callback to handle this gracefully.

Custom upload handler#

By default, files are read as base64 and sent inline. For large files or production apps, you'll want to upload to your own storage and pass a URL instead.

onUpload returns an AttachmentUploadResult — a discriminated union with two variants:

<CopilotChat
  attachments={{
    enabled: true,
    onUpload: async (file) => {
      const buffer = await file.arrayBuffer();
      const base64 = btoa(String.fromCharCode(...new Uint8Array(buffer)));
      return {
        type: "data",
        value: base64,
        mimeType: file.type,
      };
    },
  }}
/>

Adding metadata#

You can attach custom metadata to any upload. It's included in the InputContent part sent to the agent and accessible via metadata on the content part.

onUpload: async (file) => {
  const url = await uploadToStorage(file);
  return {
    type: "url",
    value: url,
    mimeType: file.type,
    metadata: {
      uploadedBy: currentUser.id,
      category: "support-ticket",
    },
  };
},

The filename is always included in metadata automatically — you don't need to add it yourself.

Handling upload errors#

Use onUploadFailed to react when a file is rejected or an upload fails — for example, to show a toast:

<CopilotChat
  attachments={{
    enabled: true,
    accept: "image/*",
    maxSize: 5 * 1024 * 1024, // 5MB
    onUploadFailed: (error) => {
      // error.reason: "file-too-large" | "invalid-type" | "upload-failed"
      // error.file: the original File object
      // error.message: human-readable description
      toast.error(error.message);
    },
  }}
/>
ReasonWhen it fires
invalid-typeFile doesn't match the accept filter.
file-too-largeFile exceeds maxSize.
upload-failedThe onUpload handler threw, or the default base64 reader failed.

For errors that happen after the message is sent (e.g., the model doesn't support the file type), use the onError callback on CopilotChat:

<CopilotChat
  attachments={{ enabled: true }}
  onError={(event) => {
    console.error(`[${event.code}]`, event.error.message);
  }}
/>

How it works#

When a user attaches files and sends a message, CopilotKit:

  1. Reads each file (via the default base64 reader or your onUpload handler)
  2. Builds an array of InputContent parts — text + one part per attachment
  3. Adds the message to the agent with content: [{ type: "text", ... }, { type: "image", source: ... }, ...]
  4. The agent receives the multimodal content via the AG-UI protocol and forwards it to the model

The attachments are part of the standard AG-UI InputContent schema, so any AG-UI-compatible agent (BuiltInAgent, LangGraph, custom) can receive them.

On this page
Quick startConfigurationSupported file typesCustom upload handlerAdding metadataHandling upload errorsHow it works