The agent database
Every agent gets its own SQLite database, and the workspace gets shared tables. The agent creates the tables; people browse and export them.
An agent that runs more than once needs somewhere to keep what it learned: the leads it emailed, the prices it saw yesterday, the tickets it already filed. The agent database is that place. It is not Brain — Brain is knowledge you give the agent to read; this is data the agent writes.
Two scopes
| Scope | Who reaches it | Named in the document as |
|---|---|---|
agent | This agent only. Its own SQLite database. | tools.database: "agent" |
workspace | Every agent in the workspace granted the shared scope. One database per workspace. | tools.database: "workspace" (which includes the agent's own) |
"off" (or an absent field) means no database. The switch lives under Abilities in the builder — Own database, then Shared workspace tables — and republishing mints a key that carries toolkit:data, plus the gateway:shared_data capability for the workspace scope.
The workspace scope is a second decision because other agents read what this one writes. Use it to hand work between agents: a research agent fills leads, an outreach agent drains it.
The four tools
The agent sees them as ordinary tools in its list, under the data toolkit. Every call takes an optional scope ("agent" by default).
| Tool | Does | Risk tier |
|---|---|---|
DATA_DESCRIBE_SCHEMA | Lists tables, columns, keys and row counts. Free. | read |
DATA_QUERY_SQL | One SELECT or WITH statement. Returns up to max_rows rows (100 by default, 1000 at most) and a truncated flag. | read |
DATA_WRITE_SQL | One INSERT, UPDATE, DELETE, CREATE TABLE / INDEX / VIEW or ALTER TABLE. RETURNING is supported. | write |
DATA_DROP_TABLE | Drops one table or view by name. | destructive |
The tiers matter because they are what the agent's approval setting acts on: with approval: "write" every write pauses for a person, and a drop pauses for everyone. Inside a sandbox run, where nothing can pause, DATA_DROP_TABLE is refused outright.
{ "name": "DATA_WRITE_SQL", "arguments": {
"sql": "CREATE TABLE IF NOT EXISTS leads (id INTEGER PRIMARY KEY, email TEXT UNIQUE, stage TEXT, last_touch TEXT)"
} }{ "name": "DATA_WRITE_SQL", "arguments": {
"sql": "INSERT OR IGNORE INTO leads (email, stage) VALUES (?, ?)",
"params": ["ada@northwind.io", "new"]
} }{ "name": "DATA_QUERY_SQL", "arguments": {
"sql": "SELECT email FROM leads WHERE stage = 'emailed' AND last_touch < date('now', '-4 days')",
"max_rows": 50
} }Bind values with ? and pass them in params; never quote them into the SQL. params may hold strings, numbers, booleans and null, at most 100 of them.
What the SQL may not do
The dialect is SQLite, one statement per call. The store refuses, whatever the statement looks like:
ATTACH,DETACH,PRAGMA,VACUUMand extensions;- triggers, virtual tables, temporary objects;
- the engine's own tables (
sqlite_*); - a
DROPanywhere in a write — dropping is its own tool, so it gets its own tier.
A query that somehow writes is rolled back. The refusal comes back to the agent as the tool's error, with the reason, so it can correct the statement.
Limits
| Rows per query | 100 by default, 1000 at most; larger results are offloaded like any big tool result |
| Tables per database | Pro and Business 50, Enterprise 200 |
| Database size | Pro and Business 100 MB, Enterprise 1 GB |
| Credits | a query 1, a write or drop 2, describe free |
From a Connect client
The same four tools are on the workspace endpoint for a person's own MCP client — a spr_ key or an OAuth grant from Claude, ChatGPT or Cursor — on any plan that sells the store. The defaults differ, because a person has no agent:
| Agent key | Connect client | |
|---|---|---|
scope default | agent (its own tables) | workspace (the shared tables) |
scope: "agent" | its own tables | refused: a client has no database of its own |
agent: "<slug or name>" | that agent's tables, read-only, with the shared-data grant | that agent's tables, read-only |
DATA_WRITE_SQL on the shared tables | with the shared-data grant | any member |
DATA_DROP_TABLE on the shared tables | with the grant, at the destructive tier | workspace admins only |
Two rules carry the weight. An agent's own tables are its to write: a client (or another agent) reads them by naming the agent and can never write or drop them, because an edit behind the agent's back would be invisible to it. A drop from a client takes an admin: there is no approval card on the MCP path, so the one irreversible action is fenced by role as well as by any Enhanced Control rule on the destructive tier.
{ "name": "DATA_QUERY_SQL", "arguments": {
"agent": "outreach",
"sql": "SELECT email, stage FROM leads WHERE stage = 'replied'"
} }Team endpoints (/mcp/t/<slug>) do not list the toolkit: a team endpoint exists to narrow what a client reaches, and one database per workspace cannot be narrowed.
Where it lives, and what people see
Each database is a SQLite store pinned to the EU, with thirty days of point-in-time history and a nightly copy to the blob store. Nothing of it is mirrored elsewhere.
People browse it on the agent's Data tab (and the workspace's Data page under Resources): the tables, a paged grid of one table, a CSV export. Nobody edits rows from there — a person's edit would be invisible to the agent that owns the table. An admin can drop a table.
Rows read back into the agent are wrapped as untrusted data, the same as any tool result: an agent may have stored text it scraped from anywhere, and persistence must not turn that into instructions.