From zero to your first autonomous AI — step by step. No fluff, just the concepts that matter and the code to prove it.
# The agentic loop — the heart of every agent while True: response = client.messages.create( model="claude-sonnet-4-5", tools=tools, messages=messages ) if response.stop_reason == "tool_use": result = run_tool(response) messages.append(result) else: print(response.content) break $ python agent.py → Searching for AI news... → Summarising 12 articles... ✓ Done in 4 steps.
You've used ChatGPT. An LLM gives you one answer. An agent has goals, tools, and the ability to keep going until the job is done.
You send a message. It sends one back. No memory of what came before, no tools, no way to act on the world.
You give it a goal. It plans, calls tools, observes results, and decides whether it's done. Many steps, not one.
No matter how complex an agent gets, it is always built from the same four pieces. Click each one to expand.
how it touches the world
Tools are functions the agent can call — web search, a calculator, a database query, an API. Without tools, an agent is just a chatbot with ambition. Tools give it the ability to act.
what it holds onto
Memory is the growing conversation history — every tool call, every result, every decision — passed back in on each step. This is how the agent knows what it already tried.
how it decides what's next
Planning is the model reasoning about what to do next. In powerful agents you make it explicit — prompting the model to write a plan before it acts.
what makes it autonomous
The loop is your runner — code that keeps calling the model until it decides it's done. Tool call? Run it and loop. Final answer? Stop. This is the engine of every agent.
Exactly what happens from the moment you give an agent a goal to the moment it returns an answer.
This is the whole pattern. Every challenge builds a more capable version of exactly this.
# 1. Define what tools the agent can use tools = [{ "name": "web_search", "description": "Search the web for current information", "parameters": { "query": { "type": "string" } } }] # 2. Seed memory with the user's goal messages = [{ "role": "user", "content": "Summarise today's AI news" }] # 3. The loop while True: response = client.messages.create( model="claude-sonnet-4-5", tools=tools, messages=messages ) if response.stop_reason == "tool_use": result = run_tool(response.tool_call) messages.append(response) # agent's turn messages.append(result) # tool result else: print(response.content) # final answer break
Five challenges. Each one adds a capability to a single agent you will own by the end.