Compute Workspace

Storage

Per-tenant object storage, outputs produced by skills and dedicated tasks land here, auto-filed into a folder named after the producing skill.

How it works

Every workspace has its own object store. When a skill or dedicated task writes an output, an object row is registered, a storage_key in the tenant bucket plus category, source, size_bytes and an optional task_id. Runs auto-file into a folder named after the producing skill; you can create your own folders to organize further. Every route is scoped by business_profile_id, the workspace the hyb_* key belongs to.

Browse folders and objects

GET/api/v1/tenant-objects/folders
GET/api/v1/tenant-objects

List folders (each with an object count and total bytes), or list objects directly. Pass task_id to narrow objects to a single dedicated-task run, or folder_id to one folder.

ParameterTypeDescription
business_profile_idrequiredstring (uuid)The workspace to list.
task_idstringFilter objects to one dedicated-task run.
folder_idstring (uuid)Filter objects to one folder.
CLI
stimulir storage folders
stimulir storage list
stimulir storage list --task-id <task-id>
SDK
from stimulir import StimulirClient

client = StimulirClient()  # reads STIMULIR_API_KEY
wid = "<workspace-id>"

folders = client.storage.folders(workspace_id=wid)
objects = client.storage.list(workspace_id=wid, task_id="<task-id>")

The list route returns the 100 most-recent objects and is not paginated, key lookups (below) resolve against that window.

Upload an input

POST/api/v1/tenant-objects/upload-url

Uploads go through a presigned PUT URL: mint the URL, then upload the bytes to it. The returned storage_key is what a sandbox run expects as its input_key, the on-ramp for a fully SDK-driven pipeline. The key is always scoped under the workspace's own prefix, so a caller can't write outside their tenant.

ParameterTypeDescription
business_profile_idrequiredstring (uuid)The workspace to upload into.
filenamestringStorage filename. Defaults to input.bin.
CLI
# Uploads the file and prints its storage key
stimulir storage upload ./data.jsonl --name data.jsonl
SDK
with open("data.jsonl", "rb") as f:
    input_key = client.storage.upload(f, workspace_id=wid, filename="data.jsonl")

Signed access URL

POST/api/v1/tenant-objects/:object_id/access-url

Mint a time-limited signed URL for an object you already know by id (from storage list). Set download to serve it with a Content-Disposition: attachment header.

ParameterTypeDescription
expires_in_secondsintegerSigned URL TTL. Default 900; clamped to 60–3600.
downloadbooleanServe as an attachment. Default false.
CLI
stimulir storage link <object-id> --expires-in 900
stimulir storage link <object-id> --download
SDK
access = client.storage.access_url("<object-id>", expires_in_seconds=900)
print(access["access_url"])

Fetch by key

A sandbox run hands back a storage_key (its output_key), not an object id. Fetch-by-key closes that loop: it matches the key to an object among the most-recent 100, mints an access URL, and (optionally) downloads the bytes. This is the read side of the SDK-driven pipeline, upload → run → read.

CLI
# Print a signed URL for a run's output_key
stimulir storage get --key <output-key>

# Or download the bytes to a file
stimulir storage get --key <output-key> --output result.jsonl
SDK, the full pipeline
# 1. upload an input
with open("data.jsonl", "rb") as f:
    input_key = client.storage.upload(f, workspace_id=wid, filename="data.jsonl")

# 2. run a skill / dedicated task in the sandbox, which returns an output_key
output_key = client.sandbox.run(input_key=input_key, ...)["output_key"]

# 3. read the result straight back by key
data = client.storage.read_by_key(output_key, workspace_id=wid)

# get_by_key returns the object + signed URL instead of the raw bytes
info = client.storage.get_by_key(output_key, workspace_id=wid)

Fetch-by-key resolves against the 100 most-recent objects only, a key older than that window raises a 404. Use it right after a run, while the output is fresh.

Delete

DELETE/api/v1/tenant-objects/:object_id

Deleting an object removes both the backing file in the bucket and its record.

CLI
stimulir storage delete <object-id>
SDK
client.storage.delete("<object-id>")

For where these keys come from, running a skill or dedicated task and getting an output_key back, see Sandbox.