Skip to main content
When an MCP tool returns an image or audio, such as a browser screenshot, Dive stores the file and gives the agent a short reference to it instead of the bytes. The agent can pass that reference to another tool, and Dive hands the tool the file in the form it expects.

What a tool’s result looks like

Dive stores every image and audio item in a tool’s result: inline image and audio content, embedded resources with binary contents, and resource_link items whose MIME type is an image or audio, which Dive reads from the server. The result lists them under files, next to whatever text or structured content the tool returned:
When the tool’s result isn’t an object, or already has its own files key, Dive puts it under result instead, as {"result": …, "files": […]}. A reference names the file by its SHA-256 hash, so the same image stored twice is kept once. It stays the same wherever the file is kept, and threads and plan results that mention it keep working if you move file storage to another backend and copy the files across. Deleting a thread removes the files no other thread refers to, except in S3 storage, where other machines may share the bucket. Files kept in S3 or in memory are copied to a local cache when a tool needs a path. The cache holds up to 512 MB and drops the least recently used files past that.

Show a file in a reply

Every conversation agent is told about files and refs in its system prompt, after its own system_prompt. To show the user a file, an agent writes it into its reply as a markdown image with the ref as the URL:
The desktop app draws the image in the message. In a terminal the markdown shows as written. The agent chooses which files to show, so a screenshot it only used to read the page stays in the tool’s result.

Pass a file to another tool

Any argument whose whole value is a reference is replaced before Dive calls the tool. A reference inside longer text is left as it is. Each server’s files setting decides what the tool receives: Use url for a server running on another machine, which can’t read your local paths, and base64 for a server that only accepts file contents in its arguments. Most local servers take a path. If Dive can’t read a referenced file, the tool isn’t called and the agent gets an error naming the reference.

Files in your own tools

An exec tool takes files the same way. Give an input property format: blob, or an array whose items have it, and a reference passed there reaches the command as a local path:
tools/thumbnail.yaml
Files the command writes to the directory in $DIVE_OUT are stored when it exits successfully and listed under files in its result, each with a ref, just like a server’s. builtin__generate_image returns the images it draws as references too, under images; see Image models.

Where files are kept

Without a [storage.files] table, files follow [storage].backend: under <data_dir>/blobs for file, and in memory for memory, which keeps nothing between runs. To keep files somewhere else, set [storage.files].backend:
  • file keeps files under <data_dir>/blobs.
  • memory keeps files only for the length of the run.
  • s3 keeps files in an S3 bucket, or a bucket on an S3-compatible server such as Garage or MinIO. Set endpoint for an S3-compatible server, and region to the region it expects. Keys go under prefix when you set one, so several stores can share a bucket.
Credentials expand ${NAME} references like the rest of config.toml, so you can keep them in the OS credential store with dive secret set DIVE_S3_SECRET. When access_key_id and secret_access_key are omitted, Dive reads the standard AWS_* environment variables. If a referenced secret isn’t set, Dive still starts. A tool call that receives a file then fails naming the missing variable, and files a tool returns are left out of its result, with a warning in the log.