criogenai

IBM agent types

Goal-based agent

Searches for actions that reach a goal, and replans.

A goal-based agent knows what it wants to reach and looks ahead: it searches for a sequence of actions that gets there, then follows it. When the world changes it plans again instead of following a stale rule.

This delivery drone finds the shortest route to the clinic; a road closes on the way and it replans. With a language model, the planner step is often the model itself.

Use it when
A clear goal with many ways to reach it
The world changes and plans must adapt
Navigation, scheduling, task planning
Skip it when
Several goals that trade off (utility-based)
Search spaces too big to plan in time

Run it

No model needed · CriogenAI engine in your browser
Ready
next hopnew positiongoal reachedGoal: ClinicSensePlan (search)FlyArrived
The run
  1. Press Run to watch the pattern work, step by step.

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 loop: plan → act → check (goto)
roads = {"Depot": ["Market", "Mill"], "Market": ["Park", "Bridge"], "Mill": ["Bridge"], "Bridge": ["Clinic"], "Park": ["Clinic"]}

def plan(here: str, goal: str, closed: list) -> list:
    paths = [[here]]
    while paths:  # breadth-first search: the shortest route first
        path = paths.pop(0)
        if path[-1] == goal:
            return path
        paths += [[*path, n] for n in roads.get(path[-1], []) if n not in path and [path[-1], n] not in closed]
    return []

def fly(state: Dict[str, Any]) -> Any:
    route = plan(state["at"], state["goal"], state["closed"])  # replans every hop
    if len(route) < 2:
        return goto("arrived", {})
    return goto("fly", {"at": route[1], "log": [*state["log"], route[1]]})

wf = Workflow()
wf.add_node("fly", fly)
wf.add_node("arrived", lambda state: {"output": " → ".join(state["log"])})
wf.start("fly").goto("fly", ["fly", "arrived"]).edge("arrived", END)
start = {"at": "Depot", "goal": "Clinic", "closed": [["Market", "Bridge"]], "log": ["Depot"]}
print((await wf.compile().run(start, max_steps=20)).state["output"])
const roads: Record<string, string[]> = { Depot: ["Market", "Mill"], Market: ["Park", "Bridge"], Mill: ["Bridge"], Bridge: ["Clinic"], Park: ["Clinic"] };

const plan = (here: string, goal: string, closed: string[]): string[] => {
  const paths = [[here]];
  while (paths.length) {
    // breadth-first search: the shortest route first
    const path = paths.shift()!;
    const last = path[path.length - 1];
    if (last === goal) return path;
    for (const n of roads[last] ?? []) if (!path.includes(n) && !closed.includes(`${last}-${n}`)) paths.push([...path, n]);
  }
  return [];
};

const app = new Workflow()
  .node("fly", (state: State) => {
    const route = plan(state.at, state.goal, state.closed); // replans every hop
    return route.length < 2 ? goto("arrived") : goto("fly", { at: route[1], log: [...state.log, route[1]] });
  })
  .node("arrived", (state) => ({ output: (state.log as string[]).join(" → ") }))
  .start("fly")
  .goto("fly", ["fly", "arrived"])
  .edge("arrived", END)
  .compile();
const start = { at: "Depot", goal: "Clinic", closed: ["Market-Bridge"], log: ["Depot"] };
const result = await app.run(start, { maxSteps: 20 });
console.log(result.state.output);