{
  "title": "Image & Media Support — 2025-12-05",
  "content": "The WhatsApp channel runs via **Baileys Web**. This document captures the current media handling rules for send, gateway, and agent replies.\n\n* Send media with optional captions via `openclaw message send --media`.\n* Allow auto-replies from the web inbox to include media alongside text.\n* Keep per-type limits sane and predictable.\n\n* `openclaw message send --media <path-or-url> [--message <caption>]`\n  * `--media` optional; caption can be empty for media-only sends.\n  * `--dry-run` prints the resolved payload; `--json` emits `{ channel, to, messageId, mediaUrl, caption }`.\n\n## WhatsApp Web channel behavior\n\n* Input: local file path **or** HTTP(S) URL.\n* Flow: load into a Buffer, detect media kind, and build the correct payload:\n  * **Images:** resize & recompress to JPEG (max side 2048px) targeting `agents.defaults.mediaMaxMb` (default 5 MB), capped at 6 MB.\n  * **Audio/Voice/Video:** pass-through up to 16 MB; audio is sent as a voice note (`ptt: true`).\n  * **Documents:** anything else, up to 100 MB, with filename preserved when available.\n* WhatsApp GIF-style playback: send an MP4 with `gifPlayback: true` (CLI: `--gif-playback`) so mobile clients loop inline.\n* MIME detection prefers magic bytes, then headers, then file extension.\n* Caption comes from `--message` or `reply.text`; empty caption is allowed.\n* Logging: non-verbose shows `↩️`/`✅`; verbose includes size and source path/URL.\n\n## Auto-Reply Pipeline\n\n* `getReplyFromConfig` returns `{ text?, mediaUrl?, mediaUrls? }`.\n* When media is present, the web sender resolves local paths or URLs using the same pipeline as `openclaw message send`.\n* Multiple media entries are sent sequentially if provided.\n\n## Inbound Media to Commands (Pi)\n\n* When inbound web messages include media, OpenClaw downloads to a temp file and exposes templating variables:\n  * `{{MediaUrl}}` pseudo-URL for the inbound media.\n  * `{{MediaPath}}` local temp path written before running the command.\n* When a per-session Docker sandbox is enabled, inbound media is copied into the sandbox workspace and `MediaPath`/`MediaUrl` are rewritten to a relative path like `media/inbound/<filename>`.\n* Media understanding (if configured via `tools.media.*` or shared `tools.media.models`) runs before templating and can insert `[Image]`, `[Audio]`, and `[Video]` blocks into `Body`.\n  * Audio sets `{{Transcript}}` and uses the transcript for command parsing so slash commands still work.\n  * Video and image descriptions preserve any caption text for command parsing.\n* By default only the first matching image/audio/video attachment is processed; set `tools.media.<cap>.attachments` to process multiple attachments.\n\n**Outbound send caps (WhatsApp web send)**\n\n* Images: \\~6 MB cap after recompression.\n* Audio/voice/video: 16 MB cap; documents: 100 MB cap.\n* Oversize or unreadable media → clear error in logs and the reply is skipped.\n\n**Media understanding caps (transcription/description)**\n\n* Image default: 10 MB (`tools.media.image.maxBytes`).\n* Audio default: 20 MB (`tools.media.audio.maxBytes`).\n* Video default: 50 MB (`tools.media.video.maxBytes`).\n* Oversize media skips understanding, but replies still go through with the original body.\n\n* Cover send + reply flows for image/audio/document cases.\n* Validate recompression for images (size bound) and voice-note flag for audio.\n* Ensure multi-media replies fan out as sequential sends.",
  "code_samples": [],
  "headings": [
    {
      "level": "h2",
      "text": "Goals",
      "id": "goals"
    },
    {
      "level": "h2",
      "text": "CLI Surface",
      "id": "cli-surface"
    },
    {
      "level": "h2",
      "text": "WhatsApp Web channel behavior",
      "id": "whatsapp-web-channel-behavior"
    },
    {
      "level": "h2",
      "text": "Auto-Reply Pipeline",
      "id": "auto-reply-pipeline"
    },
    {
      "level": "h2",
      "text": "Inbound Media to Commands (Pi)",
      "id": "inbound-media-to-commands-(pi)"
    },
    {
      "level": "h2",
      "text": "Limits & Errors",
      "id": "limits-&-errors"
    },
    {
      "level": "h2",
      "text": "Notes for Tests",
      "id": "notes-for-tests"
    }
  ],
  "url": "llms-txt#image-&-media-support-—-2025-12-05",
  "links": []
}