Sequential workers (default)
All steps
Parts of this pattern
- Question Input / output
- The question to answer, such as 'What is Iceland's population density?'.
- Planner LLM call
- Called once: writes every tool call upfront, using #E placeholders for results it cannot see yet.
- Search Tool
- Runs the plan's lookups, such as Iceland's population as #E1 and its area as #E2.
- Calculator Tool
- Runs the arithmetic step, dividing #E1 by #E2 once those values have been substituted in.
- Evidence Memory
- Stores each tool result under its variable (#E1, #E2, #E3) for the solver to read.
- Solver LLM call
- Called once: reads the question, plan and all evidence together and writes the final answer.
- Answer Input / output
- The solver's final answer with a one-sentence justification.
- Question → Planner
- The question goes to the planner, which is only ever called this one time.
Question: What is Iceland's population density?
- Planner → Search#E1 #E2 #E3
- The full plan, a list of tool calls with placeholders, which the workers run with no model calls between.
Plan: Get population. #E1 = Search[Iceland population] Plan: Get area. #E2 = Search[Iceland area km2] Plan: Divide. #E3 = Calculator[#E1 / #E2]
- Search → Calculator#E1, #E2
- Earlier results are substituted for #E1 and #E2 in the calculator's input, with no model call.
Calculator[#E1 / #E2] becomes Calculator[376000 / 103000]
- Search → Evidence
- Each search result is saved under its placeholder variable.
#E1 = 376,000 people; #E2 = 103,000 km2
- Calculator → Evidence
- The calculator's result is saved as the last piece of evidence.
#E3 = 3.65
- Evidence → Solver
- The plan and every piece of evidence are given to the solver in one prompt.
Plan and evidence: #E1 = 376,000; #E2 = 103,000 km2; #E3 = 3.65
- Solver → Answer
- The solver's single pass produces the answer; the planner is never revisited.
About 3.7 people per km2, from 376,000 people over 103,000 km2.
Parallel evidence
Planned calls that do not reference each other's #E results run at the same time; only a call that needs an earlier result waits for it.
All steps
Parts of this pattern
- Question Input / output
- The question to answer, such as 'What is Iceland's population density?'.
- Planner LLM call
- Called once: writes every tool call upfront with #E placeholders, exactly as in the sequential version.
- Search Tool
- The population lookup. It references no other result, so it starts as soon as the plan is parsed.
- Search Tool
- The area lookup. It is independent of #E1, so it runs at the same time.
- Calculator Tool
- The division step. Its input mentions #E1 and #E2, so it waits for both, then runs.
- Solver LLM call
- Called once: reads the question, plan and all evidence together and writes the final answer.
- Answer Input / output
- The solver's final answer with a one-sentence justification.
- Question → Planner
- The question goes to the planner, which is only ever called this one time.
Question: What is Iceland's population density?
- Planner → Search#E1
- The first planned call has no #E in its input, so it is started immediately.
#E1 = Search[Iceland population]
- Planner → Search#E2
- The second planned call is also free of #E references, so it starts in the same wave as #E1.
#E2 = Search[Iceland area km2]
- Search → Calculator
- The population result is substituted for #E1 in the calculator's input.
#E1 = 376,000
- Search → Calculator
- The area result is substituted for #E2; with both in place, the calculator is released.
#E2 = 103,000 km2
- Calculator → Solverevidence
- With the last step done, the plan and all three results (#E1 to #E3) go to the solver together in one prompt.
#E1 = 376,000; #E2 = 103,000 km2; #E3 = 3.65
- Solver → Answer
- The solver's single pass produces the answer; the planner is never revisited.
About 3.7 people per km2, from 376,000 people over 103,000 km2.
← → neighboursesc atlas
ReWOO
Also known as Reasoning WithOut Observation · Planner-worker-solver
Plan every tool call upfront using placeholders (#E1, #E2), run them, then a solver writes the answer in one pass.
Introduced by Xu et al. (2023)
The authors' affiliations are not confirmed: the paper's first page lists only email addresses (microsoft.com, tamu.edu, ncsu.edu), so no organisation is given here.
Measured over one run
Sequential workers
- Nodes
- 7. Boxes in the diagram: models, tools, stores, people and plain code.
- LLM calls
- 2. Model invocations in the first scenario: each time a model or agent node starts thinking, plus each branch it decides.
- Tool calls
- 2. Messages sent to a tool node in the first scenario.
- Steps
- 5. Steps in the first scenario, with repeated steps counted every time they run.
- Scenarios
- 1. Distinct example runs you can switch between on the diagram.
- Loop
- no. Whether the flow cycles back on itself until a condition is met.
- Parallel
- no. Whether two or more messages are in flight at the same time.
- Branch
- no. Whether the flow takes one path out of several, chosen at run time.
- Human in the loop
- no. Whether a person appears as a node, to approve, correct or answer.
- Autonomy
- medium. How much the model decides the control flow itself, from fixed code paths (low) to open-ended (high).
- Cost
- medium. Relative token spend per request.
- Latency
- medium. Relative wall-clock time per request.
Parallel evidence
- Nodes
- 7. Boxes in the diagram: models, tools, stores, people and plain code.
- LLM calls
- 2. Model invocations in the first scenario: each time a model or agent node starts thinking, plus each branch it decides.
- Tool calls
- 4. Messages sent to a tool node in the first scenario.
- Steps
- 4. Steps in the first scenario, with repeated steps counted every time they run.
- Scenarios
- 1. Distinct example runs you can switch between on the diagram.
- Loop
- no. Whether the flow cycles back on itself until a condition is met.
- Parallel
- yes. Whether two or more messages are in flight at the same time.
- Branch
- no. Whether the flow takes one path out of several, chosen at run time.
- Human in the loop
- no. Whether a person appears as a node, to approve, correct or answer.
- Autonomy
- medium. How much the model decides the control flow itself, from fixed code paths (low) to open-ended (high).
- Cost
- medium. Relative token spend per request.
- Latency
- medium. Relative wall-clock time per request.
Counted from the first scenario's timeline when the site is built.
Problem
A ReAct-style agent calls the model after every tool result, and each call re-sends the whole growing transcript, including the instructions and every earlier observation. For a question that needs four lookups, that means four or five long prompts, each one mostly repeating the last. Tokens, time and money go to re-reading, not to thinking.
How it works
ReWOO, short for Reasoning WithOut Observation, separates thinking from doing. It has three roles.
The planner sees the question and writes the whole plan in one go. It cannot know the tool outputs yet, so it names them with placeholders: “#E1 = Search[Iceland population]”, “#E2 = Search[Iceland area]” and “#E3 = Calculator[#E1 / #E2]”.
The workers, here search and calculator, then run the plan step by step. Plain code does the work: it substitutes earlier results into later inputs and calls each tool. No model is involved, and every result is saved to the evidence store.
Finally the solver receives the question, the plan and all the evidence together, and writes the answer in a single call. The model is invoked exactly twice, no matter how many tools run. The authors report substantial token savings on multi-hop question answering compared with ReAct-style prompting.
What makes ReWOO distinctive is what is missing from the diagram: there is no edge back to the planner. Once the plan is written, it is final.
The workers do not have to run one at a time. In the parallel-evidence variant, calls whose inputs mention no #E variable start together, and a call such as the calculator waits only for the results it names. That scheduling idea is the heart of LLMCompiler, which adds streaming and a joiner that can replan.
When to use
- The steps can be named before seeing any results, as in multi-hop lookups or standard report assembly.
- Token cost matters, or the same model runs many similar jobs.
- You want a plan you can inspect or cache before any tool executes.
When to avoid
- Later steps depend heavily on what earlier tools return, for example “open whichever result looks most relevant”.
- Tools fail often, so the plan needs adjusting mid-run. Plan-and-Execute or ReAct recover better.
- The task is a single lookup.
Trade-offs
You save calls and tokens, and gain a plan that can be validated or logged first. You lose adaptivity: the planner is committing to a path with incomplete information. If step one returns something surprising, steps two and three still run as written.
Failure modes
- Wrong plan, confidently executed: an early mistake propagates through every placeholder. Validate plans against tool schemas before running them.
- Missing dependencies: a step references #E4 that does not exist. Check placeholders before execution.
- Tool errors: one failure leaves a hole in the evidence. Pass the error to the solver so it can say what it could not determine.
- Solver overreach: with thin evidence it answers from memory. Tell it to admit gaps.
Build it with your AI
Sequential workers
Paste this into Claude Code, Cursor, ChatGPT or any AI coding assistant.
Implement the ReWOO pattern in this codebase, using the LLM client and language we already use.
## Goal
Answer a question with two model calls on the happy path: a planner that writes every tool call upfront with #E placeholders, and a solver that answers from the collected evidence.
## How it works
1. Call the planner model once with the Planner prompt, passing the question and the tool descriptions.
2. Parse the reply into an ordered list of steps, each with a reason, a variable (#E1, #E2...), a tool name and an input string.
3. Validate the plan before running anything: every tool name exists, every variable is unique, and every #E an input mentions belongs to an earlier step.
4. Run the steps in order with plain code and no model calls: substitute the stored evidence for each #E in the input, call the tool, and store the result under its variable.
5. Call the solver model once with the Solver prompt, passing the question and the plan with every step's evidence filled in, and return its answer.
## Prompts
### Planner prompt
```markdown
For the question below, make a plan of tool calls that will gather
everything needed. Write the whole plan now. You will not see any
tool output before the plan is executed.
Tools:
{{tool_descriptions}}
Format, one pair per step:
Plan: a short reason for this step
#E1 = Tool[input]
A later step may use the output of an earlier one by writing its
variable (#E1, #E2, ...) inside its input.
Question: {{question}}
```
### Solver prompt
```markdown
Solve the question using only the plan and the evidence below. If the
evidence is missing or contradictory, say so instead of guessing.
Question: {{question}}
Plan and evidence:
{{plan_with_evidence}}
Give the final answer with one sentence of justification.
```
## Stop rule
Stop after the solver's single call; the planner is never called again (an LLM used as a worker tool counts as a tool, not a planner call). If the plan fails validation twice, stop before any tool runs and return the validation errors with a failed status.
## Requirements
- Cap the plan length (default 8 steps) and give each tool call a timeout (default 30 seconds).
- If the plan cannot be parsed or fails validation, retry the planner once with the errors appended; do not run a partly valid plan.
- When a tool call errors or times out, store the error text as that variable's evidence and keep going, so the solver can say what it could not determine.
- Log the plan, each substituted tool input and each piece of evidence, so a wrong answer can be traced to the step that caused it.
- Add a test with a stub LLM that plans 3 steps and fake tools; assert exactly two model calls (one planner, one solver), and that the third tool received the first two results in place of #E1 and #E2.
Parallel evidence
Paste this into Claude Code, Cursor, ChatGPT or any AI coding assistant.
Implement the ReWOO pattern (Parallel evidence variant) in this codebase, using the LLM client and language we already use.
## Goal
Answer a question with one planner call and one solver call, running the planned tool calls in dependency waves so that independent calls overlap.
## How it works
1. Call the planner model once with the Planner prompt, passing the question and the tool descriptions, and parse the steps (variable, tool, input) as in the sequential version.
2. For each step, record the set of #E variables its input mentions; reject the plan if any refers to a later or missing step.
3. Start every step whose referenced variables all have evidence, concurrently, with each input's #E placeholders substituted.
4. As each call finishes, store its result under its variable and start any step that has just become ready; repeat until no step is waiting.
5. Call the solver model once with the Solver prompt, passing the question and the plan with all evidence filled in, and return its answer.
## Prompts
### Planner prompt
```markdown
For the question below, make a plan of tool calls that will gather
everything needed. Write the whole plan now. You will not see any
tool output before the plan is executed.
Tools:
{{tool_descriptions}}
Format, one pair per step:
Plan: a short reason for this step
#E1 = Tool[input]
A later step may use the output of an earlier one by writing its
variable (#E1, #E2, ...) inside its input.
Question: {{question}}
```
### Solver prompt
```markdown
Solve the question using only the plan and the evidence below. If the
evidence is missing or contradictory, say so instead of guessing.
Question: {{question}}
Plan and evidence:
{{plan_with_evidence}}
Give the final answer with one sentence of justification.
```
## Stop rule
Stop after the solver's single call. If a step can never start because its input depends on a failed step, mark it skipped rather than waiting forever.
## Requirements
- Cap the concurrent tool calls (default 4) and the plan length (default 8), and give each call a timeout (default 30 seconds).
- If a tool call errors, store the error text as its evidence and mark every step that depends on it as skipped, with the reason, in the evidence.
- If the plan cannot be parsed or has a dependency cycle, retry the planner once with the error appended, then stop before any tool runs.
- Record each call's start and end time, so the overlap is visible in logs.
- Add a test with a stub planner and two fake 100 ms search tools; assert both searches started before either finished and the calculator started only after both.
Prompt templates
Sequential workers · Parallel evidence
For the question below, make a plan of tool calls that will gathereverything needed. Write the whole plan now. You will not see anytool output before the plan is executed.
Tools:{{tool_descriptions}}
Format, one pair per step:Plan: a short reason for this step#E1 = Tool[input]
A later step may use the output of an earlier one by writing itsvariable (#E1, #E2, ...) inside its input.
Question: {{question}}Solve the question using only the plan and the evidence below. If theevidence is missing or contradictory, say so instead of guessing.
Question: {{question}}
Plan and evidence:{{plan_with_evidence}}
Give the final answer with one sentence of justification.Related patterns
Composes well with:
Sources
From the Agentic Atlas by Joran Kikke · Edit on GitHub · Suggest a correction