feat(cli): multi-harness batch reflection#3274
Draft
sarahwooders wants to merge 9 commits into
Draft
Conversation
… aggregation letta dream can now ingest recorded sessions from multiple coding harnesses (claude, codex, openhands, letta conversations, normalized transcripts) in one run, reflect on them in parallel, and aggregate the results into the agent's memory filesystem. - src/agent/trajectories/: normalized-v1 as the single interchange format — Claude Code and Codex store normalizers, OpenHands events (migrated from dream-sources), letta conversation transcripts, and listed conversation messages, all through one shared row pipeline (caps, timestamps, shapes) - src/cli/subcommands/dream-pipeline/: select (repeatable --from, session-id cursors, per-agent ingest ledger), normalize-first packing (batch on normalized sizes), batch reflection into fresh seeded memfs trees, and one aggregation pass that owns the final commit via the existing memory-worktree merge-back + recompile path - one persistent hidden reflector agent per primary agent; every batch and the aggregator run as fresh concurrent conversations on it, and trajectories are recorded by listing each conversation's messages and normalizing them - --plan (batch preview), --aggregate <run-id|latest> (re-run integration over recorded batches), --force (bypass ledger), and a self-contained viz.html per run (trajectories, output trees, git diffs, reports) - --from is now repeatable, fixing the silent last-flag-wins parse bug; the old dream-sources staging path is removed - cross-agent memory guard now recognizes the parent's .dream/ directory as parent-scoped so batch output trees survive into subagent shell envs; deployed subagent sessions no longer auto-enable memfs on cloud; reflection deploys get the same prompt-surface flags as fresh reflection subagents; provider-fallback retry now forwards memoryScope
…agent, md prompts, single pass
- Aggregator is its own persistent hidden agent (default system prompt +
aggregator persona block from the batch-reflection prototype); the
aggregation pass runs as a fresh conversation on it, deployed
general-purpose. Reflections stay as concurrent conversations on the
reflector.
- One aggregation pass over the run's batches/ directory (path given
inline in the prompt); no payload manifests, no $TRANSCRIPT_PATH for
the aggregator, no inlined parent-memory snapshot.
- Prompt text moved to dream-pipeline/prompts/*.md with the prototype's
{{var}} templating; batch prompts list their input transcripts inline.
- Dead code trimmed: unused runId/ledger/skippedEmpty fields, viz
merge-stage loader.
sarahwooders
requested review from
4shub,
carenthomas,
christinatong01,
cpacker,
devanshrj,
jnjpng and
kl2806
as code owners
July 8, 2026 01:46
cpacker
marked this pull request as draft
July 8, 2026 02:52
…at they select Every run reflects whatever its --from specs select; cursors (claude:<session>) are the way to narrow repeat runs. Removes ledger.ts, --force, and the skippedByLedger plumbing.
…gate archiving - No manifest.json: --aggregate reruns rebuild batch results from each batch directory's report.json; the viz derives everything from batch artifacts (reports now record the reflector agent id). - Workers are reused whenever their stored agent still exists; model is matched only at creation time. - --aggregate overwrites the previous aggregate artifacts instead of archiving them as aggregate-prev-<n>.
… synthesizes diffs Each batch reflection now works in a git clone of the primary agent's memory filesystem at a shared base revision, reconciling its batch's learnings against existing memory in place (dedupe happens at the edge, not the center). Each batch records diff.patch against the base; the aggregator's primary input is the set of diffs — it surveys the file-change map, decides structure changes, dispatches subagents for focused aspects (e.g. all human.md changes), and lands ONE synthesized edit rather than attempting any git merge. Replaces fresh-seeded batch trees (seed.ts) and reverts the renderInitialMemoryFile export.
…rofile Deploying the aggregator as general-purpose dropped the launch profile that points $MEMORY_DIR/cwd/sandbox at the memory worktree; the agent then resolved the real memfs path itself and committed directly, bypassing finalize/recompile. Deploy as subagentType reflection — the agent's own (default + persona) system prompt is unaffected.
sarahwooders
force-pushed
the
worktree-dream-multi-harness
branch
from
July 8, 2026 06:03
0ee629b to
7de1e2a
Compare
…ession id = conversation id The per-harness implementations (claude-code, codex, openhands, letta, normalized-file) move to src/agent/trajectories/sources/, leaving the shared pieces (types, normalize-core, store-utils, registry, letta-messages) at the module root. A letta conversation IS the session, so its DiscoveredSession.sessionId is now the conversation id rather than the <agent>/<conversation> locator.
…p letta-messages One-shot headless runs now append the reflection transcript on success, mirroring bidirectional mode — so dream workers (deployed subagent conversations) record locally like any session. Trajectory recording then reads that transcript through the same letta source used for ingestion, replacing the conversations-API fetch: letta-messages.ts, its wire-shape handling, and the pagination helper are gone.
The source's name now matches its scheme (transcript:<file|dir>), like claude-code.ts matches claude:, and stops colliding with normalize-core.ts — the shared conversion engine it never uses.
This was referenced Jul 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
letta dreamcan now form memory from recorded coding sessions across multiple harnesses — Claude Code, Codex, OpenHands, Letta conversations, or pre-normalized files — not just the agent's own conversation history. It follows the batch-reflection prototype's design (normalize → batch → reflect → aggregate), adapted to letta-code's production subagent and memfs machinery.How it works
Sources (
--from, repeatable):claude/codex~/.claude/projects/~/.codex/sessionsclaude:<session-id-or-prefix>openhands:<conversation-dir>letta/letta:<conv-id>/letta:<agent-id>transcript:<file|dir><conversation-id>(bare)Every run is recorded under
~/.letta/transcripts/<agent>/.dream/runs/<run-id>/, one self-contained directory per batch (input/,output/clone,diff.patch,trajectory.json,report.json— trajectories are fetched from the conversations API and normalized to the same format as the inputs), plusaggregate/and a self-containedviz.htmlshowing every agent's trajectory, report, inputs, memory tree, diffs, and agent/conversation ids.Commands
Verified end-to-end on Letta Cloud (opus-4.6), on a fresh agent: 20 sessions (10 Claude Code + 10 Codex) → 9 concurrent batch reflections, 9/9 committed, 683 diff lines total → one synthesized aggregation commit producing 7 cohesive memory files, ~15 min wall clock.
Changes outside the new modules (kept minimal)
subagents/manager.ts— reflection deploys get the same prompt-surface flags as fresh reflection agents; provider-fallback retry now forwardsmemoryScope(latent bug).tools/impl/shell-env.ts— the cross-agent memory guard recognizes the parent's.dream/directory as parent-scoped (batch clones live there; without this the guard silently unset$MEMORY_DIR).headless.ts— subagent sessions no longer auto-enable memfs on cloud for deployed memfs-less workers.agent/create.ts—asSubagentoption to create harness-managed worker agents (hidden, no memfs) from a non-subagent process.utils/transcript-paths.ts—getDreamRootDir(shared with the memory guard).cli/subcommands/dream-sources/— replaced by the trajectories module;transcript:now means normalized-v1 files.Test plan
bun run check— 10/10 pass