Memory Branching
Memory branching gives you a git-style fork, diff, and merge workflow for the entire memory state. Create parallel branches to explore different contexts, run experiments, or isolate changes — without touching the main memory state. When you are ready, merge branches back using CRDT-inspired conflict-free resolution.
How it works
Branching operates in three phases:
- Fork — A new branch is created as a copy-on-write snapshot of the current memory state. No data is duplicated until a write is made to the branch.
- Diverge — Writes made in the branch are isolated to that branch. The main branch continues to evolve independently. Both branches track their own commit history.
- Merge — When the branch is ready, its changes are merged back into the target branch. Non-conflicting changes are applied automatically. Conflicts are resolved using the configured merge strategy.
API
Create a branch
bash
POST /memory/branch
{
"name": "experiment-new-persona",
"description": "Testing a revised user profile model"
}
# Response:
# { "branchId": "branch_abc123", "baseBranch": "main", "createdAt": "2026-02-25T10:00:00Z" }List branches
bash
GET /memory/branches
# Response:
# [
# { "id": "main", "commits": 142, "createdAt": "..." },
# { "id": "branch_abc123", "name": "experiment-new-persona", "divergedAt": "..." }
# ]Merge a branch
bash
POST /memory/merge
{
"source": "branch_abc123",
"target": "main",
"strategy": "crdt-auto"
}Diff between branches
Before merging, inspect the diff to see exactly what changed between two branches across all memory tiers:
bash
GET /memory/branches/branch_abc123/diff/main
# Response:
# {
# "added": [ { "tier": 3, "key": "domains.persona", "value": "..." } ],
# "modified": [ { "tier": 2, "key": "note_xyz", "before": "...", "after": "..." } ],
# "removed": []
# }The diff is scoped to entries that diverged after the branch point. Entries that were modified on both branches simultaneously are flagged as conflicts in the diff output.
Merge strategies
| Strategy | Behavior |
|---|---|
crdt-auto | Applies CRDT-inspired last-write-wins semantics with vector clock ordering. All non-conflicting changes are merged automatically. Recommended for most use cases. |
interactive | Pauses the merge when a conflict is detected and surfaces a resolution prompt via GET /memory/merge/:mergeId/conflicts. Each conflict must be resolved manually before the merge can complete. |
source-wins | The source branch always wins conflicts. Use when you know the branch state is authoritative. |
target-wins | The target branch always wins conflicts. Use when you want to incorporate only the non-conflicting additions from the source branch. |
💡
crdt-auto resolves the vast majority of real-world merges without any manual intervention. Only use interactive when the merged content will affect critical long-term memory entries like user profiles or architecture decisions.Use cases
- Scenario testing — Fork memory before running a speculative what-if analysis. If the results are useful, merge them back. If not, discard the branch.
- User onboarding experiments — Run two variants of an onboarding flow in parallel branches, compare the resulting user profiles after N sessions, and promote the better-performing branch to main.
- Safe refactoring — Restructure graph entities or profile keys in a branch without risking the live memory state. Validate the new shape, then merge.
- Debugging — Reproduce an issue by forking the memory state at a known-good point and replaying events in a branch, leaving the production state untouched.