Skip to main content

Branch Logs

Branch logs let several agents start from the same backup snapshot, write local memory independently, and later merge only the branch you want to keep.

Branch logs move the source-of-truth records between stores or machines. Pair them with aidememo session handoff when an orchestrator also needs a compact, receiver-specific prompt artifact: merge the chosen branch, then generate or consume the handoff packet with the same session_id.

This is useful when the memory itself is part of an experiment:

SituationWhy branch logs help
Several cloud agents try the same task from one baselineEach worker writes its own facts without sharing a hot SQLite file.
You compare prompting, extraction, or retrieval strategiesKeep candidate lessons separate, run an external eval, then merge the winner.
A risky automation may write noisy memoryPush the branch log, inspect it, and merge only if the result is useful.
You need a replayable artifact for an agent runThe segment JSONL plus manifest records what that branch tried to add.

Do not use branch logs as full multi-master conflict resolution. Merge is idempotent and append-oriented: identical or stale entity/fact records are skipped, newer records with the same ID are applied in LWW order, relation identities are inserted or replaced, independent new facts are appended, and semantic conflicts such as two competing decisions are left to the caller's policy.

Workflow

Create a baseline backup:

aidememo --store ./main.sqlite backup create ./shared

Restore that backup into separate candidate stores:

aidememo --store ./candidate-a.sqlite backup restore ./shared/backup-01... --force
aidememo --store ./candidate-b.sqlite backup restore ./shared/backup-01... --force

Run different attempts and write their memory locally:

aidememo --store ./candidate-a.sqlite fact add \
"Candidate A used broad context and produced noisy results." \
--type lesson \
--entities Experiment

aidememo --store ./candidate-b.sqlite fact add \
"Candidate B used focused context and produced the best result." \
--type lesson \
--entities Experiment

Push each branch as a delta after the backup cursor:

aidememo --store ./candidate-a.sqlite branch push \
--branch candidate-a \
--base ./shared/backup-01... \
./shared

aidememo --store ./candidate-b.sqlite branch push \
--branch candidate-b \
--base ./shared/backup-01... \
./shared

Merge only the winning branch:

aidememo --store ./main.sqlite branch merge --branch candidate-b ./shared

Discarding a branch means not merging it. If you want to remove the stored artifact too, delete that branch directory or S3 prefix:

./shared/branches/candidate-a/
s3://bucket/prefix/branches/candidate-a/

Omit --branch to merge every branch under the source:

aidememo --store ./main.sqlite branch merge ./shared

SDK And Binding Calls

The Python composition SDK exposes the same flow for code-first agents:

from aidememo_agent import Memory

candidate = Memory.open(store_path="./candidate-b.sqlite", storage_backend="libsqlite")
candidate.branch_push(
"candidate-b",
"./shared",
base="./shared/backup-01...",
)

main = Memory.open(store_path="./main.sqlite", storage_backend="libsqlite")
main.branch_merge("./shared", branch="candidate-b")

aidememo-python exposes branch_push(branch, destination, base=None) and branch_merge(source, branch=None). aidememo-napi exposes branchPush and branchMerge with JSON-string reports. aidememo_nif exposes AideMemoNif.branch_push/4 and AideMemoNif.branch_merge/3 with decoded map reports. Local paths use the already-open native store handle, which avoids reopening the same file from SDK/plugin code. S3 branch URIs should go through the CLI, because S3 support is controlled by the CLI's --features s3 build.

Storage Layout

Local branch logs are stored under:

<DEST>/branches/<branch-id>/segments/<segment-id>.jsonl
<DEST>/branches/<branch-id>/segments/<segment-id>.manifest.json

S3 branch logs use the same prefix shape and compress payloads:

s3://bucket/prefix/branches/<branch-id>/segments/<segment-id>.jsonl.zst
s3://bucket/prefix/branches/<branch-id>/segments/<segment-id>.manifest.json

Every segment manifest stores byte counts and SHA-256 checksums for both the stored object and decoded JSONL payload. Merge verifies these before import.

Guarantees And Limits

What is covered:

  • branch push --base <BACKUP> exports records written after the backup manifest's sync cursor.
  • branch merge --branch <ID> imports only that branch.
  • Merging the same segment again does not duplicate facts because it goes through sync_import.
  • All selected segments retain their original LWW order; after import, records actually changed by the merge receive one coordinator relay timestamp so an already-advanced downstream sync cursor still observes historical IDs.
  • The relay timestamp applies to entity/fact records. Relation inserts or replacements change the complete relation-snapshot generation, which makes an already-advanced downstream replay the relation snapshot instead.
  • S3 is a transport for branch artifacts, not the live database backend.

What is not covered yet:

  • Automatic quality scoring of candidates.
  • Semantic conflict resolution between competing decisions.
  • A first-class branch delete command.
  • Bidirectional live replication between running stores.

For the current validation evidence, see Measurements, "Branch Log Push / Merge".