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 browserThe run
- 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);