How Slack files reach the agent turn, and how Apus sends text and media back.

Voice input

To speak to Apus in Slack today, send a Slack audio clip to the Apus app. Slackbot's dictation microphone is a separate Slack-owned feature, not an app API.

Audio clips and Slackbot dictation have different privacy semantics: clips follow Slack file-retention policy and Apus downloads them for transcription, while Slack says dictation audio is not stored.

In a channel with requireMention: true, a captionless audio clip can satisfy the gate by speaking a configured mention pattern (agents.entries.*.groupChat.mentionPatterns, falling back to messages.groupChat.mentionPatterns). Apus authorizes the sender before downloading or transcribing the clip, then admits it only when the transcript matches. A failed or nonmatching speculative transcript is discarded with the downloaded clip; it is not retained in channel history. Native Slack @bot identity cannot be inferred from speech, so configure a spoken-name pattern or include a typed mention. If transcript echoing is enabled, the echo is sent only after admission.

Media, chunking, and delivery

Inbound attachments
Slack file attachments are downloaded from Slack-hosted private URLs (token-authenticated request flow) and written to the media store when fetch succeeds and size limits permit. File placeholders include the Slack `fileId` so agents can fetch the original file with `download-file`.

Downloads use bounded idle and total timeouts. If Slack file retrieval stalls or fails, Apus keeps processing the message and falls back to the file placeholder.

Runtime inbound size cap defaults to `20MB` unless overridden by `channels.slack.mediaMaxMb`.
Outbound text and files
- text chunks use `channels.slack.textChunkLimit` (default `8000`, capped at Slack's own message-length limit)
- `channels.slack.streaming.chunkMode="newline"` enables paragraph-first splitting
- file sends use Slack upload APIs and can include thread replies (`thread_ts`)
- long file captions use the first Slack-safe text chunk as the upload comment and send remaining chunks as follow-up messages
- text and context blocks preserve code formatting and literal backslashes across section boundaries
- outbound media cap follows `channels.slack.mediaMaxMb` when configured; otherwise channel sends use MIME-kind defaults from media pipeline

Native Block Kit sections retain all fields even when their combined accessibility text exceeds the preferred text chunk size. Slack's block limits and the 40,000-character message text hard limit still apply.
Delivery targets
Preferred explicit targets:

- `user:<id>` for DMs
- `channel:<id>` for channels

Text/block-only Slack DMs can post directly to user IDs; file uploads and threaded sends open the DM via Slack conversation APIs first because those paths require a concrete conversation ID.

Attachment media reference

Slack can attach downloaded media to the agent turn when Slack file downloads succeed and size limits permit. Audio clips can be transcribed, image files can pass through the media-understanding path or directly to a vision-capable reply model, and other files remain available as downloadable file context.

Downloading an attachment by file ID

The message tool's download-file action requires a Slack fileId from a message or file placeholder. It uses the current Slack channel unless you provide an explicit channelId. An explicit threadId additionally requires the file to be shared in that thread; an ambient conversation thread does not narrow a channel-only download.

Apus checks the channel's existing access policy and fresh files.info share evidence before downloading. It repeats the file-share check if Slack refreshes an expired download URL. Verified official npm and ClawHub installations use the same provider checks as the bundled Slack plugin.

An allowed download returns the existing local media artifact. Images also return image content within the configured image dimension limit. The configured read credentials, Slack/GovSlack host restrictions, HTTPS and redirect checks, and channels.slack.mediaMaxMb size cap continue to apply. For agent downloads, a canceled or revoked read cannot return an accepted artifact; cleanup removes its own newly created file while preserving preexisting or replaced files.

Supported media types

Media type Source Current behavior Notes
Slack audio clips Slack file URL Downloaded and routed through shared audio transcription Requires files:read and a working tools.media.audio model or CLI
JPEG / PNG / GIF / WebP images Slack file URL Downloaded and attached to the turn for vision-capable handling Per-file cap: channels.slack.mediaMaxMb (default 20 MB)
PDF files Slack file URL Downloaded and exposed as file context for tools such as download-file or pdf Slack inbound does not convert PDFs into image-vision input automatically
Other files Slack file URL Downloaded when possible and exposed as file context Binary files are not treated as image input
Thread replies Thread starter files Root-message files can be hydrated as context when the reply has no direct media File-only starters use an attachment placeholder
Multi-file messages Multiple Slack files Each file is evaluated independently Slack processing is capped at eight files per message

Inbound pipeline

When a Slack message with file attachments arrives:

  1. Apus downloads the file from Slack's private URL using the bot token.
  2. The file is written to the media store on success.
  3. Downloaded media paths and content types are added to the inbound context.
  4. Audio clips are routed to the shared transcription pipeline; image-capable model/tool paths can use image attachments from the same context.
  5. Other files remain available as file metadata or media references for tools that can handle them.

Thread-root attachment inheritance

When a message arrives in a thread (has a thread_ts parent):

Multi-attachment handling

When a single Slack message contains multiple file attachments:

Size, download, and model limits

Known limits

Scenario Current behavior Workaround
Expired Slack file URL File skipped; no error shown Re-upload the file in Slack
Audio transcription unavailable Clip remains attached but no transcript is produced Configure tools.media.audio or install a supported local transcription CLI
Captionless clip does not pass a mention gate Dropped after private speculative transcription; transcript and download discarded Configure a spoken-name mention pattern, add a typed bot mention, or use a DM
Vision model not configured Image attachments are stored as media references, but not analyzed as images Configure agents.defaults.imageModel or use a vision-capable reply model
Very large images (> 20 MB by default) Skipped per size cap Increase channels.slack.mediaMaxMb if Slack allows
Forwarded/shared attachments Text and Slack-hosted image/file media are best-effort Re-share directly in the Apus thread
PDF attachments Stored as file/media context, not automatically routed through image vision Use download-file for file metadata or the pdf tool for PDF analysis

Related documentation