DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS /// DOCS
CUSTOM FIELDS·OVERVIEW

Custom fields

Custom fields are the column definitions you add to a table to shape what each record can hold. Every table starts with a primary column and you extend it with as many typed columns as you need — text, numbers, dates, references to other entities, computed formulas, or values generated by AI.

Custom fields are the schema layer of Onnie's Tables module. They are not a separate system — they live in table_columns and apply to rows in the same table.


What custom fields extend

Tables are the primary home for custom fields. Each column you add to a table is a custom field: it defines a data type, display options, optional default value, and (for computed types) the expression or AI instructions that derive the value.

Every record in a table stores its field values as a JSON map keyed by column name. When you rename a column the database automatically rewrites the key in all existing records — no manual migration needed.

Custom fields on tables are the only entity type with a full typed-column system today. Other entities (tasks, projects, pages) carry a single onnie_md freeform document for extensible agent context rather than structured columns.


Field types you can add

Onnie supports the following column types out of the box:

TypeWhat it holds
TEXTShort text values
LONGTEXTMulti-line rich text
NUMBERNumeric values with optional formatting
SERIALAuto-incrementing integer
BOOLEANTrue / false
DATETIMEDate and/or time value
FILEFile attachment
EMAILEmail address
PHONEPhone number
URLWeb address
SELECTSingle-choice option list
MULTISELECTMulti-choice option list
REFERENCEPointer to another entity (record, page, task, etc.)
FORMULAComputed value — synchronous, derived from other columns
AIAI-generated value — asynchronous, derived by a model

For the full details on each type — accepted values, display options, filter operators, and configuration — see Tables: Fields.


AI fields

AI columns let you add a column whose value is generated by a language model rather than entered by hand. You write an instruction like "Summarize {{Notes}} in one sentence" and Onnie evaluates it asynchronously whenever the referenced columns change.

AI field jobs are queued in ai_field_generation_jobs, processed by the onnie-engine, and written back to records.fields once complete. While a job is running the cell shows a pending indicator; when it finishes the value appears.

AI columns and FORMULA columns cannot reference each other — cross-runtime dependencies are blocked at save time. Both types support {{Column Name}} placeholder syntax for referencing other columns.

Full documentation including prompt patterns, display configuration, and manual regeneration is at Formulas and AI fields.


When to use a custom field vs. a separate table

Use a custom field when:

  • The data point belongs to every record in the same table (or most of them).
  • The value is a simple scalar — a status, a date, a count, a short text.
  • You want AI to generate or aggregate it automatically per row.

Create a separate table when:

  • You have a one-to-many relationship — for example, a task can have multiple comments, each with its own timestamp and author.
  • The data point has its own identity and you want to reference it from multiple places.
  • The shape of the data is too complex to fit in a single typed column.

A REFERENCE column is the bridge between the two: it stores a pointer from one record to one or more entities in another table (or to a page, task, project, etc.), keeping the tables normalized without losing the lookup.