TL;DR
MEDAKA is a structured prompt that makes the model do three things before every action. First, it finds the gap between the current state and the goal. Then it proposes an action with a still-unknown number ("pour… how much?"). Only after that does it solve for that number algebraically as a separate subgoal, commit the action, and write out the full new state of every object. The method comes straight from the classics: Means-Ends Analysis (Newell and Simon, 1950s).
Plain "think step by step" struggles with tasks where you have to pick the numbers: how much of what to take, mix, or buy. The model throws out a number at random, then fudges it, loses track of what's left in the other containers, and the error snowballs down the chain. Methods that branch over options ("try three actions, pick the best") don't help either: you can't enumerate numbers, you have to derive them from equations. On weaker models they sometimes make things worse.
The method forbids the model from committing to an action until every number in it has been derived. After each step it recomputes the full state, so a made-up figure pops out as a contradiction on the next step. One caveat: we don't have the full prompt text from the paper's appendix, so the template below is reconstructed from the method description.
Want this for your own case? Apply this study to your task: AI adapts its method to what you are working on and writes the prompt.
Method Blueprint
LOOP (in a single prompt, until no gap remains):
STEP 1: DIFF — which goal conditions are still unmet → list of gaps
STEP 2: Pick an operator (action) for one gap → action with unknown numbers
STEP 3: Applicability check: are all conditions and numbers known?
NO → create a subgoal, derive the number with an equation, return to STEP 3
(deferred subgoals go on the subgoal stack)
STEP 4: Commit the action with concrete numbers
STEP 5: Write out the FULL new state (every object, not just the changed ones)
EXIT: no gaps left → final plan
Example
Task: A coffee roaster in Portland is preparing an order for a café: 6 kg of a blend. The warehouse has ready-made blends and single origins, and the target ratio has to be assembled from what's on hand. Origins repeat across different bags, so the numbers are tied to each other and eyeballing it won't work. This is the method's sweet spot: coupled parameters plus decoy bags.
Prompt:
<Role>
You are a production planner. You don't guess numbers: you derive them from equations.
</Role>
<State>
S1 (capacity 50 kg): 10 kg, 60% Brazil, 40% Colombia
S2 (capacity 50 kg): 10 kg, 100% Ethiopia
S3 (capacity 50 kg): 10 kg, 50% Brazil, 50% Ethiopia
S4 (capacity 50 kg): 10 kg, 100% Colombia
S5 (capacity 50 kg): 10 kg, 100% Robusta
ORDER (capacity 50 kg): empty
</State>
<Goal>
ORDER: 6 kg, 40% Brazil, 30% Ethiopia, 30% Colombia
Tolerance for each origin and for total volume: ±0.05 kg.
</Goal>
<Operators>
Pour X kg from A into B (0 < X ≤ current volume of A).
Composition transfers in proportion to the source's composition.
New concentration in B = (volume_B · conc_B + X · conc_A) / (volume_B + X).
</Operators>
<Procedure>
Repeat while a gap remains:
1. DIFF: list which goal conditions are not yet met.
2. OPERATOR: propose an action for one gap. Numbers may stay unknown for now.
3. APPLICABLE?: check that all conditions are met and ALL numbers are determined.
If not, declare each unknown number a subgoal. Write the equations
that link it to the current state and the goal, and solve them.
Put deferred subgoals on the subgoal stack.
4. COMMIT: only once all numbers are derived, commit the action.
5. STATE: write out the new state of ALL containers (volume and composition of each),
including the ones the action didn't touch.
Compute the next DIFF only from this written state.
If the new state contradicts the previous one, stop and find the error.
</Procedure>
<Output>
Show the steps of the loop. At the end, give the final list of actions and the final state of ORDER.
</Output>
Result: For each step the model will show the blocks DIFF → OPERATOR → subgoals with equations → COMMIT → full STATE. Bag S5 (Robusta) should stay untouched. At the end you'll get a numbered list of "pour X kg from … into ORDER" and the final composition of the order. You can check the numbers by plugging them in by hand or on a calculator.
Why It Works
The LLM's weakness. When a model writes a plan as a stream, it usually names a number first and justifies it afterward. It keeps the state "in its head" and doesn't recompute all of it. Leftovers in neighboring containers get forgotten, and one wrong figure poisons every step that follows. Branching methods don't help here: the space of options is infinite.
The LLM's strength. A model handles a small system of two or three equations well if you carve it out as its own subtask. It's also good at following a structured protocol when the output format is locked down.
How the method exploits this. Every unknown number becomes an explicit subgoal that gets solved before the action is committed. The work is done up front instead of patched afterward. Writing out the full state after each step acts like balancing the books. The next step is computed from the written figures, so anything made up shows up as a contradiction.
Control knobs: - Full state of all objects → keep it, it's the main safeguard. If you drop it and write only what changed, you lose control but save tokens. - Subgoal stack → can go for simple tasks. Keep it for tasks with coupled parameters. - The phrase "numbers may stay unknown" → without it the model slides back into naming a number right away. - Tolerance and action format → adapt to your domain (kg, dollars, units, percentages). - Stop-on-contradiction rule → add an explicit "if the balance doesn't add up, go back and find the error."
Prompt Template
<Role>
You are a planner in {domain}. You don't guess numbers: you derive them from equations.
</Role>
<State>
{objects and their current parameters: volume, composition, leftovers, limits}
</State>
<Goal>
{target state of the objects}
Tolerance: {tolerance}.
</Goal>
<Operators>
{list of allowed actions and the rules for how they change the state}
{formula for recomputing the state after an action}
</Operators>
<Procedure>
Repeat while a gap remains:
1. DIFF: list which goal conditions are not yet met.
2. OPERATOR: propose an action for one gap. Numbers may stay unknown for now.
3. APPLICABLE?: check that all conditions are met and ALL numbers are determined.
If not, declare each unknown a subgoal. Write the equations
linking it to the current state and the goal, and solve them.
Put deferred subgoals on the subgoal stack.
4. COMMIT: only once all numbers are derived, commit the action.
5. STATE: write out the new state of ALL objects (not just the changed ones).
Compute the next DIFF only from this written state.
If the new state contradicts the previous one, stop and find the error.
</Procedure>
<Output>
{answer format: loop steps, final list of actions, final state}
</Output>
What to fill in:
- {domain} — where you work: manufacturing, purchasing, dosing.
- {objects and parameters} — everything you have "in stock," with numbers.
- {target state} — what you need to end up with.
- {list of actions} — what you're allowed to do and how it changes the state.
🚀 Quick start — paste into the chat:
Here is the MEDAKA template (planning that solves for numbers via subgoals). Adapt it to my task: [your task].
Ask me questions to fill in the fields.
[paste the template above]
The LLM will ask what your objects and their current numbers are, what the goal is, which actions are allowed, and how they change the state. Without that data it can't write the state-update formula the whole method rests on. It will take the structure from the template and tailor it to your task.
Limitations
⚠️ Weak models: on nonlinear tasks (where the result depends on intermediate "shared" containers) the method barely helps small and open models. They simply lack the raw ability to derive equations. Structure is no substitute for model horsepower.
⚠️ Cost: the answer gets 2–4 times longer. That means more tokens, longer waits, and a bigger API bill.
⚠️ No gain for some strong models: on simple "linear" tasks the top models already solve almost everything, so MEDAKA adds little. On GPT-5.4 the overall result landed level with a competing method, with no clear edge.
⚠️ A single domain: it was only tested on mixing liquids. Carrying it over to cost estimates, dosing, and budgets makes sense, but the authors didn't prove it.
⚠️ Reasoning mode was off: "thinking" was disabled in every test. The paper didn't check what happens with the model's built-in reasoning turned on. Part of the gain may already come for free there.
⚠️ Check the result: the method cuts errors but doesn't eliminate them. Verify the final figures by plugging them in or with a calculator.
How They Tested It
The authors built a test set called LiquidWorld: 189 liquid-mixing tasks. Each one was tagged by difficulty: "nonlinear" (via intermediate containers), "coupled" (the same components appearing in different sources), "multiple goals," and "extra vessels." Answers were checked by a programmatic validator, no LLM judge: it applied the pouring formulas step by step and compared the result against the goal within 1–5%. MEDAKA was compared with plain Chain-of-Thought and with AoT+ (a branching method with periodic state saving). They tested 7 models, from small Gemma models up to Claude Sonnet 4.6 and GPT-5.4. Each task was run three times, with reasoning mode turned off.
Results: Claude's overall score rose from roughly 78% to 94%. On nonlinear tasks it jumped from 33% to 87%, and on "multiple goals" tasks from 50% to 89%. GPT-4o's result on tasks with extra vessels nearly quadrupled. Even accounting for token spend, single-attempt MEDAKA beat best-of-three CoT on 4 of 7 models.
The surprise: AoT+, the branching method, sometimes hurt weaker models compared with plain CoT. That backs the authors' hypothesis: when you need to compute parameters, enumerating options isn't just useless, it's harmful. Practical takeaway: if the task requires deriving a number rather than choosing an option, build your prompt around subgoals and state tracking, not around branching.
Adaptations and Extrapolations
🔧 Technique: slim down the state output → saves tokens, weaker safeguard
In the procedure, replace step 5 with:
5. STATE: write out the new state of only the changed objects; mark the rest "unchanged."
For tasks with 3–4 objects this is reasonable. The paper required writing out all vessels, and that's a key part of the method. For long tasks with dozens of objects, keep the full output.
Extrapolation: purchasing and budgets. The method is built on "gap → action with an unknown number → subgoal → commit → full state." You can carry that over to any calculation where numbers depend on each other. The authors didn't test this transfer, so treat it as an experiment:
<State>
Budget: $50,000. Inventory on hand: {...}. Supplier prices: {...}
</State>
<Goal>
Buy the set of items {...} by Friday, staying within budget and keeping {N} days of safety stock.
</Goal>
<Procedure>
[same structure DIFF → OPERATOR → APPLICABLE? → COMMIT → STATE,
where STATE = remaining budget and stock of each item after every purchase]
</Procedure>
After the answer, check the final totals by hand: the method doesn't replace verification.
Resources
- Paper: Means-Ends Analysis Helps LLMs Plan in Continuous-State Domains — Jiayi Li, Carl Kingsford, Carnegie Mellon University (Ray and Stephanie Lane Computational Biology Department, School of Computer Science).
- Code: https://anonymous.4open.science/r/medaka_code-FFD0
- Theoretical foundation: Newell & Simon, General Problem Solver / Means-Ends Analysis.
- Compared against: Chain-of-Thought (Wei et al., 2022), AoT+ (Sel et al., 2025).
- Appendices with the full algorithm (Algorithm 1, Appendix B.1) — in the original paper.