Tables define data storage schemas for your agent. They provide structured storage that’s automatically synced with Botpress Cloud and accessible throughout your agent.
Creating a table
Create a table definition in src/tables/:
import { Table , z } from "@botpress/runtime" ;
export default new Table ({
name: "PricingTable" ,
columns: {
itemName: z . string (),
price: z . string (),
},
});
Naming a table
To properly deploy your agent, make sure your table name follows the correct convention:
Must start with a letter or underscore
Must be 35 characters or less
Can contain only letters, numbers, and underscores
Must end with Table
Table schema
Simple definition
Define your table using Zod schemas:
export default new Table ({
name: "OrderTable" ,
columns: {
userId: z . string (),
items: z . array ( z . string ()),
total: z . number (),
status: z . string (),
createdAt: z . string (). datetime (),
updatedAt: z . string (). datetime (),
},
});
Extended definition
You can also define table columns with additional options for each column:
import { Table , z } from "@botpress/runtime" ;
export default new Table ({
name: "OrderTable" ,
columns: {
itemName: {
schema: z . string (),
searchable: true
},
price: {
schema: z . string (),
searchable: true
}
},
});
Check out the column options in the Table props reference for a full overview of the available options.
Using tables
Tables are automatically created and synced when you deploy. You can import them and interact with them directly using the table instance methods, which provide type-safe operations.
Creating rows
import OrderTable from "../tables/order-table" ;
const { rows } = await OrderTable . createRows ({
rows: [{ userId: "user123" , total: 99.99 , status: "pending" }],
});
Finding rows
const { rows : orders } = await OrderTable . findRows ({
filter: { status: "pending" },
orderBy: "createdAt" ,
orderDirection: "desc" ,
limit: 10 ,
});
Updating rows
await OrderTable . updateRows ({
rows: [{ id: orders [ 0 ]. id , status: "completed" }],
});
Getting a single row
const row = await OrderTable . getRow ({ id: 42 });
Deleting rows
await OrderTable . deleteRows ({ status: "cancelled" });
Upserting rows
Insert rows or update them if they match on a key column:
const { inserted , updated } = await OrderTable . upsertRows ({
keyColumn: "userId" ,
rows: [{ userId: "user123" , total: 149.99 , status: "pending" }],
});
Filtering
Use filter operators for advanced queries:
const { rows } = await OrderTable . findRows ({
filter: {
total: { $gt: 100 },
status: { $in: [ "pending" , "processing" ] },
},
});
Available operators
Operator Description $eqEqual to $neNot equal to $gtGreater than $gteGreater than or equal $ltLess than $lteLess than or equal $inIn array $ninNot in array $existsField exists $regexRegex match
Logical operators
Combine filters with $and, $or, and $not:
const { rows } = await OrderTable . findRows ({
filter: {
$or: [
{ status: "pending" },
{ total: { $gt: 500 } },
],
},
});
Semantic search
Search across columns marked as searchable using natural language:
const { rows } = await TicketsTable . findRows ({
search: "VPN connection issues" ,
limit: 10 ,
});
You can combine search with filter for hybrid queries:
const { rows } = await TicketsTable . findRows ({
search: "network problems" ,
filter: { status: "open" },
limit: 20 ,
});
Aggregation
Use the group parameter to perform aggregation operations:
const { rows } = await OrderTable . findRows ({
group: {
status: "key" ,
total: [ "sum" , "avg" , "count" ],
},
});
// rows: [{ statusKey: "pending", totalSum: 500, totalAvg: 100, totalCount: 5 }, ...]
Available operations
Operation Applies to Description keyAll types Group by this value countAll types Count of rows sumNumbers Sum of values avgNumbers Average of values maxNumbers, strings, dates Maximum value minNumbers, strings, dates Minimum value uniqueAll types Array of unique values
Reference
Table props
Unique name for the table. Must start with a letter or underscore, be 35 characters or less, contain only letters, numbers, and underscores, and end with Table.
Optional description of what the table stores.
Search weighting factor (1–30). Higher values increase the table’s relevance in semantic search results. Defaults to 1.
Name of a column to use as the key for upsert operations. Must reference an existing column.
Optional metadata tags for the table. Keys must be 3–50 characters, values 1–255 characters.
Object mapping column names to their definitions. Each key is a column name. Values can be either a simple Zod schema or an object with advanced column configuration options. Show Simple column definition
Zod schema defining the column’s data type and validation rules.
Show Advanced column definition
Zod schema defining the column’s data type and validation rules.
Whether this column should be searchable via the search parameter in findRows(). Defaults to false.
Whether this column is computed from other columns. Defaults to false.
Array of column names this computed column depends on. Required when computed is true.
value
(row: any) => Promise<any>
Async function that computes the column value from the row data. Required when computed is true.
Table methods
getRow
(props: { id: number }) => Promise<Row>
Fetch a single row by its ID.
findRows
(options?) => Promise<{ rows, hasMore, limit, offset }>
Find rows with optional filter, search, group, orderBy, orderDirection, limit, and offset.
createRows
(props: { rows, waitComputed? }) => Promise<{ rows, errors?, warnings? }>
Insert one or more rows. Set waitComputed to true to wait for computed columns to be calculated before returning.
updateRows
(props: { rows, waitComputed? }) => Promise<{ rows, errors?, warnings? }>
Update one or more rows. Each row must include an id field. Only changed fields need to be provided.
upsertRows
(props: { rows, keyColumn?, waitComputed? }) => Promise<{ inserted, updated, errors?, warnings? }>
Insert or update rows based on a keyColumn. Defaults to id if not specified.
deleteRows
(filter) => Promise<{ deletedRows }>
Delete rows matching a filter.
deleteRowIds
(ids: number[]) => Promise<{ deletedRows }>
Delete rows by their IDs.
deleteAllRows
() => Promise<{ deletedRows }>
Delete all rows in the table.
getTable
() => Promise<{ rows, stale, indexing, table }>
Get table metadata including row count and indexing status.
Tables are automatically synced with Botpress Cloud. When you deploy your agent, table schemas are created or updated to match your definitions.