Storage
Every workspace has an S3-compatible bucket of its own: MinIO under
stackbone dev, whatever bucket you point the deployed box at in production. Your code reads and writes it throughstackbone.storage, with keys the runtime prefixes per agent so two agents never touch each other's files. The Storage screen in Studio browses that same bucket, uploads into it, and hands any object out with a signed URL that expires.
Every key your code writes lands under the agent's own namespace, so an agent
that writes reports/q3.md into the exports bucket ends up at
<agent>/exports/reports/q3.md in the physical bucket. The explorer shows the
part after the agent's prefix, and the SDK refuses a key with .. in it, so a
key an end user typed cannot escape that namespace.
Browse, upload and share from Studio
Open Storage under Data. The screen is a file explorer over the bucket: walk into a folder, create one with New folder, drop files onto the list or click Upload file, and Delete an object. Click an object and a panel opens with its key, a preview when it is text, and a signed URL you mint with a time to live.
A file the agent wrote during a conversation, opened from Studio: the key, a signed URL that expires in an hour, and the content.
A folder created from the screen, with two files uploaded by hand.
A signed URL is how a file leaves the box: it points at the object in your own
bucket, it works for the seconds you chose, and it needs no credential from
whoever opens it. Under rag/ the screen only lists and downloads. Uploading,
overwriting or deleting there would leave a document with no chunks behind it,
so only the RAG screen writes to that folder.
Uploading, creating a folder and deleting take the member role or above.
Every role, a viewer included, can browse the bucket and mint a signed URL.
From your code
Inside a tool or a workflow step, pick a logical bucket and use it. The runtime injected the credentials when the box booted, so there is no client to build:
import { stackbone } from '@stackbone/sdk';
async function publishReport(markdown: string) {
'use step';
const exports = stackbone.storage.from('exports');
const saved = await exports.upload('reports/q3.md', markdown, { contentType: 'text/markdown' });
if (saved.error) throw new Error(saved.error.code);
// Hand the file to a person without streaming it yourself.
const link = await exports.getSignedDownloadUrl('reports/q3.md', { expiresIn: 300 });
if (link.error) throw new Error(link.error.code);
return { url: link.data.url };
}Two patterns come up often. A tool that needs a file from the user mints a signed upload URL and returns it, so the user's browser puts the bytes straight into the bucket and the agent never carries them. A workflow that produces a report writes it here and returns the signed download URL as its result, which is what a run's Final output then shows in Studio.
Where the bucket lives
| Environment | Bucket |
|---|---|
stackbone dev |
A MinIO container started for you, with its bucket already made. Nothing to configure. |
The folder stackbone package writes |
A MinIO in the same Compose file. A one-shot container creates the bucket, and the agent waits for it before it serves. Or point .env at your own bucket. |
| A box you run your own way | The STACKBONE_S3_* variables on the container. |
Any S3-compatible backend works (AWS S3, Cloudflare R2, Azure Blob, Google Cloud Storage, Railway Buckets, another MinIO). Create the bucket yourself first: only the bundled MinIO gets one made for it.
One variable decides the address form.
STACKBONE_S3_FORCE_PATH_STYLE defaults to true, which puts the bucket in the
path (https://host/bucket/key) and is what MinIO and Cloudflare R2 accept. Set
it to false for a backend that only answers to the subdomain form
(https://bucket.host/key), such as AWS S3 and Railway Buckets. The wrong value
fails every call with NoSuchBucket or a bare 403 while the credentials are
fine, so check it before you suspect the keys. See
path-style or subdomain.
Note
Check the storage sdk and storage cli documentation for more details.
Read more
stackbone.storage: upload, download, list, remove, public and signed URLs, configuration and errors.- Retrieval: the documents behind the
rag/folder. - Agents: the file tools a deep agent gets, and where they write.
stackbone package: the Compose bundle with MinIO and its bucket in it, and every variable you set on the deployed container.