Skip to main content

Computed Columns

A computed column is an AutessaDB column whose value is produced by an AutessaScript instead of being written directly. The script reads the row's other columns as variables, returns one value with response.setResponse(...), and the platform converts that value to the column's type and merges it into the row. Same language, same sandbox — but a slimmer execution context than a script tool.

See AutessaDB Tables for creating tables and columns; this page covers what your script sees once it's attached to a column.

When the script runs​

Computed columns are recomputed asynchronously, in the background, after the row write that triggers them:

  • On insert, every computed column in the table runs.
  • On update, a computed column runs only when one of its declared dependencies (see below) is among the updated columns. If an update writes a computed column directly, that column is not recomputed over your explicit value in the same update.

Because computation is asynchronous, the insert or update returns immediately — with the row's computation status reported as COMPUTING — and the computed value appears in the row shortly after, once the script finishes. Scripts read a snapshot of the row as it was written; they never block the write itself.

When several computed columns exist, they run in dependency order: a computed column that depends on another computed column sees the freshly computed value, not the stale one. A circular dependency between computed columns is rejected and none of them compute.

Variables: the row, natively typed​

The variables binding contains the row's columns, keyed by column name. Unlike tool executions — where every variable is a string — computed columns receive native types per the column's type:

Column typeJavaScript value
SHORT_TEXT, LONG_TEXT, SINGLE_SELECTstring
MULTI_SELECTstring (the selections in their combined string form)
INTEGERnumber
FLOATnumber
BOOLEANboolean
FILE, IMAGE, VIDEO, AUDIOstring (the stored file path)

Details that matter in practice:

  • Empty columns are absent, not null. A column with no value doesn't appear in variables at all — guard with variables.has("name") before reading.
  • Built-in fields are included: id (number), created_at and updated_at (strings).
  • DATETIME columns don't cross the boundary — they are neither passed in as variables nor writable as a computed result. Store timestamps as SHORT_TEXT UTC strings if a computed column needs them.
  • Other computed columns' values are available too: previously stored values on update, and freshly computed values for columns earlier in the dependency order.

Declaring dependencies​

A computed column's configuration includes a dependsOn list — the column names your script reads. It does three jobs:

  1. Update triggering. After an update, only computed columns whose dependsOn intersects the updated columns are recomputed. A script that reads a column it doesn't declare will silently go stale on updates.
  2. Ordering. Dependencies on other computed columns put your column later in the computation order.
  3. Validation. A missing dependency is logged; a dependency cycle fails the whole computation pass.

Declare every column the script reads. There is no automatic detection.

Returning the value​

Call response.setResponse(...) with a string; the platform converts it to the column's type:

Column typeConversion
SHORT_TEXT, LONG_TEXT, SINGLE_SELECTstored as-is
MULTI_SELECTparsed from the combined multi-select string form
INTEGERparsed as an integer — must be a plain integer string like "42"
FLOATparsed as a float
BOOLEAN"true" (case-insensitive) becomes true; anything else false
FILE, IMAGE, VIDEO, AUDIOstored as the file path

If the string doesn't parse (say, "42.5" into an INTEGER column), the conversion fails and no value is written. The same happens when the script throws or never calls response.setResponse — the column is simply left unset. One failing computed column doesn't stop the others.

Failures are silent from the table's point of view: there is no error cell, just an empty column and a server-side log you can't see. Develop and debug the script as a script tool first — where the test window shows you logs and errors — then attach it to the column.

What's missing compared to tool execution​

The script runs in the same sandbox with the same helpers bound, but the context is slimmer:

  • No tool arguments. There are no @@{name} placeholders — the variables are the row's columns, nothing else.
  • No platform context. AUTESSA_COMPANY_ID, AUTESSA_TOOL_NAME, and the other AUTESSA_* variables from tool execution are absent. As a consequence, company-scoped helpers refuse to run: tools.invokeById returns MISSING_COMPANY_ID and connector.* returns NO_COMPANY_CONTEXT.
  • No responseStream. Computed columns never stream; referencing responseStream throws a ReferenceError. See Global bindings.
  • api, llm, mathUtils, and waitUtils work normally.

Keep computed-column scripts small, fast, and deterministic — derive from the row, return a value. Side effects and orchestration belong in script tools.

Example: derive a display name​

A SHORT_TEXT column full_name with dependsOn: ["first_name", "last_name"]:

const first = variables.has("first_name") ? variables.get("first_name") : "";
const last = variables.has("last_name") ? variables.get("last_name") : "";
const full = (first + " " + last).trim();

if (full !== "") {
response.setResponse(full);
}
// If both inputs are empty, setResponse is never called and the column stays unset.

Example: numeric derivation​

A FLOAT column margin_percent with dependsOn: ["revenue", "cost"]. Numeric columns arrive as real numbers — no parseFloat needed:

if (variables.has("revenue") && variables.has("cost")) {
const revenue = variables.get("revenue"); // number
const cost = variables.get("cost"); // number

if (revenue > 0) {
const margin = ((revenue - cost) / revenue) * 100;
response.setResponse(margin.toFixed(2)); // "23.50" parses cleanly as FLOAT
}
}