Building AI Agents from Scratch
The Agent Loop
Build the think → act → observe → repeat loop from scratch and decide when it stops.
One completion is a thought. An agent is a while that may think again after it acts. You own the loop. The vendor SDK does not.
The four steps
- Think — call the model with the current messages (and later, tools).
- Act — if the model asked for a tool, run your Python.
- Observe — append the tool result as a message the model can read.
- Repeat — until the model returns plain text, or you hit a cap.
This lesson implements think and stop only. Act arrives in Giving Your Agent Tools. The shape of run() should not change.
A loop with a hard stop
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["OPENAI_API_KEY"],
base_url=os.environ.get("OPENAI_BASE_URL") or None,
)
MODEL = os.environ.get("OPENAI_MODEL", "gpt-4.1-mini")
def think(messages: list[dict]) -> object:
return client.chat.completions.create(model=MODEL, messages=messages).choices[0].message
def run(user_text: str, max_steps: int = 8) -> str:
messages = [
{"role": "system", "content": "Solve the user's request. Be brief."},
{"role": "user", "content": user_text},
]
for step in range(max_steps):
message = think(messages)
messages.append({"role": "assistant", "content": message.content or ""})
# No tools yet: the first assistant message is the answer.
return message.content or ""
return "stopped: max steps"
if __name__ == "__main__":
print(run("Name three Linux commands that show disk use."))The for is the loop. max_steps is a fuse. Returning on the first assistant message is correct until tools exist — otherwise you would call the model forever on the same prompt.
When to stop
- The model returned content and no tool calls (final answer).
max_stepshit — return a structured “stopped” string, not silence.- Later: a human rejected an action, or a budget ran out.
Run the file. You should see a short list, then the process exits. Next: let the model request a tool.