criogenai

Reasoning

Plan-and-Solve

Write a plan first, then carry out each step.

Plan-and-Solve splits the job in two. A planner writes the steps before any work starts; an executor then does one step at a time, each with the results so far; a last call writes the answer.

Planning first keeps long tasks on track and makes the work easy to review: you can read, edit or approve the plan.

Use it when
Longer tasks with several distinct parts
You want to review or approve a plan before work
Steps are known up front
Skip it when
Each step depends on surprises from the last (ReAct adapts as it goes)
Very short tasks: the plan costs a call

Run it

Scripted model · no key needed · CriogenAI engine in your browser
Ready
stepsnext stepGoalPlannerExecutorResultsWrite-upAnswer
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 + Agent nodes (or patterns.sequential)
class Plan(BaseModel):
    steps: list[str]

planner = Agent(MODEL, instructions="Write a plan of three short steps.", output=Plan)
executor = Agent(MODEL, instructions="Carry out one step of a plan. At most two sentences.")
writer = Agent(MODEL, instructions="Write the final brief from the step results.")

async def plan(state: Dict[str, Any]) -> Dict[str, Any]:
    return {"steps": (await planner.run(state["input"])).output.steps, "results": []}

async def execute(state: Dict[str, Any]) -> Any:
    done = state["results"]
    step = state["steps"][len(done)]
    out = await executor.run(f"Task: {state['input']}\nResults so far: {done}\nNow: {step}")
    results = [*done, out.text]
    # One step per pass; loop until the plan is done.
    return goto("execute" if len(results) < len(state["steps"]) else "write", {"results": results})

async def write(state: Dict[str, Any]) -> Dict[str, Any]:
    return {"output": (await writer.run(f"{state['input']}\n{state['results']}")).text}

wf = Workflow()
wf.add_node("plan", plan)
wf.add_node("execute", execute)
wf.add_node("write", write)
wf.start("plan").edge("plan", "execute").goto("execute", ["execute", "write"]).edge("write", END)
result = await wf.compile().run({"input": "Is a heat pump a good idea for a 1970s house?"}, max_steps=20)
print(result.state["output"])
const planner = new Agent<{ steps: string[] }>({
  model: MODEL,
  instructions: "Write a plan of three short steps.",
  output: { type: "object", properties: { steps: { type: "array", items: { type: "string" } } }, required: ["steps"] },
});
const executor = new Agent({ model: MODEL, instructions: "Carry out one step of a plan. At most two sentences." });
const writer = new Agent({ model: MODEL, instructions: "Write the final brief from the step results." });

const app = new Workflow()
  .node("plan", async (state) => ({ steps: (await planner.run(String(state.input))).output?.steps ?? [], results: [] }))
  .node("execute", async (state: State) => {
    const step = state.steps[state.results.length];
    const out = await executor.run(`Task: ${state.input}\nResults so far: ${state.results}\nNow: ${step}`);
    const results = [...state.results, out.text];
    // One step per pass; loop until the plan is done.
    return goto(results.length < state.steps.length ? "execute" : "write", { results });
  })
  .node("write", async (state) => ({ output: (await writer.run(`${state.input}\n${state.results}`)).text }))
  .start("plan")
  .edge("plan", "execute")
  .goto("execute", ["execute", "write"])
  .edge("write", END)
  .compile();
const result = await app.run({ input: task }, { maxSteps: 20 });
console.log(result.state.output);