When you ask an AI model a hard question, it answers the way it was built to: one word at a time, in a single unbroken stream. Researchers call this autoregressive generation, and the "let me think step by step" text you sometimes see is called a chain of thought. It looks like reasoning, and often it works. But notice what the model can't do in that stream: it can't lay two ideas side by side. It can't put an idea down, try another, and come back. And it has no scratchpad other than its own words — so when a puzzle needs it to track a changing situation precisely, the words drift, and the model starts believing things about the situation that are no longer true. Once that happens, more thinking doesn't help. It just produces a longer, more confident version of being lost.
ReasonTree is a small open-source controller built around a different picture. Instead of one long monologue, the problem becomes a tree: the current situation is the trunk, each candidate idea is a branch, and every branch is played out on a real copy of the situation — in software terms, a state that actually updates, not a description of one. For each branch, something pushes back: an opponent's best counter-move, a failing test, a counter-example. Branches get scores, weak ones are pruned, and a strict budget of time and compute (bounded search) decides when to stop. Wherever a claim can be checked mechanically, a verifier — real executed code, not another opinion — gets the final word. Only then does the language model speak: one short call to explain the branch that survived.
Below are four real, captured experiments — a chess puzzle, a probability question, a debugging session, and a business decision. Each one exercises a different part of the tree, so along the way you'll see which specific feature earns its keep: executable states, verifiers, scoring, or the adversarial pushback. At the end, we place ReasonTree honestly among its research ancestors — Tree of Thoughts, Monte Carlo Tree Search, and friends — including a small head-to-head we ran for this page.
First, what is this task? A chess tactics puzzle is a position from a real game where exactly one move wins decisively — every alternative lets the opponent escape. Puzzle sites rate them by how often humans solve them; this one is rated 1809, roughly "strong club player" territory. There is nothing to debate and nothing to interpret: a move either works against the opponent's best defense or it doesn't, which is exactly why we use chess as the microscope. Nobody can argue with the scoreboard.
Now think about what answering this requires from a model that can only write words. To evaluate one candidate move it must imagine the move, imagine the opponent's best answer, imagine its own follow-up — while keeping all thirty-two pieces straight, in prose, across every line it explores. Each imagined move changes the position; each new candidate means rewinding to the original position from memory. The captured stream in the first panel shows what that does in practice. Haiku starts out impressively organized — it reads the position correctly and lists ideas. Then the drift begins: it circles back to the same candidate a third time, "double-checks" the board and misremembers it ("wait — the king can't be on g7 if there's a pawn there" — it could, there wasn't), and at 127 seconds it commits, politely and confidently, to a move that is not merely wrong but illegal — its own knight is standing on the path. No time limit was in play; we let it run as long as it wanted.
The second panel is the same model inside ReasonTree, and the difference is not effort — it's plumbing. The controller never remembers the board; it computes it. Every legal move is enumerated by code, each one is played on a real copy of the position, and for each, the opponent answers with its best move — what game programmers call an adversarial search (four levels deep here; the classic negamax algorithm, for the technically curious). Positions are scored by checkmate and material, a 12-second budget caps the work, and the winning branch — Qxd5, a queen sacrifice — surfaces in about four seconds. Click any branch below: the counter-moves it had to survive are all there.
On the full frozen 25-puzzle benchmark this is not a one-off: raw Haiku solved 1 of 25 under a 30-second operational cap; the tree solved 21 of 25. And the pattern survives a model tier. We repeated the entire protocol with Claude Sonnet 5 — a far stronger model — on a new frozen holdout of harder puzzles (rated 2200–2300, master-level) with an eight-times-longer budget: raw Sonnet solved 3 of 25 in a median of 57 seconds; the unchanged adapter solved 18 of 25 in a median of three, and the first ten rescue cases ran end-to-end with Sonnet as the explanation layer at 10/10, about $0.008 per case. One more honest wrinkle from that run: searching deeper (depth 5 and 6) scored worse than the frozen depth-4 config — a classic horizon effect — a reminder that bounded and even beats big and truncated. The lesson travels beyond chess: whenever a problem has precise rules and a changing state — a spreadsheet, a database, a codebase, a schedule — "what happens if" can be computed instead of imagined.
Let me analyze this chess position. I need to find the single best move for White. FEN: 2r2rk1/4q1p1/p3p2p/1p1b4/P7/1QN1RP2/1P3P1P/2R3K1 w - - 0 23 Let me understand the board: ``` 8: . . r . . r k . (rank 8) 7: . . . . q . p . (rank 7) 6: p . . . p . . p (rank 6) 5: . p . b . . . . (rank 5) 4: P . . . . . . . ( …
Hmm, so Ne4 doesn't seem to trap the queen or win material immediately. Let me think about whether Ne4 improves White's position in some other way. After 1. Ne4, the knight is centralized and attacks the queen. The queen moves, and then what? I'm not sure this leads anywhere concrete. Let me go ba …
Let me go back to considering Rxc8+. That seems like the most forcing move. After 1. Rxc8+ Qxc8, White has traded rooks. The position is roughly equal in material. But I should evaluate the resulting position more carefully. Is White better, worse, or equal? …
But wait—the king can't be on g7 if there's a pawn there. Let me recheck the pawn structure from the position. Looking at rank 7: e7 has the queen, g7 has a pawn. So the king must move elsewhere after the rook check. The available squares are Kf7, Kh7, or Kh8. In each case, White follows with Rc7, …
Let me examine whether there's a stronger initial move I've overlooked. The position warrants a closer look at other candidate moves before committing to the rook capture. What about Qxd5+? The queen takes the bishop with check, which forces the king to respond and wins material …
So the move is c1c8 in UCI notation. Let me verify the board position once more to make sure I have the right setup before finalizing this answer. Looking at the full board: the black rook sits on c8 and black king on g8. The white rook is actually on e3, not c1 as I initially thought. Checking rank 1, there's a rook on c1 and the white …
FEN: 2r2rk1/4q1p1/p3p2p/1p1b4/P7/1QN1RP2/1P3P1P/2R3K1 w - - 0 23
No chessboard here — this is the kind of question that lands in a Slack channel. A company's mail system sees about 1 phishing message per 100. It runs two phishing scanners. Each scanner, measured on its own, catches 90% of phishing emails and false-alarms on 5% of legitimate ones. This morning, both scanners flagged the same message, and the security lead asks the natural question: "Okay — what's the probability this one is actually phishing?" To be precise about what's being asked: of all the messages that ever get double-flagged, what fraction are truly phishing? Statisticians call this the posterior probability; everyone else calls it "how sure are we."
There is a textbook way to compute it, and it's genuinely tempting. Phishing is rare (1 in 100), so even a good scanner cries wolf a lot — that's the famous base-rate trap. But two independent alarms fix that: the odds that two unrelated scanners both false-alarm on the same innocent email are tiny (5% of 5%). Run the arithmetic — Bayes' theorem — and out comes a satisfying 76.6%. One catch. That word independent. These two scanners come from the same vendor and share code and training data. They are two witnesses who went to the same school and read the same books: when one is fooled, the other tends to be fooled by the very same trick. How much does their agreement really add, then? Here is the uncomfortable truth: the numbers given do not say. Nobody has measured how often the two scanners fail together, and no amount of cleverness can conjure that missing measurement out of thin air.
Watch what the raw model does with this. Midway through its thinking, it spots the trap — genuinely, in its own words:
Without knowing the correlation between the scanners, I can't give a precise answer. The 76.6% figure assumes independence, which is likely too optimistic given they share code and training data. The true probability probably falls between 15.4% (perfect correlation) and 76.6%, closer to the lower end. I should acknowledge this …
77% Justification: Using Bayes' theorem: P(phishing | both flag) = (0.9² × 0.01) / (0.9² × 0.01 + 0.05² × 0.99) = 0.0081 / 0.010575 ≈ 77%. Critical limitation: This assumes the scanner errors are independent. Since both scanners share code and training data, their errors are positively correlated—if one makes a false positive, the other likely will too. This correlation means the true probability is lower than 77%. Without m …
The question demanded one number, so it delivered one: 77% — the textbook figure that silently assumes the two scanners fail independently, the very assumption it had just doubted. It even guessed a direction ("the true probability is lower"), which the facts don't support either. Cost of the confident answer: 47.43s, 4407 tokens, $0.0264. This is the single-stream weakness in its purest form: noticing a flaw is possible, but nothing in the stream forces the flaw to change the answer.
ReasonTree's structure changes who is allowed to have the last word. "Assume independence and multiply" isn't the method here — it's just one branch, sitting next to a rival branch that asks: what do the stated facts actually pin down? That second branch goes to a verifier — a small piece of exact mathematics (bounds under unknown dependence, for the technical reader) that computes every probability consistent with the given facts. The answer it returns is not a number. It's a range, and the range is enormous:
Both ends of that range are real possibilities, and each has a plain-English story. The bottom (13.9%): if the scanners' mistakes overlap almost completely, the second flag adds nearly nothing — you effectively have one scanner wearing two badges, and one flag on a rare event mostly means "false alarm." The top (100%): if their false alarms happen never to coincide, then a double flag is practically proof. Between those extremes, any value fits the facts. So the only honest answer to "give me the exact probability" is: underdetermined — you cannot know from this data, and here is precisely the measurement that would settle it (how often do both scanners flag the same legitimate email?). ReasonTree calls this the gap rule: when two fact-compatible worlds disagree, name the gap instead of picking a world. That refusal is a feature. A wrong-but-confident 77% could justify auto-deleting customer email; "between 14% and 100%, and here's what to measure" leads somewhere useful.
- Status: Underdetermined. - Verified range: 13.9% to 100%. - Independence scenario: 76.6%, explicitly labeled unproven. - Missing measurement: joint error rates between the two scanners.
Three times faster than the raw attempt, and — more importantly — it refuses the false precision and names the fact that would close the question. The same trap, by the way, is everywhere once you see it: two medical tests processed by the same lab, two references who heard the story from the same person, two AI models trained on the same data, two auditors using the same checklist. Agreement feels like confirmation; without independence, it's often just an echo.
A Python service ships a small feature: every user can set their own request timeout. One day a customer sets theirs to 60 seconds — and suddenly every user's timeout is 60. Settings are leaking across users who have never touched them. Here's the entire relevant code:
Two things in this snippet deserve a plain-language introduction. @functools.lru_cache()
is Python's "remember the answer" sticker: the first time get_config("prod") runs, the result
is stored; every later call skips the work and returns the stored result. Useful — but note the subtlety:
it remembers the object itself, not a photocopy. Every caller receives the same
dictionary. The second thing is overrides={} — a mutable default
argument, one of Python's most famous gotchas, the thing every code reviewer has been trained to
pounce on the moment they see it. It looks guilty. That's precisely what makes this case
interesting: there's a well-known suspect standing right next to the actual culprit.
Credit where due: asked raw, Haiku correctly blamed the cache this time (19.64s, 1758 tokens, $0.0133). But look at what that answer is: a plausible story about code it never ran. You'd still have to verify it yourself before shipping the fix — and if it had picked the decoy instead, the answer would have read exactly as confident.
ReasonTree treats a debugging session as hypothesis testing. Each suspect becomes a branch, and the
verifier executes the actual program. Branch one — "the cache hands out one
shared dict" — is confirmed by reproduction: run the code, watch user 2 inherit user 1's timeout, observe
that get_config("prod") really does return the identical object twice. Branch two — the
famous decoy — is cleared by direct observation: after the failure, the default dict is still empty; it
was never touched. Then the fix branch: apply copy-on-return, re-run the same scenario, watch the symptom
disappear. The fix isn't recommended; it's demonstrated. All of the code execution took
under a millisecond; one short model call writes it up. Total:
7.32s and $0.007 — roughly half
the time and cost of the raw attempt, with proof attached instead of plausibility.
The pattern generalizes to most "how is this even possible?" bugs: settings that leak between users, tests that pass alone and fail together, caches that serve stale data, "works on my machine." Wherever a hypothesis can be turned into a few lines of executable check, the tree turns detective stories into experiments.
Root cause (verified): `functools.lru_cache` returns the same mutable dict object across calls, and `apply_user_settings` mutates it in place, causing user2 to see user1's timeout value. Why Branch B is refuted: The mutable default argument `overrides={}` was never mutated, as directly observed in the execution evidence. Minimal fix: Return a copy of the cached dict from the cached function so each caller gets an independent mutable object: `return dict(get_settings())` or `return copy.copy(cached_result)`.
Our last case has no verifier at all — no chess engine, no formula, no test suite can tell you the right answer. That's deliberate: most real decisions live here, and it's important to see what a reasoning tree can and cannot honestly do in this territory.
The setup: you advise a six-person B2B software startup with 40 customers. A bug is corrupting non-English characters (ç, ö, 漢字…) in the data-export feature; two customers are affected. Option A: a hotfix can ship tomorrow — but deploying it means disabling every customer's data export for up to 24 hours, starting tomorrow morning. Option B: wait for next week's scheduled maintenance window and fix it with zero downtime. Sounds like a judgment call between speed and disruption — until you read the account notes: one of the two affected customers is mid contract-renewal, worth 30% of the company's revenue, and their procurement team runs a data-export compliance test tomorrow afternoon as part of the renewal checklist. Now look again. Option A knocks out the very feature that customer will be testing, during the very hours they'll be testing it:
To raw Haiku's credit, this time the single stream caught it — its very first step was to call the customer and move the test out of the deployment window:
Call the renewal customer today — Inform them directly of the bug, tomorrow's maintenance window, and estimated restoration time (underpromise). Ask if they can run their compliance test before 7am or after the estimated restore time, and offer to have an engineer standing by during their test. This removes ambiguity and gives them ownership of the solution path. 2. Test the hotfix tonight end-to-end — Validate the fix …
A genuinely good answer. But hold it next to Case 2 for a moment: the same model, on the same day, noticed the independence trap and still answered "77%." A single stream may catch the buried fact. Nothing makes it. Whether the collision surfaces depends on where the stream happens to wander — and you only get one stream.
The tree makes the catch structural instead of lucky. Two advocate branches each argue one option as hard as they can — and are required to list the biggest risks of their own plan against every stated fact. Then a skeptic pass cross-examines both branches, specifically hunting for facts that break them. In the captured run it found both of the things that matter. Against Option B, the fatal one:
If the test is tomorrow afternoon and the fix isn't deployed until next week, the customer will encounter the bug during their renewal compliance test. This is not a negotiable reschedule—it's a compliance checklist for a renewal decision. The bug discovery at that moment guarantees escalation and exactly the "forced into Option A under duress" scenario Branch B warns against. Waiting doesn't avoid the crisis; it defers it to the worst possible time. …
And against Option A — subtler and easy to miss — the skeptic caught the plan contradicting its own numbers:
A deployment that starts "tomorrow morning" and runs "up to 24 hours" does not have an afternoon window available for the test. The 4–6 hour estimate contradicts the stated "up to 24 hours" requirement. Branch A cannot have it both ways—either deployment finishes by afternoon (contradicting the stated scope), or export is still down during the test. …
The final recommendation (153.43s, $0.0928): hotfix tomorrow, but only sequenced around the test — call the customer first, verify the test can move, stage the deploy accordingly. Crucially, the answer ships with a table of its own assumptions ("the test is movable on 12-hour notice") and unverifiable facts, each labeled. Because no verifier exists for decisions, ReasonTree doesn't pretend one does: the output is marked unverified — an honest judgment, stress-tested, with its load-bearing assumptions in plain view. That's the most a reasoning system can truthfully offer here, and it costs about 6× the raw call — worth it when 30% of revenue rides on a scheduling detail, overkill for picking lunch.
The shape to remember: any decision where dated facts can collide. A kitchen renovation scheduled just before a family event; switching payroll vendors the month of a tax deadline; accepting a job offer whose start date quietly overlaps a signed obligation. One stream may notice. A tree with a skeptic pass must check.
If the model already verifies its work, the tree mostly adds cost. In our matched-compute experiments on math benchmarks (AIME) with tools enabled, one-shot agents wrote their own checking code and nearly saturated the test — extra tree structure gained nothing. We publish that result alongside the wins.
"Think in branches" as a mere prompt does nothing. We tested it: telling the model to build a tree in words, even with all legal moves listed, still failed the chess puzzles. The gain appears only when branches become executable — real states, real checks. Structure has to be in the machinery, not the phrasing.
Judgment calls get scrutiny, not proofs. Case 4 shows the ceiling: without a verifier, the tree can force hidden facts into view and label assumptions, but it cannot certify the decision — and says so.
None of the individual ideas here are new, and it matters to say so plainly. Researchers have been giving language models more structure for years, and ReasonTree borrows from most of them:
Ask the model to think out loud before answering. The baseline everything else builds on.
Shared: nothing structural — this is the single stream all four cases start from.
Ask the same question many times, take the majority answer. Wisdom of a crowd of one model.
Difference: votes measure agreement, not correctness — correlated errors win votes too (see Case 2).
Branch into multiple partial "thoughts," have the model rate its own thoughts, search over the best ones.
Shared: branching, scoring, pruning. Difference: in ToT the model grades its own homework; in ReasonTree an executed check outranks any model opinion.
Generalize the tree to a graph: branches can merge, loop, and refine each other.
Difference: richer topology, same self-evaluation. ReasonTree keeps the plain tree and spends the complexity budget on verification instead.
The statistics-guided game search behind AlphaGo: simulate, score, expand the promising branches.
Shared: adversarial state-action search. Difference: our own experiments found visit-count MCTS cost 3–6× more with no quality gain at this scale — a small bounded search was enough.
Let the model criticize its own answer and try again, possibly across attempts.
Shared: the skeptic pass of Case 4 is kin. Difference: where a real check exists, ReasonTree replaces self-critique with execution.
So what is actually different? One design rule, applied stubbornly: the model never gets the last word on anything a machine can check. There's a reason for that rule. A well-known study — Huang et al., "Large Language Models Cannot Self-Correct Reasoning Yet" (arXiv 2310.01798) — found that when models review their own reasoning without external feedback, they fix wrong answers about as often as they break right ones. Every method above that relies on the model evaluating its own thoughts inherits that ceiling. ReasonTree's bet is to route around it: executable states and verifiers wherever the domain allows (Cases 1–3), and where nothing can be executed (Case 4), honest labels instead of borrowed confidence — plus two habits that are rarer than they should be: a hard compute budget on every search, and the "underdetermined" output when facts genuinely don't pin down an answer.
We didn't just assert the difference — we ran a small version of the comparison. We built a one-level Tree-of-Thoughts-style harness (three independent proposals, then one evaluate-and-vote call; our own emulation, not the original authors' code) and pointed it at the same tasks, same model, no tools:
| Approach | Chess rescue puzzles (2) | The two-alarms trap | Typical cost/case |
|---|---|---|---|
| Raw Haiku — one stream | 0/2 — one illegal move, one wrong | committed to "77%" after doubting it | $0.01–0.07 · up to minutes |
| "Think in branches" prompt | 0/2 — both timed out at 90s | — | — |
| ToT-style, propose×3 + vote | 1/2 — voted for a refuted move on the other | named the right conclusion, then answered "15.4%" anyway | $0.2232 · 263s |
| ReasonTree — tree + verifier | 2/2 — in seconds, branches inspectable | verified range 13.9–100% + the missing measurement | ~$0.014 · 5–21s |
Proposal 2's insight is important—the true answer depends on unknown correlation—but that argues for a range or a recommendation to measure, not a specific guess. FINAL ANSWER: 15.4%
This is the most instructive failure on the page. Branching did surface the uncertainty — one proposal argued for a range. The vote even agreed with it in words. Then it picked a number anyway, because nothing structural stopped it. Branches without a verifier are opinions with better formatting.
Fairness requires the caveats: this is a tiny probe — two puzzles and one trap question, one model, our own ToT emulation rather than the official implementation, single runs. A proper head-to-head against the published Tree-of-Thoughts and Graph-of-Thoughts codebases, across many tasks and seeds, has not been done — by us or, to our knowledge, by anyone, for the verifier-gated setup. It's the obvious next experiment, and the repository is set up to run it. Until then, the claim we're comfortable making is narrow and matches everything above: structured branching helps a model surface doubts; only an executed check reliably converts doubts into a different answer.
Everything here is reproducible: the frozen puzzle set, the captured thought streams, the verifier code, the comparison harness, and the renderer that generated this very page are all in the open-source repository — github.com/uolkan/reason-tree.