Letting an Agent read and write a table
Give an Agent access to chosen Data Tables, one table at a time — reads by default, writes only when you switch them on.
An Agent can answer questions from a Data Table — "which contracts are due this month?", "is there already a row for Acme?" — by reading it. It can also record something in a table — add a row, change a row — but only where you switched that on, for that table and that action. It can never delete.
What the Agent is given
You choose the tables, one at a time. For each table you pick which of six actions it gets:
| Action | What the Agent can do |
|---|---|
| Read rows | Look rows up with conditions, ordering and paging. At most 50 rows come back per call. |
| Check whether rows exist | Ask "is there a row where…?" and get back whether any match, and how many. |
| Look up by key | Give a key column and up to 50 values (SKUs, customer ids) and get the matching rows. |
| Add rows | Add up to 10 new rows per call. Writes data. |
| Change rows | Change the rows that match conditions, at most 50 per call. Writes data. |
| Add or change a row | Update the rows that match, or add one when none do (an upsert). Writes data. |
The three reads are the default. The three writes are separate switches: Add all never adds them, and a table bound for reading stays read-only until you add a write for it. Each write carries a warning in the picker, and the Agent is told in the tool's description that it changes data for real and cannot be undone — an override of the description cannot remove that sentence.
There is no delete, and there is no "list the tables" either: an Agent knows only the tables it was given, and what it learns about each one is its name and its columns.
A table you add to the project later is not readable by any Agent until you bind it. Nothing here is a project-wide switch.
Binding a table
Open the Agent, go to Tools & connectors, choose + Add Tool, and pick the Data Tables filter. Each table is listed with its actions; add one, or use Add all for the three reads.
The Agent's author can still:
- Disable a binding without removing it.
- Replace the tool's description with a better one for the Agent's job.
- Pin a parameter, for example always
limit: 5. A pinned value always wins over what the model sends.
What the model sees
The Agent is told the table's name, every column and its type, and whether the tool is read-only. The
column names are listed in the tool's parameters, so the model picks from your real columns instead
of guessing. Dates are written as ISO 8601, for example 2026-10-31.
A conditions list works like the Data Table node's:
{
"conditions": [
{ "column": "Status", "operator": "eq", "value": "open" },
{ "column": "Deadline", "operator": "lte", "value": "2026-11-30" }
],
"match": "all",
"order_by": { "column": "Deadline", "direction": "asc" },
"limit": 10
}Looking up many keys at once
For a price list or a customer register with thousands of rows, Look up by key answers in one call what Read rows would need many pages for. The model names one column and up to 50 values:
{ "column": "SKU", "values": ["A-100", "A-101", "ZZ-9"] }The answer lists, per value, the matching rows (at most 5 per value, with more: true when there
are further matches) and a not_found list of values with no row. A value repeated in the request
is answered once, and a call never returns more than 50 rows in total — values left out for that
reason are listed in unanswered.
The match is exact, and case-sensitive for text: a-100 does not find A-100. A value is
converted to the column's type first, so "9" finds the number 9 in a number column; a value the
column cannot hold is refused with a sentence naming the column, its type and the value.
To count rows, use Check whether rows exist: it returns the true number of matching rows. There is no separate count action.
A write uses the same rules as the Data Table node: the same type coercion, the same limits and the same errors. A change needs conditions — an update with none is refused, and the Agent is never offered a way to change every row — and an upsert needs a match. A call that would touch more than 50 rows is refused with advice to narrow it.
If a call asks for something the table cannot do — a column that does not exist, a text value for a number column — the Agent gets a sentence naming the problem and can correct itself.
When more rows match than were returned, the answer says so and says which offset to ask for next.
An Agent never has to guess whether a list was complete.
Letting skill scripts read a table
A bound table can also be made available to the skill scripts of that Agent. Turn on Available to skill scripts on the table's binding in the Agent's Tools section. When a script runs for that Agent, the table's rows are mounted in its workspace as data/<table-slug>.jsonl, one JSON row per line, and the script reads them like any file. The slug is the table name in lower case with every run of other characters turned into - ("Price List 2026" is data/price-list-2026.jsonl); when two tables share a slug, the second gets -2.
- It is a separate decision from the Agent's own tools: a model asking a question sees at most a page of matching rows, while a script reads the whole table. That is why it is off by default and set per table.
- It is a read-only snapshot taken the first time a script runs in a conversation turn, and reused for later scripts in that turn. A script cannot write the table. To change rows, give the Agent a write action.
- The gateway checks the switch on every request, not only the Agent's configuration. A table that is not bound to the Agent, or bound without the switch, is never mounted.
- Each table may be up to the Code node's input budget (
CODE_NODE_MAX_INPUT_FILE_BYTES, 50 MB by default). If a table is over it, the script run fails and names the table instead of reading part of it. - The sandbox still has no network, no secrets and no database: the data goes in as a file.
Who can read and write what
- A write only works for an Agent that has a binding for that table and that action. The gateway checks this on every call; the prompt is not the only thing standing between a model and a table.
- Every write is recorded in the organization's audit trail with the Agent, the table, the action and how many rows it touched — never the row contents.
- A Team member's Agent, and an Agent used as a Workflow node, may write when the binding exists on that Agent. There is no extra rule.
- An Agent in a project reads that project's tables, and only those.
- An Agent that is not in a project (every Agent a Package installs) reads the tables it was bound to, wherever they sit in its own organization. The binding is the grant.
- A table in another organization is never reachable. A project Agent asking for a table in a different project gets the same answer as for a table that does not exist.
When you delete a table, the Agent's bindings to it are deleted with it.
In a Package
A Package can give its Agent reads and writes of a table it also ships. In the Agent's definition the table is named the way a Workflow's Data Table node names it, by the Package's own name:
tools:
- { table: dataTables.register, actionId: rows.get, enabled: true, config: {} }
- { table: dataTables.register, actionId: rows.exists, enabled: true, config: {} }
- { table: dataTables.register, actionId: rows.upsert, enabled: true, config: {} }To make the table available to the Agent's skill scripts, set config: { expose_to_scripts: true } on its bindings.
actionId is one of rows.get, rows.exists, rows.lookup, rows.insert, rows.update or rows.upsert. A
definition that names anything else — a delete, for example — is refused when you build it and again
when it is installed. The table must be declared under dataTables: in the
manifest, or validate fails and says which names are declared. The installer creates the table
before the Agent and binds the Agent to the table it just created. Every binding field, with a
snippet for each action, is in the authoring reference:
Data Tables → Agent tool bindings.
Limits to know about
- A write changes data for real. There is no undo and no dry run. Bind a write only where you would be comfortable with the Agent doing it unattended, and consider a Human Review step in front of anything important.
- It cannot delete. To remove rows, use a Workflow with a Data Table node.
- It reads what the table holds right now. There is no snapshot, so a question asked twice can have two answers.
- Rows go into the model's context. That is why a call returns at most 50 rows: narrow the conditions rather than paging through a large table.