agentskit.js
Recipes

Time-travel debug

Step through a recorded agent session, rewrite a tool result, and replay from that point forward.

You recorded a session with deterministic replay. The bug happens after a specific tool call returns bad data. You want to rewrite the tool result and re-run from there — without re-recording.

createTimeTravelSession from @agentskit/eval/replay wraps a cassette in a cursor: step through it, override any chunk, fork at an index to get a fresh cassette, and hand that cassette to a replay adapter.

Install

npm install -D @agentskit/eval

Step through a session

import { loadCassette, createTimeTravelSession } from '@agentskit/eval/replay'

const cassette = await loadCassette('./fixtures/bug-427.cassette.json')
const session = createTimeTravelSession(cassette)

console.log('total chunks:', session.length)
let chunk = session.step()
while (chunk) {
  console.log(session.cursor, chunk)
  chunk = session.step()
}

Rewrite a tool result, fork, replay

The workflow:

  1. Find the chunk index where the broken tool result was emitted.
  2. override(index, {...}) with a corrected chunk.
  3. fork(index + 1) — everything up to and including the fix, discarding the broken tail.
  4. Feed the forked cassette into createReplayAdapter to re-run.
import { createReplayAdapter, loadCassette, createTimeTravelSession } from '@agentskit/eval/replay'
import { createRuntime } from '@agentskit/runtime'

const session = createTimeTravelSession(await loadCassette('./fixtures/bug-427.cassette.json'))

session.override(12, {
  type: 'tool_call',
  toolCall: { id: 'call_3', name: 'lookup_user', args: '{"id":42}', result: '{"plan":"pro"}' },
})

const fork = session.fork(13)
const runtime = createRuntime({ adapter: createReplayAdapter(fork, { mode: 'sequential' }) })
const rerun = await runtime.run('/* same initial prompt */')

API

MethodDescription
lengthTotal flattened chunk count
cursorCurrent read position
peek(i)Read chunk at absolute index without moving cursor
step()Return chunk at cursor, advance cursor
seek(i)Jump cursor to absolute index
override(i, chunk)Replace chunk at index — returns prior value
fork(i)Return a new cassette containing chunks [0, i)
snapshot()Full copy of current (possibly mutated) cassette

See also

✎ Edit this page on GitHub·Found a problem? Open an issue →·How to contribute →

On this page