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

# Files & Document Storage

> Accept uploads, persist files, store file metadata, and pass documents to AI.

SLang represents uploaded and stored files with the `FILE` type. A `FILE` value carries file metadata and can be streamed, stored, downloaded, or passed to modules such as `AI.prompt`.

## Upload and Store a File

HTTP file uploads are exposed through `@request.files.<fieldName>`. Use `store fileValue` to persist the upload to Sutro object storage before saving it on an entity.

```slang theme={null}
import "AI"

entity User
  subject
  identity email
  fields
    email: EMAIL
    displayName: TEXT?

entity Document
  fields
    title: TEXT
    file: FILE
    summary: TEXT?

relation User[documents] 1 --- 0..* Document[owner]

action UploadDocument(title: TEXT, file: FILE): Document
  body
    user := @subject.entity
    storedFile := store file
    document := create Document {
      owner := user
      title := title
      file := storedFile
    }
    return document

action SummarizeDocument(documentId: TEXT): Document
  body
    user := @subject.entity
    document := single Document where @id == documentId and owner == user
    summary := AI.prompt(
      message := "Summarize the uploaded document.",
      attachments := [document.file],
      provider := "openai",
      maxTokens := 600
    )
    update document {
      summary := summary
    }
    return document

trigger UploadDocument on HttpRequest
  endpoint POST /documents
  arguments
    title := @request.body.title
    file := @request.files.file
  auth
    @subject is @defined

trigger SummarizeDocument on HttpRequest
  endpoint POST /documents/{documentId}/summary
  arguments
    documentId := @request.path.documentId
  auth
    @subject is @defined
```

Clients should send upload requests as `multipart/form-data` with a file field matching the trigger binding. In the example above, the field name is `file`.

## What `store` Returns

`store` accepts a `FILE` and returns a persisted `FILE`. The stored value keeps the original file name, MIME type, size, and a Sutro storage location. Persisted `FILE` values can be saved on entities and later used in actions.

Use `store` when the file must survive after the current request. If an action only needs to process the upload immediately, it can pass the request file directly to another function or module without storing it first.

Uploaded or stored `FILE` values can also be used as top-level request bodies
with `HTTP.fetch` for outbound raw binary uploads. `HTTP.fetch` sends the file
bytes unchanged and uses the file MIME type as the request `content-type` unless
you provide one explicitly.

`HTTP.fetch` can also return downloaded bytes as a `FILE` when you pass
`responseType := "file"`. Store the returned file before saving it on an entity
if it must survive after the current action.

## File Fields

Use `FILE` fields for documents, images, PDFs, CSVs, or any uploaded blob that should be attached to an entity.

`FILE` values are especially useful with:

* Document upload workflows.
* AI prompts with `attachments := [document.file]`.
* Audit records that need to retain source files.
* Imported data pipelines where a queue processes an uploaded file later.

## Upload Limits

Generated app HTTP routes accept multipart uploads for trigger arguments bound from `@request.files`. The local and generated runtimes enforce upload limits before the SLang action runs, so oversized uploads fail at the HTTP layer.
