Perceive → think → act → observe — the humble cycle every agent, simple or complex, is built on.
The engine
One loop, turning until the task is done.
No matter how fancy the agent, underneath it's a cycle that keeps spinning: perceive → think → act → observe, over and over.
The four steps
Perceive, think, act, observe.
Perceive
Take in input — your instruction, a tool's result, or an error. Whatever just landed in context.
Think
The LLM reads everything in context and reasons out the smartest next move.
Act
Call a tool… or decide it's done and answer. One decision, one action.
Observe
Read the result of that action, update its understanding — then loop back to Think.
It keeps looping until the task is done, it hits a max number of steps, or something breaks.
The pattern
ReAct: think out loud before every move.
ReAct = reasoning + acting. Before every action, the agent explicitly writes down its thinking — like forcing yourself to explain your reasoning before you touch anything.
No impulse
Stops random, impulsive tool calls before they happen.
Paper trail
Leaves a written record of the logic behind each step.
Easy to debug
When it fails, you can see exactly where the reasoning went wrong.
A worked trace
Should I bring an umbrella in Tokyo?
Thought — I don't know live weather. I'll use the weather tool for Tokyo.
Action — get_weather("Tokyo")
Observation — 18°C, light rain, humidity 82%
Thought — It's raining, so the user should take an umbrella.
Final Answer — It's 18°C with light rain in Tokyo. Yes — bring an umbrella. ☔
tools = {"get_weather": get_weather, "web_search": web_search}
messages = [{"role": "user", "content": goal}] # PERCEIVE
for step in range(MAX_STEPS): # safety belt
reply = llm(messages, tools=tools) # THINK — model reasons
if reply.tool_call: # ACT — it wants a tool
fn = tools[reply.tool_call.name]
out = fn(**reply.tool_call.args)
messages.append(reply)
messages.append({"role": "tool", "content": out}) # OBSERVE
continue # loop back and think again
print(reply.text) # no tool call → FINAL ANSWER
break
MAX_STEPS is your safety belt — without it, one bug becomes thousands of API calls.
Chapter 4 in one breath
Think, act, observe — repeat.
An agent perceives input, thinks about the next move, acts by calling a tool, observes the result, and loops — with ReAct making it reason before each step. It's a dozen lines of code.
Everything else we build just hangs off this loop — starting with the tools it can call.
Next up
Chapter 5 · Tools.
We've got the loop turning. Now we give the agent things to actually do inside it — the tools it reaches for on every Act step.