EmpryoEmpryo.beta
concepts

The Marionette

A prompt-compiler pre-pass: a cheap model walks the code graph before the main agent moves and attaches a map — files:lines, wiring, memories — to your prompt.

Every Empryo prompt already carries the Genome: the whole repo as a ranked dependency graph. The marionette adds the second half — a map of *this request*. A cheap model surveys the same graph before the main agent sees your prompt, and attaches what it found: the files this sentence is about, with line ranges, how they wire together, and which past decisions apply.

The Genome says what the repo is. The marionette says which rooms you just pointed at. The agent starts warm instead of resolving that on frontier tokens.

Your prompt is never rewritten. The map rides under it.

It finds the room. It never picks the fix.

One rule outranks everything else in the design: the marionette locates, and only locates. The output schema has no field for a cause, a fix shape, or an acceptance criterion — a guess has nowhere to live. That discipline was bought with a benchmark: a pre-pass that wrote hypotheses dropped an opus-class agent from 3/3 fixes to 1/3, and one of its briefs told the agent to *preserve* the bug it was sent to kill. The locator rewrite — rooms, wiring, memories, open doors, nothing else — went back to 3/3 with four fewer main-agent steps and −11% median spend. A cheap model's opinions anchor an expensive model's judgment. Its observations arm it.

Using it

/marionette fix the race in tab restore     # compile this prompt only
/marionette fix it --steps 12 --time 90s    # bound the survey
/marionette on | off | status               # always-on toggle, per scope

Always-on also lives in Settings → Router → Behaviors on desktop, and headless runs take --marionette / --marionette-mode <lane>.

The map

While the compile streams, the map assembles folded under your prompt — expand it to read:

sectioncontents
askseach distinct behaviour you asked for, quoting your words
locifile.ts:120-180 · symbol · role, ranked primary/adjacent
strandswiring between the loci — callers, co-changes, blast radius
memoriespast decisions that apply, by id
unmappedwhat the survey did not reach, stated plainly

Every strand names the tool that produced it (navigate, genome_impact, …) — nothing in the map is a guess, and nothing in it is advice. Which tap to turn stays the main agent's call.

Lanes

Set per scope with /marionette none|fast|assist|deep or "marionetteMode" in config:

lanewhat runsrecalllatencycost (haiku)
noneindex retrieval only, no model83%0.2sfree
fast *(default)*retrieval + one model pass83%~20s~$0.01
assistretrieval + short tool loop72%~60s~$0.05
deepfull read-only survey agent53%~2min$0.09–0.13

Recall figures are the clean bench set. On a deliberately messy one — typos, product nouns that match no symbol — fast's retrieval stage now lands 82% of gold files in the dossier (up from 68% before the pass-5 tuning: typo correction against the repo's own vocabulary, light stemming, a wider candidate list, and a rarity boost for files literally named after a request word). The model pass buys precision on top: it decides which candidates belong on the map.

Measured against a frontier main

The harness also runs the whole chain (bench/marionette-ab/e2e.ts): opus-5 as the main agent, the same diagnosis prompt, four arms. On a request whose wording barely overlaps the code that owns it:

armfirst gold file touchedmain-agent spend
opus alonestep 3$0.68
opus + explore subagent firststep 2$0.69
opus + marionette (fast, haiku)step 1$0.37 + $0.014 compile

The $0.014 compile put the right file in the agent's *first* tool call and cut the frontier bill 46%. The counterweight stays in the open: when the cheap judge drops a right room from the map, the pre-pass costs more than it saves — map quality is the tuning frontier, and the bench that measures it ships in the repo.

Routing

The marionette lane in /router picks its model (taskRouter.marionette). Unset, it falls back to the spark slot — cheap by default. The pre-pass carries the same read-only intelligence belt as subagents (LSP, code graph, impact analysis, memory search — never a mutation tool), and a failed compile always degrades to your raw prompt: the pre-pass can never kill a turn.

Why not just dispatch an explore agent?

Explore is chosen by the main agent mid-turn; the marionette is guaranteed, runs *before* the turn on a clean context, emits a constrained schema instead of free prose, can skip the tool loop entirely (none/fast), and surfaces project memories. Explore remains the right tool once the agent discovers it needs eyes on a subsystem — the marionette owns the cold start. The end-to-end bench agrees: a forced explore-first arm paid control prices on every task and never beat the map on orientation, because its report lands mid-turn while the map lands at step zero.