Dataset revisions
Erdo stores a file dataset’s contents as a file. Every write that replaces those contents — a refresh, a re-import, an upload that overwrites — stores the new file alongside the one it replaced rather than on top of it, so the previous version is still there after the new one goes live. A revision is one of those stored versions. This matters on the day a refresh goes wrong. If a source briefly returned fewer rows, or a rebuild ran in replace mode when it should have merged, the live dataset now holds less than it did an hour ago — and the hour-ago version is sitting in storage, intact. Revisions are how you look at it. Revisions are read-only. Nothing here rolls a dataset back, and there is no “restore” button: you read the rows out of the last-good revision and write them in again through the normal write path, so the write carries provenance, honours the dataset’s upsert key, and merges rather than clobbering whatever arrived since.What a revision is, and is not
A revision exists for each version of a file dataset’s stored contents. Alongside them you may also see a file that was uploaded into an existing dataset and merged into it — it is stored in its own right, so it is listed and queryable, but it was never the dataset’s contents. That distinction is visible: a version that was live and has since been replaced reports when it was replaced; one that was never live reports nothing. Row-level writes — appending a row, updating one, deleting one — do not create a revision. They change the current contents in place. Revisions record whole-contents replacements, which is the failure they exist for. Datasets queried live at their source keep no revisions here. A dataset backed by a connected database or warehouse is read from that system on every query, so Erdo holds no copy to keep versions of, and its revision list is empty.Listing revisions
--json prints the raw result instead of a table.
Reading one
Pass a revision id to the normal read. The same DuckDB SQL you would run against the live table runs against that version’s contents, with the file exposed as a table nameddata:
erdo_write_rows, POST /v1/datasets/:datasetSlug/rows, or just asking an agent — so the rows land with their
provenance and the dataset’s key decides what is an insert and what is an update.
In chat
An agent working on a dataset can do all of this itself. Ask it what a dataset held before a refresh, or to recover rows a rebuild dropped, and it will list the revisions, query the last-good one, and write the missing rows back.MCP tools
REST
datasets:query capability for the dataset can make both calls.
A revision id that does not belong to the dataset you name is rejected as not found, so
an id alone never reaches another dataset’s contents.
