Skip to main content
Your data never needs a support ticket to leave the box. Every project-scoped table streams out of the engine as NDJSON over one authenticated endpoint, and the same endpoint powers client.export in the Python SDK.

What’s exportable

GET /api/v1/export (with your project’s x-api-key) returns a manifest of every entity with live row counts. GET /api/v1/export/<entity> streams the rows, one JSON object per line, in exactly the stored shape (timestamps as ISO-8601): Config tables ride along with the data because a usable backup is the data plus the scorer configuration that produced it. Everything is scoped to the API key’s project: an export can never cross a tenant boundary. Instance-wide state (auth users/orgs, app settings, the pricing catalog) is deliberately not in the project export; it belongs to the database-level backup below.

Exporting

Exports are keyset-paginated internally, so memory stays flat on both ends regardless of table size, and a nightly dump(since=...) only moves the delta.

Restore runbook

There are two supported restore paths. There is deliberately no blind row-level import endpoint: one would bypass the engine’s invariants (span dedupe, id uniqueness, derived agent rows) and could corrupt a live project silently.

Path 1: database-level (full instance restore)

In the SQLite and Postgres tiers the engine owns exactly one database; restoring it restores everything, including auth and settings.
  • SQLite (default): stop the engine, copy $AGENTX_HOME/agentx.db back into place, start the engine. For hot backups use sqlite3 agentx.db ".backup backup.db" which is safe while the engine runs.
  • Postgres: standard pg_dump / pg_restore (or your provider’s point-in-time recovery). The engine runs its own migrations at boot, so restoring an older dump into a newer engine is supported; the reverse is not.
  • Enterprise tier (Postgres + ClickHouse): the control plane is the Postgres backup above; spans live in ClickHouse and are append-only, so incremental strategies work well - a native format dump (SELECT * FROM agentx_spans FORMAT Native), clickhouse-backup, or volume snapshots. Restore into a fresh table (the engine creates it on boot) with INSERT INTO agentx_spans FORMAT Native.

Path 2: replay (project-level, cross-instance migration)

NDJSON exports replay through the normal ingest surface into any project on any instance:
Replay is how the engine’s own round-trip test verifies the export contract: export a seeded project, replay it into a fresh one, and the counts and contents match. Ground truth (feedback, outcomes) replays the same way through client.feedback / client.outcomes. Note what replay preserves and what it does not: content, sessions, span trees, and metadata survive; engine-assigned row ids and createdAt are newly assigned on the target (the original timestamps remain inside the exported file if you need them).

Dataset import & delete

Datasets get a first-class replay path of their own: POST /api/v1/evaluate/datasets/import takes a row from the datasets NDJSON export as-is and recreates it - cases, grading config, similarity flags - as a new dataset with fresh ids (201). It is a copy, never an in-place restore, so importing can’t clobber a live dataset:
The reverse also exists now: datasets can be deleted from the dashboard. Deleting removes the dataset, its grading config, and both version histories; past runs are kept - run history is your record of what was measured, not part of the dataset. A dataset whose grading config is still bound to a live online evaluator refuses deletion (409) until the scorer is detached.

Suggested schedule

  • Nightly: client.export.dump(dir, since=<24h ago>) to object storage - the incremental NDJSON is your audit-friendly, vendor-neutral copy.
  • Weekly: database-level backup (SQLite .backup file or pg_dump) - the fast full-restore path.
  • Before upgrades: database-level backup, always; the engine migrates forward only.