Use this page when an agent’s run went wrong and you want its rows back. Undo restores what the agent changed. It leaves alone any row your team or your app changed since. For why, see Undo.
You need the agent’s name and the run id. To find the run id, ask the agent for its runs (it has list_runs), or read the record with basalt log. The examples use the agent demo_bot and the run id RUN_ID.
1. Preview the undo
Section titled “1. Preview the undo”Add --dry-run to see the plan. Nothing is changed and nothing needs approving.
basalt revert --agent demo_bot --run RUN_ID --dry-run
restore basalt_demo.leads {"id": 1}: score: 47 -> 37, status: "QUALIFIED" -> "NEW"
restore basalt_demo.leads {"id": 3}: score: 21 -> 11, status: "QUALIFIED" -> "NEW"
skip basalt_demo.leads {"id": 2}: CHANGED_AFTER
basalt: 2 rows to restore, 1 left as they are (people win)
basalt: dry run, nothing was reverted
restore is a row that goes back to the values it had before the agent, shown as column: now -> restored. skip is a row the undo leaves alone, with the reason next to it. Here lead 2 was changed after the agent (CHANGED_AFTER), so it stays.
2. Approve the undo
Section titled “2. Approve the undo”Run the command without --dry-run. Add --open to open the undo link in your browser.
basalt revert --agent demo_bot --run RUN_ID --open
The command prints the plan and a link, then waits for you. Nothing is undone yet. Open the link, check the rows and approve the undo. The command finishes by itself, with its last line:
restore basalt_demo.leads {"id": 1}: score: 47 -> 37, status: "QUALIFIED" -> "NEW"
restore basalt_demo.leads {"id": 3}: score: 21 -> 11, status: "QUALIFIED" -> "NEW"
skip basalt_demo.leads {"id": 2}: CHANGED_AFTER
basalt: 2 rows to restore, 1 left as they are (people win)
basalt: revert REVERT_ID expires 2026-11-15 08:21 UTC. Open this link on a device with your passkey, check the rows, and sign:
http://localhost:8787/reverts/REVERT_ID#s=...
basalt: waiting for your signature on the revert page (or paste the code it shows here)...
basalt: reverted: 2 rows restored, 1 left as they are
Without --open the command prints the link instead. Copy it into your browser. If the page cannot reach the command, it shows a code. Paste the code into the terminal and the undo applies the same way.
The command exits with 0 even when some rows were kept. A partial undo is a normal result. For how approving works, and what to do if you lose your passkey, see Passkeys.
3. Check the result
Section titled “3. Check the result”The undo is recorded as a new change that names you. It belongs to no run, so basalt log --run RUN_ID does not show it. Read the agent’s record, newest first:
basalt log --agent demo_bot
The undo is the newest change. The record shows what the undo did, not what the table holds now. For the current values, query the table:
SELECT id, status, score FROM basalt_demo.leads WHERE id <= 3 ORDER BY id;
The restored rows hold their old values. The kept rows hold the newer values. Nothing in the ledger was edited.
Undo less, or more
Section titled “Undo less, or more”basalt revert takes one scope.
| Flag | What it undoes |
|---|---|
--run ID |
Everything one run changed. |
--change ID |
One change inside a run. |
--task ID |
Changes that share a task id. |
--intent TEXT is not a scope. It sets the reason for the undo, kept in the log. Without it the reason is Revert run RUN_ID, or the same for the change or task.
--agent names the agent whose work is undone, and basalt revert prepares only that agent’s own work. For --task that means its own lines in the task. If other agents changed rows in the task, you can widen the undo on the signing page. The command never widens it by itself.
To drop a prepared undo, run basalt revert --agent demo_bot --reject REVERT_ID. It is the same as pressing Reject on the signing page. Add --note TEXT to say why.
An undo can be undone. Run basalt revert --change ID with the change id of the undo, and the values the first undo put back are brought back again.
Ask your agent to do it
Section titled “Ask your agent to do it”You can ask the agent: “Undo the run that qualified this week’s leads. Keep anything a person changed.” The agent finds the run, previews the undo against today’s data, and tells you what it would restore and what it would keep. If you agree, it prepares the undo and shows you one link.
The agent cannot approve its own undo. Only you can. Open the link, check the rows and approve. The agent waits about 90 seconds for you. If you take longer, it tells you the undo is waiting. Approve when you are ready, then tell the agent.
An agent can ask to undo only its own work: its changes, its runs, or its own part of a task. If another agent’s run went wrong, ask that agent, or run basalt revert yourself.
On an engine your bot runs on its own computer, ask the bot. See A bot on its own computer.
Large and late undos
Section titled “Large and late undos”- More than 1000 rows. The command prints the size of the plan and the rows the link carries, not every row. You approve once, and the agent applies the plan in batches.
basalt revert --agent demo_bot --status REVERT_IDprints the progress. - An hour to approve. A prepared undo expires after 1 hour if nobody approves it. Run the command again to prepare a new one. A large plan that you approved must be finished within 24 hours.
- Apply later.
basalt revert --agent demo_bot --apply CODEapplies an undo that was prepared earlier, within its hour.
If something goes wrong
Section titled “If something goes wrong”NOTHING_TO_REVERT: every row in the scope would be kept, or the run wrote no rows. A run that only read data has nothing to restore.- The plan keeps a row you expected to restore: someone wrote it after the agent. Why a row is skipped lists each reason.
NOT_FOUND: the run id does not exist, or is not this agent’s. Check the id withbasalt logand the name after--agent.QUERY_TIMEOUTwhile an agent prepares an undo: the plan took over 100 seconds to prepare. Runbasalt revertyourself, first with--dry-run, then with--open. See When something is refused.- The engine is not running: the command prints
basalt: the engine is not running; start it with ...and the command to start it. Run that command, then runbasalt revertagain.
- Undo: why a row is kept, the 30-day window and what undo covers.
- See what it did: read the record of a run.
- Passkeys: add, check and remove passkeys.
BasaltDB · Apache-2.0