AI-derived columns
A column the platform fills in with AI from other columns of the same row, and keeps current on its own.
An AI-derived column is an ordinary column whose value the platform fills in for you. You choose which columns of the row it reads and write one instruction. Every row gets a value, and a row whose source text changes gets a fresh one.
For example, the example app's invoices table has a free-text memo ("Endpoint refresh, full",
"Week 33", "Held, tariff reconciliation") and an empty spend_category column. Derive
spend_category from memo with the instruction "The spend category this invoice belongs to"
and the allowed values it, freight, facilities, professional_services, utilities, other, and
every invoice is labeled shortly after it is saved, with no code.
Because the value is stored, it is an ordinary column from then on: indexable, filterable over
REST (filter=spend_category:freight), groupable in sdk.aggregate, and readable by agents.
"How much did we spend on freight this quarter?" becomes a database query with no model call.
Set one up
Create the column first
A derived column is a real column that something fills in, so it must exist. Add it in the table
editor like any other (a VARCHAR for a label), nullable so existing rows are valid before they
are labeled.
Switch on derivation
Open the table, click the gear on the column, and switch on Derive this column's value with AI.
Choose what it reads and what it says
- Read from: the columns the model may read. Redacted columns are greyed out and cannot be chosen.
- Instruction: what the value is. One sentence is usually enough.
- Allowed values (optional): a comma-separated list. Listing them closes the set, so the model can only answer with one of them and your counts stay comparable over time. Leave it blank to let the model pick its own consistent labels.
Save
The editor states what labeling would cost on your organization's AI provider before you commit. Existing rows are labeled in the background, then each new or changed row after it is saved.
If no AI provider is connected yet you can still set the column up. It starts filling in, existing rows included, once one is connected.
How it runs
- In the background, never while saving. A save is never slowed down or failed by the model. A background pass finds rows whose value is missing or out of date and labels them in batches.
- Once per row. A row is labeled again only when its source columns change. Rows whose sources
are all empty settle to
NULLwithout a model call. - Changing the instruction or the allowed values re-labels every row, because it changes the question. Changing the model does not: switching providers never silently re-bills a whole table.
- On your fast model. Labeling runs on the fast model of your organization's AI connection (Integrations, then AI providers), not the model your arbiter uses. Leave it blank to follow the platform's low-cost choice. If the model you picked is retired, the column pauses until you choose another; it never switches models on its own.
- Any write door counts. The background pass checks the stored state, not a write hook, so a row changed through the REST API, a handler, an agent, a CSV import or the console's table editor is picked up the same way.
Rules
- A person always wins. A value someone edits by hand is kept, however often the column is re-run. Editing one of its source columns releases it, because that is a request for a fresh read.
- Redacted columns cannot be read. Saving a configuration that reads one is refused with
AI_SOURCE_REDACTED: the model would either see[redacted]and produce nonsense, or your redacted data would be sent to a third party. - A column cannot read itself. It would never stop re-deriving.
- Limits per configuration: up to 8 derived columns per table, 12 source columns each, 24
allowed values, and an instruction of up to 2,000 characters. A configuration outside them, or
one naming a column the table does not have, is refused with
AI_DERIVED_COLUMN_INVALIDand a message saying which rule it broke. - Agents do not switch this on. The arbiter and your agents can read derived values like any other column, but configuring derivation, which spends money on every row, is left to a person in the console.
Cost
Every labeling call is metered against your organization's AI usage, like any other AI feature. Because a row is labeled once and the hash of its sources decides whether it is labeled again, ongoing cost tracks how many rows are written or changed, not how often they are read.
From code
The same thing is available to handlers as sdk.ai.annotate, for a one-off labeling pass or one
driven by your own schedule. See AI in handlers.