Workspace database
Every workspace can have a real managed Postgres behind it: your agent's durable memory, the table a pipeline writes into, the rows a canvas charts. Your agent reaches it through its own tools, and your backend reaches the same database over REST.
What you get
A Postgres database scoped to the workspace, provisioned the first time something asks for it. There is no create step in your code: the first call provisions it if the organization is entitled to one.
Provisioning takes a moment, and the API tells you so in band rather than failing. While the database is coming up, every /v1/db/* route answers HTTP 202 with the current status and an instruction to retry.
{
"success": true,
"data": { "status": "provisioning" },
"message": "Database is still provisioning. Retry shortly."
}If the organization is not entitled to a database at all, the answer is HTTP 402 PLAN_LIMIT_REACHED instead, naming the fix. Nothing is provisioned and nothing is charged.
From an agent
Over MCP the database is the agnt_db_* family, served on the base connection with nothing to enable.
| Tool | What it does |
|---|---|
agnt_db_status | Is the database provisioned and reachable. |
agnt_db_list_tables | Tables with their columns, types and RLS status. |
agnt_db_list_extensions | Installed Postgres extensions. |
agnt_db_list_migrations | Migrations applied so far. |
agnt_db_apply_migration | Apply a named DDL migration. |
agnt_db_execute_sql | Run SQL directly. |
agnt_db_select | Read rows with filters and ordering. |
agnt_db_insert | Insert rows. |
agnt_db_upsert | Insert or update on conflict. |
agnt_db_update | Update matching rows. |
agnt_db_delete | Delete matching rows. |
agnt_db_load_csv | Bulk-load a CSV already held in workspace files into a table. |
deployed agents use their own path
/v1/db/*. It reaches the same database through its runtime path, which is what keeps its table allowlist, its read-only setting and its audit attribution in force. Both surfaces run the same underlying implementation, so the contract is identical; only the policy layer differs.From your backend
/v1/db/* takes the same Authorization: Bearer <key> as the rest of the API and is scoped to that key's workspace.
| Route | What it does |
|---|---|
POST /v1/db/sql | Run SQL. Destructive statements need confirm; more than one statement needs allowMultiStatement; reads are capped at 1000 rows. |
GET /v1/db/tables | List tables in the public schema. |
GET /v1/db/tables/:name | Columns, types, nullability, defaults and indexes for one table. |
POST /v1/db/tables | Create a table from a column list. |
PATCH /v1/db/tables/:name | Add or drop columns. Dropping needs confirm. |
DELETE /v1/db/tables/:name | Drop a table. Requires ?confirm=true. |
GET /v1/db/rows/:table | Read rows with repeatable filter params, order, limit and offset. |
POST /v1/db/rows/:table | Insert one row or a batch. |
PATCH /v1/db/rows/:table | Update rows. Requires at least one filter. |
DELETE /v1/db/rows/:table | Delete rows. Requires at least one filter. |
Row reads take filter more than once, and the conditions are combined. Paging is limit and offset, not a cursor.
curl "https://api.superagnt.com/v1/db/rows/leads?filter=status.eq.open&filter=score.gte.80&order=created_at.desc&limit=50&offset=0" \
-H "Authorization: Bearer $AGNTDATA_API_KEY"Vector search
POST /v1/db/vectors/:table/search takes a query vector and returns the nearest rows. column defaults to embedding, k is clamped between 1 and 200, and metric is cosine (the default), l2 or ip. Each row comes back with an extra distance column.
curl -X POST "https://api.superagnt.com/v1/db/vectors/documents/search" \
-H "Authorization: Bearer $AGNTDATA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"column": "embedding",
"query": [0.014, -0.221, 0.087],
"k": 10,
"metric": "cosine"
}'Object storage
The same database carries buckets and objects under /v1/db/storage/*: list and create buckets, list objects by prefix with limit and offset, upload, download and delete.
- 01
Upload sends raw bytes
POST /v1/db/storage/objects/:bucket?path=...takes the file as the raw request body, not a JSON field and not multipart. SetContent-Typeto the file's own type; it is stored and replayed on download. - 02
Download streams the object itself
GET /v1/db/storage/objects/:bucket/<path>returns the bytes with the object's own content type, not the usual JSON envelope. Do not try to parse it as JSON.
Everything else on the storage surface answers in the standard envelope.
What it costs
calls are free
/v1/db/* routes deduct no data credits and write no usage rows. Query your own database as often as you like. What is priced is having a database at all.On a plan, the database count comes with the plan.
| Plan | Price | Databases |
|---|---|---|
| Solo | $99/mo | 1 |
| Team | $199/mo | 3 |
| Business | $499/mo | 10 |
On the Toolkit, the database is sold as the Database & Canvas module at $19/mo, with a 7-day free trial. It includes 1 database; further databases are $9/mo each. Data Jobs and Agent Runtime both require it, so adding either bundles this module in.
Toolkit module tier quantities are published allowances describing what a rung is sized for. They are not enforced caps.
Safety rails
The rails exist because the caller is often a language model, and the cost of a mistyped statement is your data.
- Destructive SQL is refused unless the request says confirm. A DROP or a TRUNCATE has to be deliberate, not a side effect of a generated string.
- More than one statement in a single POST /v1/db/sql needs allowMultiStatement, so a stray semicolon cannot smuggle a second command in.
- Reads through POST /v1/db/sql are capped at 1000 rows, and the cap cannot be raised past that.
- PATCH and DELETE on rows both require at least one filter. An update with no WHERE clause is not expressible on this surface.
- DELETE on a table requires ?confirm=true on the URL.
agents should use the runtime surface
/v1/db/* has the whole database. A deployed agent going through its runtime path is held to its own policy instead: only the tables on its allowlist, read-only when you set it that way, and every statement attributed to that agent in the audit trail. Give an agent the runtime surface and keep /v1/db/* for your own backend.Dashboards over this data are on canvases.