Skip to main content
Every Polpo Cloud project gets a volume — a persistent filesystem shared across all agents in the project. Files survive across tasks, chat sessions, and sandbox restarts.

How it works

When you create a project on Polpo Cloud, a dedicated volume is provisioned automatically. Every time an agent runs (via task or chat completions), the volume is mounted into the agent’s sandbox:
/home/polpo/project/
├── workspace/        ← agent workspace (code, dependencies, git history)
│   ├── src/
│   ├── package.json
│   ├── node_modules/
│   └── .git/
└── .polpo/           ← polpo configuration & data
    ├── agents.json
    ├── memory/
    ├── skills/
    └── vault.enc
All agents in the project share the same volume. When one agent writes a file, other agents see it immediately (on next task). Memory, skills, and configuration are also stored here.

Volume in the dashboard

The Storage tab in the dashboard provides a file browser for your project volume. You can:
  • Browse files and directories across both roots (workspace and .polpo)
  • Upload files (drag & drop or file picker)
  • Download files
  • Rename and delete files
  • Search across the filesystem

Files API

Access the volume programmatically via the Files API.

List roots

Returns the filesystem roots that the file browser can navigate.
const roots = await client.files.roots();
// [
//   { id: "workspace", name: "workspace", totalFiles: 142, totalSize: 4821033 },
//   { id: "polpo", name: ".polpo", totalFiles: 12, totalSize: 8401 },
// ]

List directory

const listing = await client.files.list({ path: "workspace/src" });
// {
//   path: "workspace/src",
//   entries: [
//     { name: "app", type: "directory" },
//     { name: "index.ts", type: "file", size: 1204, mimeType: "text/typescript" },
//   ]
// }

Preview file

Returns the file content. Text files are returned as-is, binary files as base64.
const content = await client.files.preview({ path: "workspace/src/index.ts" });

Upload

await client.files.upload({
  path: "workspace/public",
  file: buffer,           // Buffer or Uint8Array
  filename: "logo.png",
});

Create directory

await client.files.mkdir({ path: "workspace/src/components" });

Rename

await client.files.rename({
  path: "workspace/src/old-name.ts",
  newName: "new-name.ts",
});

Delete

await client.files.delete({ path: "workspace/src/unused.ts" });
Recursive flat file listing with optional query filter.
const results = await client.files.search({ q: "layout", root: "workspace" });
// [{ name: "layout.tsx", path: "src/app/layout.tsx" }, ...]

Volume lifecycle

EventWhat happens
Project createdVolume provisioned automatically
Agent runsVolume mounted into sandbox at /home/polpo/project/
Agent finishesSandbox may stop, but volume persists
New agent runsSame volume mounted — sees all previous changes
Project deletedVolume destroyed (irreversible)
The volume is independent of sandboxes. Sandboxes are ephemeral compute — they start, run an agent, and stop. The volume is the persistent state that connects them.

Volume and agents

When an agent runs (via chat completions or tasks), its tools operate on the volume:
  • read, write, edit — read/write files on the volume
  • bash — run commands with the volume as working directory
  • glob, grep — search files on the volume
This means an agent can install dependencies, commit code, and build artifacts — and the next agent (or next chat message) will see everything exactly as it was left.

Self-hosted

In self-hosted mode, there is no Daytona volume. The project directory (workDir) serves as the persistent filesystem directly. The Files API works the same way — it just reads from disk instead of a remote volume.

API reference

See the full Files API reference for all endpoints, request/response schemas, and examples.