IBM agent types
Model-based reflex agent
Rules plus an internal picture of what it cannot see.
A model-based reflex agent still acts on rules, but it keeps an internal model of the world, updated from what it senses and what its own actions do. That lets it act sensibly when it can only see part of the world.
This robot vacuum only senses the room it is in. Its memory of which rooms are clean is what lets it stop; a simple reflex vacuum would never know it was done.
- Use it when
- The world is only partly observable
- State changes slowly and predictably
- Rules still describe what to do
- Skip it when
- Choices between competing goals (goal- or utility-based)
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 state (the internal model) + routerooms = ["A", "B", "C", "D"]
def step(state: Dict[str, Any]) -> Any:
# The internal model: rooms known to be clean, kept in the run state.
known = set(state["known"])
here = state["at"]
if state["dirty"].get(here):
return goto("step", {"dirty": {**state["dirty"], here: False}, "known": [*known, here]})
known.add(here)
if known == set(rooms):
return goto("done", {"known": sorted(known)})
nearest = next(r for r in rooms if r not in known)
return goto("step", {"at": nearest, "known": sorted(known)})
wf = Workflow()
wf.add_node("step", step)
wf.add_node("done", lambda state: {"output": "all rooms clean"})
wf.start("step").goto("step", ["step", "done"]).edge("done", END)
world = {"at": "A", "known": [], "dirty": {"A": True, "B": False, "C": True, "D": True}}
print((await wf.compile().run(world, max_steps=40)).state["output"])const rooms = ["A", "B", "C", "D"];
const app = new Workflow()
.node("step", (state: State) => {
// The internal model: rooms known to be clean, kept in the run state.
const known = new Set<string>(state.known);
const here: string = state.at;
if (state.dirty[here]) return goto("step", { dirty: { ...state.dirty, [here]: false }, known: [...known, here] });
known.add(here);
if (rooms.every((r) => known.has(r))) return goto("done", { known: [...known] });
return goto("step", { at: rooms.find((r) => !known.has(r)), known: [...known] });
})
.node("done", () => ({ output: "all rooms clean" }))
.start("step")
.goto("step", ["step", "done"])
.edge("done", END)
.compile();
const world = { at: "A", known: [], dirty: { A: true, B: false, C: true, D: true } };
const result = await app.run(world, { maxSteps: 40 });
console.log(result.state.output);