Skip to main content
Files live on the instance’s disk. A file’s absolute path is its identity: there are no file ids, so the path you list is the path you read, write, move, or delete. You write a file with one call, attach the returned path to a message, and download anything the agent produces by path. The base URL is your instance URL, https://{instanceId}.agent37.app, with the same sk_live_ key as every other call, sent as the X-Agent37-Key header. This page uses https://ab12cd34ef.agent37.app. The agent’s workspace — where it reads and writes by default — is /home/user/.agent37-gateway/workspace, and that is the default directory for a list with no path. These calls are not jailed to the workspace. The sk_live_ key is the instance root: any path the key can reach on the instance’s filesystem is fair game, with ~ expanding to the agent’s home. Treat the key accordingly.
Every timestamp here is modified, the file’s mtime in epoch milliseconds — the Agent API convention (the Hosting API uses seconds). It is a number, not an ISO string.

The file entry

List responses and every write return the same FileEntry shape, so the path you get back from a write is ready to use on the next call.
name
string
The basename, e.g. leads.csv.
path
string
The resolved absolute path on the instance. This is the identity you pass to every other call and to files on POST /v1/responses.
type
string
file, directory, symlink, or other (sockets, devices, FIFOs).
size
integer | null
Size in bytes; null for directories.
modified
number
Last-modified time (mtime) in epoch milliseconds.
hidden
boolean
true when the name starts with ..

List a directory

GET /v1/files lists one directory level. Omit path to list the agent’s workspace; pass an absolute path or a ~/ path to list anywhere the key can reach. Entries are sorted directories first, then by name case-insensitively.
path
string
The directory to list. Optional; defaults to the agent’s workspace, /home/user/.agent37-gateway/workspace. Accepts absolute and ~/ paths. A path that exists but is not a directory returns 400 not_a_directory.
path
string
The resolved absolute path of the directory you listed.
parentPath
string | null
The parent directory’s absolute path, or null at the filesystem root.
entries
array
The directory’s immediate children as FileEntry objects. One level only — this never recurses.
truncated
boolean
true when the directory holds more than 1000 entries; only the first 1000 (after sorting) are returned.

Read, preview, or download a file

GET /v1/files/content?path=… streams a file off the instance — typically one the agent told you it wrote. Any size; the 512 KB exec output cap does not apply here. The Content-Type is set from the file extension.
path
string
required
The file to read. Accepts absolute and ~/ paths. A missing or empty path, or a path that is not a regular file, returns 400 validation_error; no file at the path returns 404 file_not_found.
disposition
string
default:"attachment"
attachment sends Content-Disposition: attachment so a browser downloads the file. inline sends Content-Disposition: inline so a browser renders it (useful for previews).
Serving an agent-produced file inline runs it on your origin. HTML, SVG, and similar can execute scripts in the page that opens them, so an instance whose agent writes attacker-controlled content can run code against your users. Render untrusted files in a sandboxed frame (<iframe sandbox>) on an isolated origin, or force a download with disposition=attachment.

Download a folder

GET /v1/files/archive?path=… streams a whole directory as a gzipped tar (.tar.gz) — the one call to pull a tree instead of walking it file by file. The archive is built on the fly and streamed, so any size works and the 512 KB exec output cap does not apply. It unpacks to a single top-level folder named after the directory you packed.
path
string
The directory to archive. Optional; defaults to the agent’s workspace, /home/user/.agent37-gateway/workspace. Accepts absolute and ~/ paths. No directory at the path returns 404 file_not_found; a path that exists but is not a directory returns 400 not_a_directory.
The response is Content-Type: application/gzip and a Content-Disposition: attachment whose download filename is the packed directory’s name plus .tar.gz (characters outside A–Z a–z 0–9 . _ - and space are stripped, and an empty result falls back to archive). Symlinks are stored as links, not followed, so the archive never inlines a link target’s bytes.
Expand it with tar -xzf reports.tar.gz. There is no folder-upload counterpart: to upload a tree, recreate it with per-file PUT /v1/files/content calls — each creates any missing parent directories (mkdir -p).

Write a file

PUT /v1/files/content?path=… writes the raw request body to path — this is the one call for create, overwrite, edit, and upload. It is not multipart: the body is the file’s exact bytes. Missing parent directories are created (mkdir -p). The response is the written file’s FileEntry.
path
string
required
Where to write. Accepts absolute and ~/ paths; parent directories are created as needed. A missing or empty path returns 400 validation_error.
overwrite
boolean
default:"true"
true replaces an existing file. false makes the write fail with 409 file_exists if a file is already at path.
X-Expected-Mtime
integer
Optional optimistic-concurrency guard, epoch milliseconds. When the file exists and its modified differs from this value, the write fails with 412 modified — someone changed it since you read it. Ignored when the file does not exist (the write is treated as a create).
Attach a file to a turn. Write the bytes, then pass the returned path in the files array on POST /v1/responses:
Each entry must name an existing file on the instance, or the call returns 400 validation_error.

Delete a file or directory

DELETE /v1/files?path=… removes the path recursively and by force, like rm -rf — a directory and everything under it goes in one call. There is no confirmation and no guard, so a wrong path is unrecoverable. A symlink is removed itself, not followed. The response is { "ok": true }.
path
string
required
The file or directory to delete. Accepts absolute and ~/ paths. A missing or empty path returns 400 validation_error.
Delete is recursive and unguarded. It removes whatever the key can reach, including directories full of files, with no undo. Double-check path before you send it.

Rename or move a file

PATCH /v1/files renames or moves a path with fs.rename, taking a body of { "from", "to" }. The OS decides the edge cases — overwriting an existing to, moving into a directory, crossing devices — so behavior matches a shell mv. The response is the FileEntry of the new path.
from
string
required
The current path. Accepts absolute and ~/ paths. Empty returns 400 validation_error.
to
string
required
The new path. Accepts absolute and ~/ paths. Empty returns 400 validation_error.

Create a directory

POST /v1/files/dir?path=… creates a directory and any missing parents (mkdir -p). It is idempotent: a path that already exists returns its FileEntry rather than erroring.
path
string
required
The directory to create. Accepts absolute and ~/ paths; parents are created as needed. A missing or empty path returns 400 validation_error.

The loop

The common cycle is write, attach, fetch:
  1. PUT /v1/files/content?path=… with the input bytes; keep the returned path.
  2. POST /v1/responses with your input and that path in files.
  3. When the agent replies that it wrote a file, GET /v1/files/content?path=… to fetch it — or GET /v1/files to browse what it left behind.