criogenai

Reasoning

Tree of Thoughts

Branch into several ideas, score them, grow the best.

Tree of Thoughts treats reasoning as a search. The model proposes several different approaches, an evaluator scores each one, and only the most promising branch is developed into the answer.

It costs more calls than Chain of Thought, but it does not bet everything on the first idea.

Use it when
Creative or open problems with many possible directions
Puzzles where a first guess is often a dead end
You can say what a good branch looks like
Skip it when
One obvious approach (Chain of Thought is enough)
Tight latency or cost budgets: every branch is extra calls

Run it

Scripted model · no key needed · CriogenAI engine in your browser
Ready
bestProblemProposeIdea 1Idea 2Idea 3ScoreGrow best
The runmodel 0 · tools 0
  1. Press Run to watch the pattern work, step by step.
Try it with your own key optional: a real model makes the decisions; the tools stay simulated
  • Your key stays in this tab's memory: not saved, not in cookies or the address bar. Reload or close the tab and it is gone.
  • Your browser calls OpenAI directly. Nothing passes through criogenai.com, and nothing is logged.
  • Each run makes at most 16 short model calls, billed to your account. Tools, data and side effects are simulated.

This run is the TypeScript code below, running on the CriogenAI engine in your browser (WebAssembly). Without a key, a scripted model stands in for MODEL; with your key, your provider answers, called from this tab. The tools return made-up data.

Build it with CriogenAI

Built from primitives: Workflow: fan-out, join, route
class Score(BaseModel):
    score: int  # 1-10

proposer = Agent(MODEL, instructions="Propose one approach to the problem, with an example.")
judge = Agent(MODEL, instructions="Rate how promising the idea is, 1 to 10.", output=Score)
grower = Agent(MODEL, instructions="Develop the idea into the final answer.")

def branch(n: int) -> Callable[[Dict[str, Any]], Any]:
    async def think(state: Dict[str, Any]) -> Dict[str, Any]:
        idea = await proposer.run(f"{state['input']}\nApproach {n}: make it unlike the obvious one.")
        rated = await judge.run(f"Problem: {state['input']}\nIdea: {idea.text}")
        return {"ideas": [{"idea": idea.text, "score": rated.output.score}]}

    return think

async def grow(state: Dict[str, Any]) -> Dict[str, Any]:
    best = max(state["ideas"], key=lambda i: i["score"])  # prune the rest
    return {"output": (await grower.run(f"{state['input']}\nIdea: {best['idea']}")).text}

wf = Workflow(reducers={"ideas": "append"})
wf.add_node("begin", lambda state: None)
names = [f"branch{n}" for n in (1, 2, 3)]
for n, name in enumerate(names, 1):
    wf.add_node(name, branch(n))
    wf.edge("begin", name)  # the three branches run at the same time
wf.add_node("grow", grow)
wf.join(names, "grow").edge("grow", END).start("begin")
result = await wf.compile().run({"input": "Name a coffee shop for software developers."})
print(result.state["output"])
const proposer = new Agent({ model: MODEL, instructions: "Propose one approach to the problem, with an example." });
const judge = new Agent<{ score: number }>({
  model: MODEL,
  instructions: "Rate how promising the idea is, 1 to 10.",
  output: { type: "object", properties: { score: { type: "integer", minimum: 1, maximum: 10 } }, required: ["score"] },
});
const grower = new Agent({ model: MODEL, instructions: "Develop the idea into the final answer." });

const branch = (n: number) => async (state: State) => {
  const idea = await proposer.run(`${state.input}\nApproach ${n}: make it unlike the obvious one.`);
  const rated = await judge.run(`Problem: ${state.input}\nIdea: ${idea.text}`);
  return { ideas: [{ idea: idea.text, score: rated.output?.score ?? 0 }] };
};

const names = ["branch1", "branch2", "branch3"];
const wf = new Workflow({ reducers: { ideas: "append" } }).node("begin", () => undefined).start("begin");
names.forEach((name, i) => wf.node(name, branch(i + 1)).edge("begin", name)); // the branches run at once
wf.node("grow", async (state) => {
  const best = (state.ideas as { idea: string; score: number }[]).sort((a, b) => b.score - a.score)[0]; // prune the rest
  return { output: (await grower.run(`${state.input}\nIdea: ${best.idea}`)).text };
});
wf.join(names, "grow").edge("grow", END);
const result = await wf.compile().run({ input: task });
console.log(result.state.output);