Skip to content

Per-agent sandbox

The wedge: every Claude / GPT / custom-agent run gets its own database or its own branch. Idempotent on a ref, auto-deleting on a TTL, no per-branch fee.

import { PerSQL } from "@persql/sdk";
import { randomUUID } from "node:crypto";
const persql = new PerSQL({ token: process.env.PERSQL_TOKEN! });
const db = persql.database("acme/orders");
// Idempotent — call as many times as you like with the same ref.
const branchRef = `run-${randomUUID()}`;
await db.branches.upsert(branchRef, {
expiresAt: new Date(Date.now() + 24 * 60 * 60 * 1000), // auto-clean in 24h
});
const branch = persql.database("acme", `orders.${branchRef}`);
await branch.query("INSERT INTO scratchpad (note) VALUES (?)", ["hello"]);

No request or row charges until the agent issues its first query. Storage is metered from the moment data lands — a fresh database created with databases.create() starts empty, so a CI pipeline that spins up run-${uuid} and never writes to it pays nothing for the empty ones. A branch copies the parent’s schema only — no rows — so a branch of a populated production DB also starts empty and adds essentially no storage until the agent writes to it; you then pay only for the rows it creates at $0.40/GB-month, and the auto-delete TTL keeps that bounded. No per-branch fee.

Once your agent has scratch space, point it at the schema with db.describe() — one round-trip and the LLM has every table, column, FK, and stored description it needs to write SQL.

const schema = await branch.describe();
// → { databaseDescription, tables: [{ table, columns, foreignKeys, ... }] }