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

# Files

> Durable, organization-scoped storage for the artifacts a session produces.

**Files** is durable, organization-scoped storage: where inputs you upload and artifacts an agent chooses to keep live, independent of any single session's lifetime. Scratch work stays in the session sandbox; anything the agent should hand back goes to Files, where it persists until you delete it.

## Uploading inputs

Upload files up front for the agent to work against, then list or download them.

<CodeGroup>
  ```bash CLI theme={"system"}
  vetta file upload --file ./data/orders.csv --name orders.csv
  vetta file list
  vetta file download <file_id> > ./out/orders.csv
  ```

  ```typescript TypeScript theme={"system"}
  const form = new FormData();
  form.append("file", new Blob([bytes], { type: "text/csv" }), "orders.csv");
  const file = await vetta.files.upload(form);
  const list = await vetta.files.list();
  const csv = await vetta.files.download(file.id);
  ```
</CodeGroup>

## Getting inputs in front of an agent

Files travel **outward** by default. Uploading puts bytes in org storage; it does not put them in the agent's [computer](/docs/capabilities/computer), and a [session](/docs/concepts/sessions#create-a-session) takes no `files[]` — there is no create-time mount. What crosses the other way is the agent's own [`fetch_file`](/docs/capabilities/tools#reading-a-file-back-into-the-sandbox) call: upload the input, name its `fil_` id in the session's first `message`, and the agent writes it into its own workspace when it needs the bytes. For anything small, put the content in the first `message` itself; for anything on the open web, let the agent fetch it with [`web_fetch`](/docs/capabilities/tools#web-tools) or `bash`.

```bash CLI theme={"system"}
vetta session create --agent Analyst \
  --message "Reconcile these orders against last month's ledger: $(cat ./data/orders.csv)"
```

The loop a session completes is therefore **agent works → `publish_file` → in Files, durably**.

## Two kinds of storage

| Where               | Scope                                                       | Lifetime                            |
| ------------------- | ----------------------------------------------------------- | ----------------------------------- |
| **Session sandbox** | The session's [computer](/docs/capabilities/computer) filesystem | Deleted when the session is deleted |
| **Files API**       | Your organization                                           | Persists until you delete it        |

Scratch work belongs in the sandbox. Anything the agent should hand back belongs in Files.

## Publishing an artifact

The built-in **`publish_file`** tool promotes a file from the session sandbox into the persistent Files store. It is not the only writer: what [`generate_image` or `generate_video`](/docs/capabilities/tools#generation-tools) produces also lands here, and the session is told the new `fil_` id. This is how a finished session leaves deliverables behind without a mandatory "deliver" step — the session simply goes [idle](/docs/concepts/sessions#lifecycle) and its published files remain.

```
# from inside the agent's reasoning, it calls:
publish_file(path="/workspace/report.pdf", name="Q3-refund-report.pdf")
```

The tool takes a sandbox `path` and returns the new **published** file's id, name and size so the id can flow into a [structured output](/docs/capabilities/structured-outputs) or webhook. The file keeps the `session_id` as provenance but does not die with the session.

<ParamField path="path" type="string" required>
  Absolute path of the artifact in the session sandbox, e.g. `/workspace/report.pdf`.
</ParamField>

<ParamField path="name" type="string">
  The name to store it under in Files. Defaults to the basename of `path`.
</ParamField>

<ParamField path="content_type" type="string">
  MIME type; the library's `kind` (`image`, `video`, `audio`, `document`, `other`) is derived from it.
</ParamField>

<ParamField path="title" type="string">
  A human title for the asset library.
</ParamField>

<ParamField path="tags" type="string[]">
  Labels to find it by later with `find_files`.
</ParamField>

### Name collisions

Names in Files are **not** unique keys — every publish creates a distinct file object with its own id, and a repeated `name` is stored as-is, so both remain listed. Key off the returned `id`, not the display `name`.

## Finding assets again

Everything in Files is also the organization's **asset library**: every file carries a `kind`, a `source` (who wrote it — an upload, a URL import, an image or video generation, a clip, a screenshot, a speech generation), optional `title`, `description` and `tags`, and an image's pixel dimensions. An agent retrieves earlier assets with the built-in **`find_files`** tool:

```
find_files(query="hero", kind="image", tag="launch", limit=20)
```

It returns ids and metadata only — never bytes — so the agent can pass a `fil_` id on, or the same filters drive `vetta file list --kind --tag --search` and `client.files.list()`. Bring an asset in from the web with `vetta file import <url>` (the API fetches it server-side, so private and local addresses are refused), and describe any file after the fact with `vetta file update`. See [Files](/docs/api/files).

## Bringing an asset back into the sandbox

`find_files` stops at the id, and so does every generator — a [`generate_video`](/docs/capabilities/tools#generation-tools)
render is saved from the provider straight to storage and never lands on the computer's disk. The
built-in **`fetch_file`** tool is the inverse of `publish_file`: it writes files the organization
already holds into the session's sandbox, by id, so the agent can work on the bytes.

```
# from inside the agent's reasoning, it calls:
fetch_file(file_ids=["fil_seg1", "fil_seg2", "fil_seg3"], dir="segments")
```

This is the step that has to come first whenever a rendered asset is an *input* rather than a
deliverable — joining a 60–180s piece out of 30-second segments, overlaying a generated voiceover,
re-encoding for a platform that wants a different container. Pull the files down, do the work in the
shell, and `publish_file` the result as a new file. Up to eight ids a call and 64 MiB a file,
resolved against your organization's library and nobody else's; a session with no computer is
refused by name. See [Tools](/docs/capabilities/tools#reading-a-file-back-into-the-sandbox).

## Reading a session's outputs

```bash CLI theme={"system"}
vetta file list --session $SID           # session-scoped + published
```

<Warning>
  Cancelling a session releases its sandbox, and the files it produced *in the sandbox* go with it. Files promoted with `publish_file` or uploaded through the Files API are organization-scoped and survive. Publish anything you need to keep before cancelling. See [Session operations](/docs/concepts/session-operations#archiving).
</Warning>

<Card title="Next: tools & plugins" icon="plug" href="/docs/capabilities/tools">
  The extension point every capability plugs into.
</Card>
