> ## Documentation Index
> Fetch the complete documentation index at: https://docs.labelbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Files

> Upload input files once, attach them read-only to any session, show them to the agent in a message, and download the deliverables sessions save.

Files are how you give a session input and how you take its results away. Your organization's files are of two kinds:

* **Uploads.** Files you add, such as a data set or a spec. Attach an upload to any number of sessions, read-only.
* **Session outputs.** Deliverables an agent saves in a session. They're kept with the session, and you can preview and download them.

The sidebar **Files** page shows uploads and session outputs together. You can also attach inputs when you launch a session or from its **Files** tab, and find that session's outputs there.

<Note>
  Listing and downloading files needs read permission. Uploading needs create, and attaching to or detaching from a session needs update. Organization developers and admins have all of them. See [Organizations and roles](/recursion/organizations-and-roles). Attaching files needs an environment with a sandbox, which every environment has by default.
</Note>

## Upload a file

<Tabs>
  <Tab title="Console">
    Open **Files** in the sidebar and click **Upload file**, or upload from **Launch session**, the session's **Files** tab, or **Attach from Files** in the message box. Each upload is added to your organization's files and selected for you. The console accepts a file up to 1 GiB.
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/files' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -F 'file=@signups.csv;type=text/csv' \
      -F 'expires_in_seconds=604800'
    ```
  </Tab>
</Tabs>

The response is `201` with the file, including its `file_id`. Use that id to attach the file to a session or name it in a message.

To remove a file you no longer need, select it on the sidebar **Files** page and choose **Delete**. This works for uploads and session outputs. Deleting its catalog row removes it from Files and prevents future attachments; a copy already mounted in a running sandbox remains there. Session outputs that you keep are removed when their session is purged.

<Accordion title="Upload fields">
  `uploadFile` takes a `multipart/form-data` body. The `file` part's filename and `Content-Type` become the file's name and media type, and the part can hold at most 30 MiB. `expires_in_seconds` is optional, from 3600 (an hour) to 7776000 (ninety days); omit it for a file that doesn't expire. `metadata` is an optional JSON object sent as a string.
</Accordion>

## Attach files when a session starts

Name files in `resources` when you start the session. They're in the sandbox before the agent's first step. An attached file is copied into the sandbox under `/workspace/.managed-agents/files`, read-only. The agent knows it's there and can read it with `read_file` or from a shell.

<Tabs>
  <Tab title="Console">
    1. In the sidebar, click **Sessions**, then click **Launch session**.
    2. Choose the agent and environment, and write the opening message.
    3. Under **Files**, click **Add**, choose each file or upload one, and optionally set the path it should have in the sandbox.
    4. Click **Launch session**.
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/sessions' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: signups-summary-2026-09-25' \
      -d '{
        "agent_id": "5f0c2a1e-8b7d-4c3a-9e21-6d4f0b9a7c55",
        "environment_id": "0d5e8a2c-6f13-4b97-a4e0-3c7f9b1d5e62",
        "message": "Summarize the weekly trend in data/signups.csv.",
        "resources": [
          { "type": "file", "file_id": "9f8b1c2d-3e4f-5a6b-7c8d-9e0f1a2b3c4d", "relative_path": "data/signups.csv" }
        ]
      }'
    ```
  </Tab>
</Tabs>

The start is all-or-nothing: one unknown, expired, or out-of-organization `file_id` refuses the whole request with `404`, and no session is created.

<Accordion title="Paths and file content">
  `relative_path` places the file under the files directory; it defaults to the file's own name. It must be unique in the session and can't contain `.` or `..` segments. Each attachment takes the file's content as it is when you attach it.
</Accordion>

## Attach and detach files while a session runs

1. Open the session and choose the **Files** tab in the side panel. **Inputs** lists the files attached to the session.
2. Click **Attach files…**, choose or upload the files, and click **Attach**.
3. To detach one, click the **×** on its row in **Inputs**.

**What success means:** the file is placed in the sandbox on the session's next tool call, and the agent can see it from its next turn.

<Accordion title="Attach and detach rules">
  * Attach is all-or-nothing. The console refuses the batch if a file is unavailable or a path collides with or nests inside another attachment.
  * Attach to the root session of a multi-agent tree. The console refuses a subagent or teammate session; everyone in the tree shares the root's sandbox.
  * You can attach to a finished root session. Its next message resumes it with the file already in place.
  * Detach stops listing the file. A copy already in the sandbox stays, because the agent may be reading it.
</Accordion>

## Show a file to the agent in a message

To have the agent look at an image or read a short document as part of a message, name the file in the message instead of attaching it. The file is read when the message is accepted.

<Tabs>
  <Tab title="Console">
    In the session's message box, click **Attach from Files**, choose an image or a text document, or upload one, then send the message.
  </Tab>

  <Tab title="cURL">
    ```bash theme={"theme":"css-variables"}
    curl -X POST 'https://api.recursion.labelbox.com/managed-agents/v1/sessions/e3a91f5c-7d24-4b68-9c10-2f8e6b4d7a53/events' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{"events": [{"type": "user.message", "content": [
        {"type": "text", "text": "Does this chart match the numbers in the CSV?"},
        {"type": "image", "source": {"type": "file", "file_id": "2b6e9d41-8c37-4f05-a1d2-7e9c3b5f8a60"}}
      ]}]}'
    ```
  </Tab>
</Tabs>

Use `"type": "image"` for a PNG, JPEG, or WebP image the model sees, and `"type": "document"` for a text file, which is placed in the message as text. To send an image that isn't in your library, see [Send an image](/recursion/sessions#send-an-image).

## Download session deliverables

