Implementing a classical agent
Up to this point, we have looked at the individual pieces of a classical agent: state, decision logic, tools, and workflows. This lesson exists to show how those pieces come together into a single, running program. The goal is to move from isolated concepts to a complete agent that behaves consistently over time.
Combining state, decisions, tools, and workflows
A classical agent is not defined by any single component. It emerges from how state, decision logic, tools, and workflows interact. State captures what the agent knows, decision logic interprets that state, tools perform actions, and workflows give structure to how actions unfold.
In practice, these pieces are usually defined separately and then wired together in the main program. This separation keeps the agent understandable while still allowing it to act as a cohesive whole.
state = {
"pages_generated": 0,
"max_pages": 3
}
def decide_next_action(state):
if state["pages_generated"] < state["max_pages"]:
return "generate_page"
return "stop"
Structuring the main agent loop
The main agent loop is where everything meets. Each iteration follows a predictable pattern: read the current state, decide what to do, perform an action, then update state. The loop itself does not need to know the details of each tool or workflow step.
This structure makes the agent easy to reason about because control always flows through the same place.
while True:
action = decide_next_action(state)
if action == "generate_page":
generate_page(state)
elif action == "stop":
break
Running the loop repeatedly over time
A classical agent gains its character by running the loop repeatedly. Each pass through the loop represents a single decision–action cycle. Over time, small state changes accumulate and produce visible progress.
The loop continues until the decision logic determines that there is nothing left to do, or until an explicit stop condition is reached.
def generate_page(state):
filename = f"page_{state['pages_generated']}.html"
with open(filename, "w") as f:
f.write("<html><body>Planet page</body></html>")
state["pages_generated"] += 1
Producing observable behavior each iteration
An agent should produce some observable effect on each iteration. This might be writing a file, printing output, or updating persistent state. Observable behavior makes the agent’s progress concrete and allows us to confirm that the loop is doing useful work.
In this example, each iteration produces a new HTML file, which makes the agent’s activity easy to verify.
python agent.py
Maintaining correctness across iterations
Correctness in a classical agent comes from careful state updates. Each iteration must leave state in a valid, consistent form so that the next decision is based on accurate information. The agent loop assumes that state reflects reality.
By keeping state updates explicit and localized, the agent remains predictable even as it runs for many iterations.
Conclusion
We now have a complete picture of a classical agent running as a single program. State, decisions, tools, and workflows are combined inside a clear, repeatable loop that produces observable behavior over time. With this structure in place, we are oriented to build and reason about deterministic agents as complete systems.