Replay a recorded run
Replay a journal and its recorded commits without sending a model request.
Record a run and replay it
Section titled “Record a run and replay it”Record a dispatch in a journal, then use a replay agent to reproduce its events and recorded commits. The replay sends no model requests; its usage fields reproduce the original counters rather than new consumption.
Both branches start from the same commit, so the replayed commits have the same ids as the recorded ones. From another commit with the same tree, trees and messages match but ids differ.
Record a replayable run
Section titled “Record a replayable run”logging: { replayable: true } adds a workspace-commits event to the journal when a sandbox dispatch ends, including a failed or cancelled one.
API reference: WorkspaceCommitsEvent.
When the history cannot be recorded, the event keeps the baseline, gives the reason in unavailable, and the dispatch emits a warning. The dispatch outcome never changes. This happens with:
- merge commits, or a history rewritten from the baseline;
- more than 8 MiB of patches and messages;
- a commit message in an encoding other than UTF-8;
- a patch that does not reproduce its commit’s tree.
What a replay does
Section titled “What a replay does”Pass the journal to createReplayAgent() and use the result as the agent of a dispatch() with the same brief. It replays turn by turn, in recorded order.
Commits are rebuilt through the sandbox, so replays work with cloud sandboxes too. The sandbox needs git.
Replay repairs, passes and fallbacks
Section titled “Replay repairs, passes and fallbacks”Typed-response repairs and extra passes replay as separate turns. replaying.remainingTurns counts the turns left; a replay agent is single-use, so create a new one per replay.
A fallback agent handover replays in the same turn: the stopped candidate’s events, the fallback event, then the next candidate’s turn. The next candidate’s prompt is not compared, since it restarted from the original brief. The result holds the selected candidate’s text, every candidate’s commits and their combined usage, but no result.fallback.
Handle divergences
Section titled “Handle divergences”When the replay differs from its journal, it throws ReplayDivergence, an OutpostError with code replay.
API reference: ReplayDivergenceKind.
turn, expected, actual and commit locate the difference. divergence: "warn" turns prompt, baseline, tree and unrecorded differences into warnings and keeps going. A patch that does not apply and an exhausted journal still throw.
With warn, a journal recorded without replayable replays its events without commits.
Replay a brief that names its branch
Section titled “Replay a brief that names its branch”A brief that uses {{WORK_BRANCH}} puts the branch name in the prompt. An integrate branch gets a new generated name on each run, so its prompt never matches.
Replay on a named branch with the recorded name, deleted beforehand so it starts from the baseline again, or replay with divergence: "warn".
Turn a run into a test
Section titled “Turn a run into a test”Save the journal once to fixtures/parser-fix.json with JSON.stringify(journal), and tag the commit the recorded branch started from parser-fix-base. The test replays it on a fresh branch from that tag.
The test fails with a ReplayDivergence when the brief or the baseline changes. Each run leaves its replay/… branch behind.
Limits
Section titled “Limits”- One journal is one dispatch. A whole workflow does not replay.
- Only commits are replayed. Uncommitted changes in the worktree are not recorded.
- A replay cannot be resumed, forked or steered, and has no conversation to capture.
- Signed commits are rebuilt without their signature, so their ids differ.
API: createReplayAgent · ReplayAgent · ReplayDivergence · WorkspaceCommitsEvent · Logging · readJournal