Every deliverable an agent saves in `/workspace/.managed-agents/outputs` is kept as a session output after each turn. See [Deliverables and artifacts](/recursion/artifacts) for what's kept and when.

<Tabs>
  <Tab title="Console">
    Open the session and choose the **Files** tab in the side panel. **Outputs** lists each deliverable with its path, size, and when it was captured. Click one to preview it, and download it from the preview.
  </Tab>

  <Tab title="cURL">
    List the session's deliverables, then download each by its `file_id`:

    ```bash theme={"theme":"css-variables"}
    curl 'https://api.recursion.labelbox.com/managed-agents/v1/files?scope_session_id=e3a91f5c-7d24-4b68-9c10-2f8e6b4d7a53' \
      -H "Authorization: Bearer $RECURSION_API_KEY"

    curl 'https://api.recursion.labelbox.com/managed-agents/v1/files/7c3d9e1a-4b5f-4a2e-8d61-0f9b2c7e5a38/content' \
      -H "Authorization: Bearer $RECURSION_API_KEY" \
      -o risks.md
    ```
  </Tab>
</Tabs>

Subagent and teammate deliverables are listed under the root session. `getFileContent` returns the bytes as `application/octet-stream` with a `Content-Disposition` naming the file. The recorded media type is in the file's metadata.

## List and find files

`listFiles` returns your organization's files, newest first, with a `next_page_token` while more follow. Filter by `source` to see only uploads or only session outputs.

```bash theme={"theme":"css-variables"}
curl 'https://api.recursion.labelbox.com/managed-agents/v1/files?source=upload&limit=50' \
  -H "Authorization: Bearer $RECURSION_API_KEY"
```

`getFile` returns one file's metadata: `filename`, `media_type`, `byte_size`, `sha256`, `source`, `expires_at`, and, for a session output, `scope_session_id` and the agent it belongs to.

```bash theme={"theme":"css-variables"}
curl 'https://api.recursion.labelbox.com/managed-agents/v1/files/9f8b1c2d-3e4f-5a6b-7c8d-9e0f1a2b3c4d' \
  -H "Authorization: Bearer $RECURSION_API_KEY"
```

<Accordion title="List parameters and expired files">
  | Parameter | Description |
  | - | - |
  | `source` | `upload` or `session_output`. |
  | `scope_session_id` | Only the files this session produced. |
  | `file_ids` | Up to 100 ids, comma-separated or repeated, answered as one page. Can't be combined with `limit` or `page_token`. |
  | `limit`, `page_token` | Page size, 1 to 1,000 with a default of 200, and the cursor from the previous page. Send the same filters with the token. |

  An expired file stays listed, with `expires_at` in the past, until it's removed after a grace period, but it can no longer be attached or downloaded.
</Accordion>

## How files reach a session

```mermaid theme={"theme":"css-variables"}
flowchart TD
  upload["Upload a file"] --> library["Organization files"]
  library -->|"attach"| inputs[".managed-agents/files<br>read-only"]
  library -->|"name in a message"| message["Image or document<br>in the message"]
  agent["Agent saves a deliverable"] --> outputs[".managed-agents/outputs"]
  outputs -->|"kept after each turn"| library
```

Uploads reach a session by attachment or by name in a message. Deliverables the agent saves return to your organization's files after each turn.

## What can go wrong

The most common problems:

* **`404 not_found` when a session request names a `file_id`.** The file doesn't exist in your organization or has expired. Use a live file id from `listFiles`.
* **The agent can't find an attached file.** It was attached mid-turn. It's in place on the next tool call and visible from the next turn. Check `mount_path` on the resource.
* **A deliverable isn't in the outputs.** The agent saved it somewhere else, or it broke a capture rule. See [Deliverables and artifacts](/recursion/artifacts#what-can-go-wrong).

<Accordion title="Every files error">
  | Code or symptom | Cause | Fix |
  | - | - | - |
  | The console refuses a file | It is over 1 GiB. | Split it into smaller files. |
  | `413 payload_too_large` from `uploadFile` | The file part is over 30 MiB. | Upload a file of at most 30 MiB through the API, or use the console for a larger file. |
  | `413 file_quota_exceeded` on upload | The upload would exceed your organization's live-file storage quota. | Set expiries on API uploads so they stop counting once they expire. |
  | `404 not_found` when a session request names a `file_id` | The file doesn't exist in your organization or has expired. | Use a live file id from `listFiles`. |
  | A file can't be attached mid-session | Its path collides with or nests inside another attachment, or the session isn't the root of its tree. | Choose another path, or attach to the root session. |
  | `400 invalid_request` on a message's `source.file_id` | The file isn't an image on an image block, or is binary or too large on a document block. | Send PNG, JPEG, or WebP images, and text documents up to 512 KiB. |
  | The agent can't find an attached file | It was attached mid-turn. | It's in place on the next tool call and visible from the next turn. Check `mount_path` on the resource. |
  | A deliverable isn't in the outputs | The agent saved it somewhere else, or it broke a capture rule. | See [Deliverables and artifacts](/recursion/artifacts#what-can-go-wrong). |

  For every error code, see [Errors](/recursion/errors).
</Accordion>

Limits on uploads, storage, expiry, attachments, list pages, files named in a message, and deliverables are in [Limits](/recursion/limits).

## Next steps

<CardGroup cols={2}>
  <Card title="Deliverables and artifacts" href="/recursion/artifacts">
    Ask for named deliverables and see how they're kept.
  </Card>

  <Card title="Sessions" href="/recursion/sessions">
    Start sessions, send messages, and attach images.
  </Card>

  <Card title="Automations" href="/recursion/automations">
    Mount the same files into every automated run.
  </Card>
</CardGroup>
