mountable.io

Cookbook: a capped workspace for every end user

Create one mountable.io filesystem per end user from your SaaS backend, set a hard monthly spend cap, handle the 402 response, and read usage back.

You run a multi-user agent app. Each end user gets an agent that writes files.

mountable.io is a persistent filesystem for AI agents. Give each end user their own filesystem.

Your backend sets a hard monthly spend cap on that filesystem. When one user reaches their cap, their billable work stops. Your other users keep working.

This page is the step-by-step. Limits per end user is the full field and error reference.

Before you start

Use an existing mountable.io account with a saved payment method. Caps are in your billing currency, so a saved payment method is required.

Keep MOUNTABLE_API_KEY in your backend environment. Use a key that is not limited to one filesystem, owned by an owner or admin.

Your backend chooses the end user, the filesystem and the cap. Do not let model output choose another user's filesystem or raise a cap.

1. Create the workspace when a user signs up

Create one filesystem per end user, once. Set the limits in the create call, so there is never a moment without them.

from mountable_sdk import Mountable
 
client = Mountable()  # reads MOUNTABLE_API_KEY
user_fs = client.create_filesystem(
    f"user-{user.id}",
    spending_cap_cents=500,
    mutations_per_minute=120,
    byte_quota=5 * 1024**3,
    entry_quota=50_000,
)
# Save user_fs.id on your own user record before you run any agent for them.
import { Mountable } from "mountable-sdk";
 
const client = new Mountable(); // reads MOUNTABLE_API_KEY
const userFs = await client.createFilesystem(`user-${user.id}`, {
  spendingCapCents: 500,
  mutationsPerMinute: 120,
  byteQuota: 5 * 1024 ** 3,
  entryQuota: 50_000,
});
// Save userFs.id on your own user record before you run any agent for them.

This user can spend at most $5.00 (or €5.00) a month, make 120 changes a minute, and store 5 GiB in 50,000 entries.

Store the returned filesystem id next to your user record. Look it up from your authenticated user on every later call. Do not create a new filesystem on every agent run.

If a create call times out, list your filesystems before you retry. The workspace may already exist.

2. Handle the 402 response

When that user reaches their cap, billable work on their filesystem is refused. Stored files stay in place.

The Files API and the SDKs report 402 with code filesystem_spending_cap_reached. Catch it and stop that user's billable work. Do not retry it in a loop.

from mountable_sdk import MountableError
 
fs = client.filesystem(user_fs.id, mode="rw")
try:
    fs.write("report.md", report_text)
except MountableError as e:
    if e.code == "filesystem_spending_cap_reached":
        stop_billable_work(user)  # this user only; everyone else keeps working
    elif e.code == "spending_cap_reached":
        stop_billable_work_for_org()  # your organisation cap was reached
    else:
        raise
import { MountableError } from "mountable-sdk";
 
const fs = client.filesystem(userFs.id, "rw");
try {
  await fs.write("report.md", reportText);
} catch (e) {
  if (e instanceof MountableError && e.code === "filesystem_spending_cap_reached") {
    stopBillableWork(user); // this user only; everyone else keeps working
  } else if (e instanceof MountableError && e.code === "spending_cap_reached") {
    stopBillableWorkForOrg(); // your organisation cap was reached
  } else {
    throw e;
  }
}

spending_cap_reached means your organisation cap was reached. Raising one user's cap does not help then. Whichever cap is reached first stops the work.

A rate limit is separate. On 429 rate_limited, wait retry_after seconds in Python or retryAfter in TypeScript, then retry.

3. Read usage and show what is left

Read the filesystem's limits and this month's usage. Usage carries reserved_cents: how much of this month's cap the filesystem already uses.

limits = client.get_filesystem(user_fs.id)
usage = client.filesystem_usage(user_fs.id)
left_cents = None
if limits.spending_cap_cents is not None:
    left_cents = limits.spending_cap_cents - usage.reserved_cents
const limits = await client.getFilesystem(userFs.id);
const usage = await client.filesystemUsage(userFs.id);
const leftCents =
  limits.spendingCapCents === null ? null : limits.spendingCapCents - usage.reservedCents;

Show left_cents in your billing currency next to the user's workspace. The cap counts a full month at the filesystem's highest stored size and file count this month, plus downloads. Deleting files does not free this month's peak. Limits per end user explains the counting.

Next steps