Skip to main content
Agent extends StatefulActor, and every actor carries a private, durable SQLite database at this.ctx.storage.sql. There is nothing to declare in telnyx.toml — the database is created on first use, and it works inside an agent exactly as it does on a plain actor.

Which tier holds the data?

An agent has three durable tiers, all in the same actor: State is read and written as one value; history is read back in order. The moment you want “the last five orders over $10” — a lookup neither tier answers without a scan — put rows in SQL.

Using it from an agent

exec() is synchronous — the database is a local file in the actor’s own process — with positional ? binds and a cursor you drain with toArray():
Everything the actor surface guarantees applies unchanged: the database is private to this one agent instance — per conversation, if you key actors by conversation — reads always reflect your prior writes, and serialized turns mean no other call interleaves mid-write. Wrap related writes in this.ctx.storage.transactionSync(() => { ... }) to commit them atomically. Patterns that come up in agents:
  • Webhook dedup. INSERT the event id into a table with a UNIQUE constraint before queue()-ing work; a thrown constraint violation means you already handled that event.
  • Tool-call ledger. Record each tool invocation and result as a row; answer “what did you do?” or audit questions with a query instead of replaying history.
  • Searchable history. this.messages is an ordered log, not an index. If the agent needs keyword lookup over past conversation, append each message to an SQL table too — in the same method that calls messages.add() — and query it with LIKE plus an index.

Semantics and limits

The full contract — cursor rules, multi-statement batches, transactionSync, binding types, and the limits (1 GB per actor database, 2 MiB per bound value, integer range) — is on the actor SQL guide. It applies verbatim inside an Agent: the SDK reserves alarm() for its scheduler, but all of ctx.storage stays yours. For data that more than one function or caller must query — shared across agents, or read from the CLI and REST API — use a standalone SQL Database instead; the embedded database is strictly per-instance.