Prompt Engineering Codex · CH 22

Chapter 22: Tree of Thoughts and Advanced Reasoning Techniques

⏱️ 4 min read·Updated Jul 2026

The Limits of Linear Reasoning

Chain-of-thought prompting asks the model to reason in a straight line: step 1, step 2, step 3, conclusion. For most problems, this is sufficient.

But some problems do not have a single correct reasoning path. They require exploring multiple approaches, backing up when an approach fails, and selecting the best path from several tried. Linear reasoning cannot do this — it commits to a path and follows it to completion, even if a better path exists.

The techniques in this chapter address this limitation.

---

Tree of Thoughts (ToT)

Tree of Thoughts extends chain-of-thought from a linear path to a branching tree. Instead of generating one reasoning path, the model generates multiple candidate reasoning steps at each decision point, evaluates them, and selects the most promising ones to continue.

ToT Architecture

code
Problem
├── Approach A
│   ├── Step A1 -> [EVALUATE: good, continue]
│   │   ├── Step A1a -> [EVALUATE: dead end, backtrack]
│   │   └── Step A1b -> [EVALUATE: promising, continue]
│   │       └── Solution
│   └── Step A2 -> [EVALUATE: mediocre, deprioritize]
└── Approach B
    └── Step B1 -> [EVALUATE: poor, abandon]

Implementing ToT via Prompting

javascript
async function treeOfThoughts(problem, nThoughts = 3, depth = 3) {
  let currentLayer = [{ path: [], state: problem }];
  
  for (let d = 0; d < depth; d++) {
    const nextLayer = [];
    
    for (const node of currentLayer) {
      const thoughts = await generateThoughts(problem, node.path, nThoughts);
      const evaluated = await evaluateThoughts(problem, node.path, thoughts);
      const topThoughts = evaluated
        .sort((a, b) => b.score - a.score)
        .slice(0, 2);
      
      for (const thought of topThoughts) {
        nextLayer.push({ 
          path: [...node.path, thought.thought],
          score: thought.score,
        });
      }
    }
    
    currentLayer = nextLayer;
    const solutions = currentLayer.filter(n => n.score > 0.9);
    if (solutions.length > 0) break;
  }
  
  return currentLayer.sort((a, b) => b.score - a.score)[0];
}

When to use ToT:

  • Complex planning problems with multiple valid approaches

  • Creative problems where exploring diverse paths is valuable
  • Problems where the correct approach is not obvious in advance
  • Mathematical or logical puzzles with multiple solution paths
Cost: ToT uses significantly more tokens than CoT (N x depth calls vs. 1 call). Reserve it for problems where quality matters more than cost.

---

ReAct (Reasoning + Acting)

ReAct interleaves reasoning and tool use, allowing the model to adjust its reasoning based on what it observes from tool outputs.

code
Thought: I need to find the current price of Apple stock to calculate the portfolio value.
Act: search_web("AAPL current stock price")
Observation: AAPL is currently trading at $218.50

Thought: Now I have the stock price. The user holds 100 shares, so the position value is 100 x $218.50 = $21,850.
Act: calculate("100 * 218.50")
Observation: Result: 21850

Thought: I have all the information needed. I can now answer the question.
Answer: Your Apple stock position is currently worth $21,850 (100 shares x $218.50/share).

The ReAct prompt structure:

code
Solve this task by alternating between Thought and Action/Observation steps.

Format:
Thought: [your reasoning about what to do next]
Action: [tool_name(parameters)]
Observation: [the result of the action - provided by the system]
... (repeat as needed)
Answer: [final answer after sufficient information gathered]

Task: {{task}}

---

Reflexion (Self-Critique and Retry)

Reflexion adds a self-critique step: after the model produces an answer, it evaluates its own answer and retries if it finds flaws.

javascript
async function reflexionSolve(problem, maxAttempts = 3) {
  let attempt = 1;
  let previousAttempts = [];
  
  while (attempt <= maxAttempts) {
    const solution = await client.chat.completions.create({
      messages: [{
        role: 'user',
        content: 'Problem: ' + problem + '\n\n' + 
          (previousAttempts.length > 0 ? 'Previous attempts that failed:\n' + 
            previousAttempts.map((a, i) => 'Attempt ' + (i+1) + ': ' + a.solution + '\nWhy it failed: ' + a.critique).join('\n\n') + '\n\nLearn from previous failures.\n\n' : '') +
          'Generate a solution.'
      }]
    });
    
    const solutionText = solution.choices[0].message.content;
    
    const critique = await client.chat.completions.create({
      messages: [{
        role: 'user',
        content: 'Problem: ' + problem + '\n\nProposed solution:\n' + solutionText + '\n\nCritically evaluate this solution. Is it correct? Are there edge cases it misses?\n\nOutput JSON: { "is_correct": boolean, "critique": string, "confidence": number }'
      }],
      response_format: { type: 'json_object' },
    });
    
    const { is_correct, critique: critiqueText, confidence } = JSON.parse(critique.choices[0].message.content);
    
    if (is_correct && confidence > 0.85) {
      return { solution: solutionText, attempts: attempt, confidence };
    }
    
    previousAttempts.push({ solution: solutionText, critique: critiqueText });
    attempt++;
  }
  
  return { solution: previousAttempts[0].solution, attempts: maxAttempts, confidence: 'low', caveat: 'Maximum retries reached' };
}

---

Choosing the Right Technique

Problem TypeBest TechniqueWhy
Single-step reasoningChain-of-ThoughtFast, cheap, reliable
Multi-path problemsTree of ThoughtsExplores alternatives
Tool-using tasksReActAdjusts based on real observations
High-stakes single answerReflexionSelf-corrects before committing
High-stakes with uncertaintyToT + Self-ConsistencyMaximum reliability

Finished reading this chapter?

Mark it completed to update your AI Builder skill profile score on your dashboard.

📋

Download Printable Chapter Checklist

Get a print-friendly, formatted checklist of workspace actions to apply this chapter offline.