Git-like forking for AI sessions
A session with an AI runs turn after turn, each one building on the context before it. Real thinking branches. Session forking lets you branch a conversation at any turn instead of losing the thread.
And it isn't a sketch — it's shipped code. →
fork_session lives in microsoft/amplifier-foundation, in amplifier_foundation/session/fork.py — a working feature, not a proposal.
So why fork at all? Consider the cost of staying linear. →
Verified present & testedTwenty turns into a good conversation, you want to explore a tangent. Without forking, you either abandon the thread you built or re-explain all of its context from scratch.
Forking removes the choice — here's the core move. →
fork_session() loads the parent's transcript, slices it to a chosen turn, and writes it to the new session — so the branch inherits every prior message. The forked session is independently resumable and addressable.
But what exactly is “a turn”? →
load_transcript() reads the parent's messagesslice_to_turn() cuts context up to the fork pointwrite_jsonl() writes it to the new session's transcriptA turn is a user message plus all subsequent non-user messages until the next user message — and turns are 1-indexed for user-facing operations. That precise definition is what makes forking at an exact point meaningful.
And the branching itself? It was already in the kernel. →
The kernel, amplifier-core, already carried the branching primitive: AmplifierSession accepts parent_id and emits a session:fork event. The fork utilities are policy built on that — “zero changes required to amplifier-core.”
Which means forks compose — and that's the payoff. →
Fork a fork a fork. A test confirms it: parent → fork1 → fork2 yields a lineage of depth 2 with 2 ancestors. Every branch still knows its parent and its full ancestry — an auditable tree of thought, not one lost thread.
So what does that change about how you work? →
Stop treating an AI conversation as one throwaway line. Fork it at any turn, keep every path, and let your thinking be as non-linear as it really is.
Conversations as branchable, versioned artifacts.
Data as of: 2026-04-09 (HEAD 0965a34, branch fix/session-naming-timeout-configurable).
Feature status: Verified present and tested in microsoft/amplifier-foundation; built as a policy layer on the amplifier-core kernel's parent_id / session:fork mechanism.
Research performed (commands run):
git remote -v && wc -l amplifier_foundation/session/fork.py → origin git@github.com:microsoft/amplifier-foundation.git; 492 lines.venv/bin/python -m pytest tests/test_session.py -q → 63 passed in 0.05sgit show --stat 2ba2a2c → introducing commit: “policy layer built on existing kernel mechanisms (parent_id). Zero changes required to amplifier-core.”grep -rn 'parent_id|session:fork|SESSION_FORK' amplifier_core/session.py amplifier_core/events.py → kernel primitive confirmedsed -n '1,65p' amplifier_foundation/session/messages.py → turn definition, 1-indexedsed -n '624,633p' tests/test_session.py → nested-fork lineage depth == 2, ancestors == 2Gaps: No dedicated end-user fork CLI subcommand exists (session CLI exposes diag, repair, rewind, info, find only). The amplifier-core copy read here is the ramparte/amplifier-core fork; upstream assumed equivalent but not directly inspected.
Primary contributors: Brian Krabach (author of the fork utilities, introducing commit 2ba2a2c, and most subsequent fork.py/session commits); Salil Das (partial-orphan transcript fix, commit 0188499, 2026-03-21).