multipart/form-data.
There are two entry points for media:
input.file— singular. Used by webhook handlers (Twilio/WhatsApp, Meta/Messenger) that resolve a single media file per inbound message. Auto-processed whenmedia.transcribeAudioormedia.processImagesis enabled.input.attachments[]— plural. Populated when the agent is invoked viamultipart/form-data(one or more files in the same request). Auto-bridged to a multimodal chat message whenmedia.processAttachmentsis enabled.
user message with image and/or file parts. Choose the entry point that matches how media reaches your agent.
Audio Transcription
Transcribe audio files to text using multiple providers:Supported Providers
Agent with Auto Media Processing
Configure agents to automatically handle audio and image files. When a user sends a voice message, it’s transcribed before processing. When they send an image, it’s analyzed with vision capabilities.Media Config Options
Multipart Uploads (Files & Images via HTTP)
When you call the agent directly over HTTP and need to send files or images, postmultipart/form-data to the agent endpoint. Runflow stores each upload, generates a short-lived URL, and delivers an input.attachments[] array to your agent.
Auto-bridge (recommended)
Enablemedia.processAttachments to have the SDK build the multimodal message for you. No glue code, no transform — the agent receives the attachments and forwards them to the LLM automatically.
agent.ts
- Runflow stores the upload and delivers your agent an input that looks like this:
- The SDK builds a multimodal user message — text plus image — and sends it to the model.
- The image reaches the LLM in whatever format that provider expects (OpenAI/Gemini get the URL directly; Anthropic, Groq, xAI and Azure all receive their respective shapes — handled transparently by the SDK).
content_typestarting withimage/→{ type: 'image_url', image_url: { url } }- anything else →
{ type: 'file_url', file_url: { url }, name }
Manual transform (advanced)
If you need custom routing — download a CSV to parse locally, OCR a PDF before sending, fan out images to different conversations — leaveprocessAttachments off and transform the attachments yourself:
Limits
Oversize uploads return HTTP 413 AttachmentTooLarge. Malformed multipart returns 400 InvalidMultipart.
The URLs in
input.attachments[].url are short-lived — your agent and the LLM provider should consume them within minutes of the request. For documents that need to live longer, persist them yourself (e.g., copy to your own storage).
Provider support for attachments
For non-image files on providers that don’t support arbitrary documents, the SDK emits a
[File: <name>] text placeholder so the model sees something coherent. If you need the model to actually read a PDF/CSV, parse it locally first and send the extracted text.
Real-World Example: WhatsApp Support Agent
A complete WhatsApp agent that handles text, voice messages, and photos. Users can send a voice message to explain their issue or a photo of a damaged product.Project Structure
Agent with Media
agent.ts
Main Entry Point
main.ts
Real-World Example: Transcription Tool
When you need more control over transcription (e.g., saving the transcription, analyzing it), usetranscribe() inside a tool:
tools/process-voice.ts
Tips
Next Steps
Agents
Configure agents with media
Tools
Build custom media tools
Context Management
Identify users in WhatsApp
Best Practices
Tips for effective agents