Fork

Branch a real thread from a saved point and try a different input, model or prompt, in a fresh sandbox.

A fork is a new branch of a thread that starts from a snapshot of an earlier point. The original branch is untouched. Use it to reproduce a production issue, try a fix, or compare two answers side by side.

Fork points

After a turn that used the sandbox, threads snapshots the sandbox's files. Those snapshots are the points you can fork from, and timeline() marks them with fork_point.

TypeScript snapshots after a turn that changed something (any tool call that isn't read-only). Python also snapshots after turns that only read from the sandbox. A thread without a sandbox has no fork points.

Fork and continue

Open the thread with the sandbox adapter to restore into, pick a point, fork, and run the child branch with the same agent.

const opened = await openThread(store, first.thread.id, { sandbox });
if (!opened.ok) throw new Error(opened.error.message);
const thread = opened.value;

const [point] = await thread.forkPoints();
if (point === undefined) throw new Error("no fork point yet");

const forked = await thread.fork(point);
if (!forked.ok) throw new Error(forked.error.message);
const child = forked.value;

const retry = await writer.run("Rewrite it in French.", { store, thread: child });
console.log(retry.status, child.branch !== thread.branch);

fork returns a value, not an exception. Common failures:

CodeWhy
sandbox_requiredThe thread was opened without a sandbox to restore into
no_snapshot_boundaryThe event you passed isn't a fork point on this branch
snapshot_restore_failedThe sandbox adapter couldn't restore the snapshot, or its provider doesn't match the snapshot's

forkPoints() returns an array in TypeScript. In Python, fork_points() returns Ok / Err like the other reads.

What a fork isolates

  • Sandbox. The child gets its own sandbox, restored from the snapshot. Changes on the fork never reach the original sandbox.
  • Log. The child shares history up to the fork point and records its own events after it. The parent branch never changes.
  • Knowledge. By default the fork searches the knowledge base as it was at the fork point, so results are reproducible. Pass knowledge: "current" to use today's documents instead.
await thread.fork(point, { knowledge: "current" });

Continue the child with the same agent definition. A thread is pinned to the config it started with.

Replay without real side effects

Python only today.

A stub fork answers every external operation from what the original branch recorded after the fork point. Nothing goes live: a call the original never made fails the run with unmatched_external_op instead of reaching the outside world. Use it to replay a production turn against a changed prompt safely.

Python
stubbed = await thread.fork(points.value[0], mode="stub")

Stub mode needs a sandbox that blocks all network access. TypeScript accepts mode: "stub" and checks the sandbox, but runs on the child branch are not stubbed yet, so don't rely on it.

Edit on GitHub

On this page