Agent Branching (Beta)
Beta / preview API. Requires a session store so snapshots are persistent. Read agents.md first.
A snapshotId is an immutable checkpoint, like a git commit. You can fork as
many independent timelines as you want from the same snapshot — each turn from a
snapshot creates a new, independent snapshot; the original is unchanged.
To branch, open a new chat attached to an earlier snapshot via
chat({ snapshotId }).
Server-side branching
import { z } from 'genkit';
import { InMemorySessionStore } from 'genkit/beta';
import { ai } from './genkit.js';
export const assistant = ai.defineAgent({
name: 'assistant',
system: 'You are a helpful assistant.',
store: new InMemorySessionStore(),
});
const root = assistant.chat();
const res1 = await root.send('Hello!');
const checkpoint = res1.snapshotId; // branch point
// Branch A — forks from `checkpoint`.
const branchA = assistant.chat({ snapshotId: checkpoint });
await branchA.send('My name is Bob.');
const resA = await branchA.send('What is my name?'); // -> Bob
// Branch B — forks from the SAME `checkpoint`, fully independent.
const branchB = assistant.chat({ snapshotId: checkpoint });
await branchB.send('My name is John.');
const resB = await branchB.send('What is my name?'); // -> John
Client-side branching ("pick a variant")
A common pattern: generate two variants from the same checkpoint in parallel, let the user pick one, and continue from the chosen snapshot.
import { remoteAgent } from 'genkit/beta/client';
const agent = remoteAgent({ url: '/api/branchingAgent' });
let snapshotId: string | undefined; // current branch point
async function twoVariants(text: string) {
// Each variant gets its own chat branching from the same snapshot
// (or a fresh session when there's no branch point yet).
const makeChat = () =>
snapshotId ? agent.chat({ snapshotId }) : agent.chat();
const [a, b] = await Promise.all([
makeChat().send(text),
makeChat().send(text),
]);
// a.snapshotId !== b.snapshotId — both branch from the same point.
return { a, b };
}
// When the user picks a variant, its snapshotId becomes the new branch point:
function pick(chosenSnapshotId: string) {
snapshotId = chosenSnapshotId;
}
Restoring history from a snapshot
Use agent.getSnapshot(snapshotId) to read a snapshot's state without starting a
turn — handy for restoring a UI after a reload (e.g. snapshotId stored in the
URL). The server must expose the agent's getSnapshotDataAction (see
agents.md).
import type { Part } from 'genkit/beta';
import { remoteAgent } from 'genkit/beta/client';
const agent = remoteAgent({ url: '/api/branchingAgent' });
const snapshot = await agent.getSnapshot(snapshotId);
const history = (snapshot?.state?.messages ?? [])
.filter((m) => m.role === 'user' || m.role === 'model')
.map((m) => ({
role: m.role,
text: (m.content ?? [])
.filter((p: Part) => p.text)
.map((p: Part) => p.text)
.join(''),
}));
Abandoned branches simply remain in the store as immutable snapshots; nothing is overwritten when you branch.