Skip to main content

Agent DB & Self-Scheduling

Any Osaurus agent can opt into two capabilities that turn it from a stateless chat into something that remembers structured data across runs and can wake itself up to act on it:

  • Agent DB — a private, encrypted SQLite database the agent designs and queries through dedicated tools.
  • Self-scheduling — a single "next run" slot the agent can set to wake itself at a chosen time.

Together they're a journal that can also set its own alarm.

This is not Memory

Memory is a global system that distills conversational context across all your chats automatically. Agent DB is per-agent, structured storage the agent explicitly schemas and queries. They're independent — an agent can use neither, either, or both.

Enabling the database

Turn on Database in an agent's Configure → Features. That does three things:

  1. Five database tabs appear in the agent detail view — Home, Schema, Data, Views, Activity.
  2. The agent gains the db_* tools (they're hidden from the model when the database is off).
  3. The agent gets a fresh, empty encrypted database on its first write — nothing is created on disk until it's actually used.

How the agent uses it

The agent works the database entirely through typed db_* tools — it never writes raw, unconstrained SQL by default.

Schema: db_schema (inspect), db_create_table, db_alter_table, db_migrate.

Writes: db_insert, db_upsert, db_update, db_delete, db_restore.

Reads & saved views: db_query (read-only SELECT, capped with a truncated flag), db_define_view / db_run_view / db_list_views / db_drop_view, and an db_execute escape hatch restricted by host policy.

Soft deletes

Every table the agent creates gets three reserved columns: _created_at, _updated_at, and _deleted_at. db_delete is a soft delete — it stamps _deleted_at rather than removing the row, and db_restore clears it. Reads hide soft-deleted rows by default. In the Data tab, the Active / Deleted / All filter maps directly to that flag. There's no hard-delete tool — purging a row is a host-side action the model can't take.

Every mutation is also appended to a hidden changelog (who changed what, and during which run), surfaced in the Activity tab.

Where it lives, and quotas

ArtifactPath
Per-agent database~/.osaurus/agents/<uuid>/db.sqlite
Self-schedule slots (all agents)~/.osaurus/scheduler.sqlite

Both files are encrypted with your device-scoped storage key via SQLCipher — the same stack as chat history and memory. See Storage & Encryption for key management.

Each agent has its own storage quota: writes are rejected once the file exceeds the limit (the error tells the model to delete or migrate older rows), and a banner warns you when usage crosses ~80%.

The detail-view tabs

TabWhat it shows
HomeA dashboard of pinned views — the agent's "what should I look at right now?"
SchemaRead-only catalogue of tables, columns, types, and indexes
DataBrowse and edit rows, with the Active/Deleted/All filter and CSV export
ViewsManage saved views; pin one to show on Home
ActivityThe audit log — run history paired with the changelog entries for each run

Self-scheduling

Self-scheduling is a separate opt-in — the Self-scheduling toggle under Configure → Features (default off). When off, the scheduling tools are stripped from the model and any pending slot is cancelled, so an agent can't fire after you opt out. It's independent of the database: any agent can self-schedule whether or not it has a DB.

The contract is deliberately minimal: one next-run slot per agent. The agent calls schedule_next_run to set it; when the time arrives, Osaurus clears the slot before dispatching (so a slow run can't double-fire) and runs the agent with the instructions it left itself. Because the slot is cleared on wake, wake-ups are single-shot — if the agent wants to run again, it must call schedule_next_run again from inside the run. That's how it expresses "keep me going" versus "I'm done."

schedule_next_run fields

Pass either scheduled_at or in_seconds, not both.

FieldTypeMeaning
scheduled_atISO-8601Absolute wake-up time
in_secondsintegerRelative offset from now
instructionsstring (required)The "wake-up brief" the agent reads when it fires
context_viewsstring[]Saved-view names to prefetch into the prompt before the run
prioritynormal | lowlow skips the run if you're mid-conversation when it's due
on_missskip | run_once | run_catchupWhat to do if the wake-up time already passed (e.g. the Mac was asleep)

cancel_next_run clears the slot. A requested time is clamped to the agent's schedule mode bounds before it's saved; if it's clamped, the tool result says why.

Schedule modes

The mode sets the bounds for self-scheduling (the on/off switch is the separate toggle above):

ModeMax horizonMin intervalDaily capQuiet hours
Ambient7 days1 hour622:00–07:00
Reactive24 hours5 minutes48None
Project30 days1 hour422:00–07:00

Pick a mode in Configure → Scheduling (only shown when self-scheduling is on). Selecting a mode rewrites the cap, horizon, and quiet hours — not just the label.

Pausing

The Next Run banner has a pause menu — 1 hour, 4 hours, until tomorrow, a custom date/time, or indefinitely. While paused, a due slot won't dispatch; it stays put and fires once the pause expires (subject to its own on_miss).


Related:

  • Memory — global conversational memory (separate from Agent DB)
  • Schedules — app-level recurring runs on a clock
  • Agents — per-agent features and configuration
  • Tasks — the agent loop the db_* and scheduling tools run inside
  • Storage & Encryption — how the encrypted databases are keyed