This is the full implementation of the example from Build Your First AI Agent.
If you have not read it yet, start there. Here we focus on the code.
What this example demonstrates
- Agent goal: get a number greater than 10 from the model
- Loop: Act -> Check -> Retry (up to
MAX_STEPStimes) - Validation: the model can return text, an empty string, or a non-numeric value - the agent handles it
- Stop condition: the agent stops either on success or when steps are exhausted
Project structure
examples/
βββ start-here/
βββ write-your-first-agent/
βββ python/
βββ main.py # agent loop
βββ llm.py # LLM call (integration isolation)
βββ evaluator.py # result validation
βββ requirements.txt
Why three files instead of one? Because in a real agent, generation and evaluation are almost always separated. If you want to change the model or validation logic, you change one file without touching the rest.
How to run
1. Clone the repository and move to the folder:
git clone https://github.com/AgentPatterns-tech/agentpatterns.git
cd examples/start-here/write-your-first-agent/python
2. Install dependencies:
pip install -r requirements.txt
3. Set API key:
export OPENAI_API_KEY="sk-..."
4. Run:
python main.py
Code
main.py - agent loop
from llm import generate_number
from evaluator import parse_int, is_goal_reached
GOAL = 10
MAX_STEPS = 5
def run():
for step in range(1, MAX_STEPS + 1):
print(f"\nπ€ Step {step}: Agent is trying...")
output = generate_number()
print(f"π¬ Model generated: {output}")
number = parse_int(output)
if number is None:
print("β Not a number. Trying again...")
continue
if is_goal_reached(number, GOAL):
print(f"β
Goal reached! {number} > {GOAL}")
return
print(f"β Not enough. {number} β€ {GOAL}. Trying again...")
print("\nβ οΈ Max steps reached without success")
if __name__ == "__main__":
run()
main.py knows nothing about OpenAI. It does not know how to parse numbers. It only controls the loop - that is the agent's role.
llm.py - model call
import os
from openai import OpenAI
api_key = os.environ.get("OPENAI_API_KEY")
client = OpenAI(api_key=api_key)
PROMPT = "Write ONLY a random number between 1 and 20. No text, no explanation."
def generate_number() -> str:
resp = client.responses.create(
model="gpt-4.1-mini",
input=PROMPT,
)
return resp.output_text.strip()
The model gets a task and returns text. It does not know there is an agent, a goal, or a step limit. It simply generates.
evaluator.py - result validation
def parse_int(text: str) -> int | None:
"""Returns int or None if text is not an integer."""
try:
return int(text.strip())
except (ValueError, AttributeError):
return None
def is_goal_reached(number: int, goal: int) -> bool:
"""Returns True if the number satisfies the condition."""
return number > goal
Two small questions with clear answers: "is it a number?" and "is the goal reached?". That is all.
requirements.txt
openai>=1.0.0
Example output
π€ Step 1: Agent is trying...
π¬ Model generated: 7
β Not enough. 7 β€ 10. Trying again...
π€ Step 2: Agent is trying...
π¬ Model generated: 3
β Not enough. 3 β€ 10. Trying again...
π€ Step 3: Agent is trying...
π¬ Model generated: 14
β
Goal reached! 14 > 10
Why this is an "agent", not just a function
| Function | Agent | |
|---|---|---|
| Number of attempts | 1 | up to MAX_STEPS |
| Checks result | β | β |
| Decides whether to continue or stop | β | β |
| Needs human involvement between steps | β | β |
One model call is not an agent.
A loop with validation and the decision "try again or stop" is an agent.
Where to dig next
Try modifying the example yourself:
- Change
GOAL = 10toGOAL = 19- how often will the agent reach the goal withinMAX_STEPS? - Remove
MAX_STEPSand usewhile True- what will happen? - Change the prompt so the model generates numbers from 1 to 100 - how will that affect agent behavior?
- Add a counter of total API calls and print it at the end