K
Docs
Building Bots

🗄️ Vault

Unbox The Vault 🗄️ (free, like every expansion) and your bot gets its own isolated database — SQLite, living on the Engine. Define the schema in the Vault tab; the Engine creates or migrates it on every deploy.

🏗️Defining Your Schema

Add tables and columns in the Vault tab. This is what a table looks like:

🗄️
scores
Vault table · 3 columns
user_idPK
TEXT
username
TEXTdefault: ""
points
INTEGERdefault: 0
📐Under the hood — your schema as SQL
TypeScript
// Your Vault schema becomes real SQLite tables:
db.run(`
  CREATE TABLE IF NOT EXISTS scores (
    user_id  TEXT    PRIMARY KEY,  -- type: TEXT, primaryKey
    username TEXT    DEFAULT '',   -- type: TEXT, default ""
    points   INTEGER DEFAULT 0     -- type: INTEGER, default 0
  )
`);
// The Engine applies CREATE TABLE IF NOT EXISTS on every deploy — safe and additive.

📊Column Types

TypeStoresGood for
📝TEXT
String textUser IDs, names, messages, ISO timestamps
🔢INTEGER
Whole numbersCounters, scores, Discord snowflakes
💫REAL
Floating-point numbersAverages, percentages
✅BOOLEAN
True/false (stored as 0/1)Flags, active/inactive states
📦BLOB
Raw binary dataRarely needed — prefer TEXT

🧩Vault Pieces

Read, write and delete rows from any flow — the three classic pieces of The Vault.

📖 Read from Vault
📖
Read from Vault
base.db.read
Vault
tablerequired
scores
filterColumn
user_id
filterValue
{{input.user.id}}
asrequired
result
found
empty

Results land in {{result}} — use {{result.0.points}}.

✏️ Write to Vault
✏️
Write to Vault
base.db.write
Vault
tablerequired
scores
upsert
true
user_idcolumn
{{input.user.id}}
pointscolumn
+10

Turn on upsert to update existing rows by primary key — +10 adds to the current points.

🗑️ Delete from Vault
🗑️
Delete from Vault
base.db.delete
Vault
tablerequired
scores
filterColumn
user_id
filterValue
{{input.user.id}}

Always set a filter — without one, the entire table is wiped.

🏆Leaderboards, Tallies & Cooldowns

The rest of the pack — the things almost every economy or levelling bot ends up needing.

➕ Bump a Number

Add to or take from one number in a single step — set "Never go below" to make spending safe.

🔎 Get One Row

One row, straight to sparks: {{row.coins}} instead of {{result.0.coins}}.

🏆 Top List

A leaderboard in one piece — sorted, trimmed, and every row knows its place.

🥇 Find Rank

"You're #4 of 120" without fetching the whole board. Ties share a place.

🧮 Tally

Count rows, or total / average / lowest / highest a column.

🎲 Random Row

Pull a random row — quotes, prizes, giveaway winners.

🔁 Update Matching

Change every matching row at once, never adding new ones.

⏳ Cooldown

"Once every 24 hours" for /daily — no table needed.

The newer pieces can filter with = ≠ > ≥ < ≤, contains or starts with.

🔐All-or-Nothing

Some changes only make sense together: take coins from one person, give them to another. All-or-Nothing makes sure it's both — or neither.

Drop a 🔐 All-or-Nothing box and wire the Vault pieces that belong together off its Inside exit. If everything works, every change is saved at once and the flow carries on from All saved. If anything fails — or a ✋ Call it Off runs — every change inside is undone and the flow takes Undone, where {{oops.reason}} says why.

📐Under the hood — what the box does, as code
TypeScript
// 🔐 All-or-Nothing — what the box does for you:
db.exec("BEGIN IMMEDIATE");            // other spells wait a blink
try {
  takeCoins(payer, amount, { neverBelow: 0 }); // Not enough? → throw CallItOff
  giveCoins(friend, amount);
  db.exec("COMMIT");                   // → All saved ✓
} catch (err) {
  db.exec("ROLLBACK");                 // → Undone ↩ with {{oops.reason}}
}
✨What fits inside

Vault pieces and thinking pieces — conditions, math, variables, text, lists, loops and your own custom pieces. Replies, DMs, roles and waits go afterthe box, on All saved or Undone: a box can't un-send a message.

💡No race conditions to think about

While a box saves, other spells wait a blink before touching the Vault — so two people pressing /pay at the same moment can never spend the same coins. Spending one number? ➕ Bump a Number with "Never go below 0" is already safe on its own.

📐Naming Rules

Table and column names must be lowercase snake_case — letters, digits, underscores only. Must start with a letter.

✅ Valid
scores
user_data
message_log
ban_records
❌ Invalid
UserScores (uppercase)
1scores (starts digit)
my-table (hyphen)

🚀Schema on Deploy

New table→ Created automatically
New column on existing table→ Added (with default if specified)
Removed table or column→ Left intact — data is never dropped automatically
⚠️Data is never dropped automatically

Removing a table or column from your schema leaves the data in SQLite. To remove data, use Delete from Vault explicitly.