What is an AI Agent?
Theme
Palette
Download
Caption (tap to copy)
📖 Deep dive (full written explanation)
This is the hands-on post, and the cover promises a real agent you can paste into a file with no framework — just the loop. After three posts of concept and mechanics, the reader wants to see the model actually choose a tool and act on the result.
The post is structured to be runnable top to bottom: install, define tools as plain functions, describe them to the model with schemas, run the loop, execute the calls, and finally show the same thing through a framework. The payoff to watch for is the model deciding on its own to call a tool, reading the result, and only then producing an answer.
The install slide is deliberately minimal: a single dependency. Using the OpenAI SDK directly keeps the focus on the loop rather than on framework abstractions, and tool/function calling is a first-class feature of the API, so nothing else is needed to build a complete agent.
Keeping the dependency footprint to one package means the reader can run the entire post in a fresh environment with just an API key. The framework version later is shown as an option, not a requirement, so the core lesson stands on its own without any heavyweight library.
This slide defines the agent's tools as ordinary Python functions, which is the right mental model: a tool is just a function the model is allowed to request. get_weather returns canned data so the example runs offline, and calculator evaluates an expression. They're registered in a TOOLS dict keyed by name so the loop can look them up later.
The eval in calculator carries an explicit 'demo only' warning because evaluating arbitrary expressions is exactly the kind of dangerous tool the mistakes post addresses. In production you'd sandbox it. Showing the warning inline reinforces that tool safety is the developer's responsibility, not the model's.
This slide describes the tools to the model using the JSON-schema format the API expects. Each tool gets a name, a human-readable description, and a parameters schema declaring argument names, types, and which are required. This is the only thing the model sees about each tool — it chooses based entirely on these descriptions.
That's why the descriptions and schemas matter so much: they're the model's entire understanding of what each tool does and how to call it. Post 5 makes vague descriptions one of the five mistakes, and this slide is where the reader sees what a clear, typed description actually looks like in practice.
This slide starts the agent loop itself. We create the client, seed the messages with a user goal that deliberately needs both tools, and enter a bounded for-loop. On each pass we call the model with the messages and the tool schemas, append the model's reply to the running history, and check whether it requested any tools.
If there are no tool calls, the model has produced its final answer and we print it and break. The bound of five iterations is the same MAX_STEPS discipline from post 3 — a hard ceiling so the loop always terminates. The tool execution that this loop depends on is the very next slide.
This slide is the execution half of the loop, and it's where the model's decision becomes a real function call. For each tool call the model requested, we read the tool name, parse the JSON arguments string into a Python dict, look up the real function in TOOLS, and call it with those arguments.
We then append a message with role 'tool' and the matching tool_call_id, carrying the result back as the observation. That tool_call_id linkage is essential — it tells the model exactly which call this result answers. Once these tool messages are appended, the loop's next iteration sends everything back and the model can write its grounded final answer.
The pipeline diagram summarizes the five moves the code just performed so the reader can map syntax to concept. Ask: the user goal goes in. Decide: the model picks which tools to call. Run: your code executes the real functions. Feed back: the observations return to the model. Answer: the model produces a grounded reply.
Placing this after the two code stages lets it act as a recap rather than an introduction. The reader has now seen the request, the decision, and the execution in code; the diagram lets them step back and confirm how the pieces connect end to end.
This tips slide walks the reader through reading an actual run, because seeing the trace cements how the loop behaves. On turn one the model requests both get_weather and calculator in a single response. Your code runs both and appends two tool messages. On turn two the model now has both results in context and writes the final combined answer.
The key signal to recognize is the absence of tool_calls — that's the loop's exit condition made concrete. Learning to read this trace is also the foundation for debugging, which is why post 5 makes logging the full trace a core reliability practice.
This slide shows the same agent through a framework so the reader sees that libraries hide the exact loop they just wrote, not something different. With LangChain you decorate a function as a tool, create a ReAct agent, wrap it in an executor, and invoke it. The docstring on the tool becomes the description the model reads — the same role the JSON schema played in the from-scratch version.
The lesson is reassurance and demystification at once: frameworks add convenience, memory, and tracing, but underneath they run the reason-act-observe loop from posts 3 and 4. Knowing the raw loop means you can debug and customize any framework instead of treating it as magic.
This tips slide bridges from a working demo to a production-ready agent, previewing the discipline the final post details. Sandbox any tool that touches code, files, or money so a wrong call can't cause real damage. Add retries and a per-tool timeout so a flaky tool doesn't hang or fail the whole run. Log every thought, call, and observation for debugging. And always keep MAX_STEPS so the loop can't run away.
Each of these maps directly to a mistake in post 5. Surfacing them here, at the moment the reader has a working agent, makes the transition from 'it runs' to 'it's safe to ship' concrete rather than abstract.
The takeaway slide compresses the whole build into one sentence: an agent is just this loop — describe tools, let the model choose, execute in your code, feed results back, repeat. That's the design pattern to carry away from the entire day.
The second point — that frameworks add memory, tracing, and retries but the engine is the dozen lines you just wrote — is the empowering conclusion. The reader is not dependent on any library to understand or build agents. They've seen the real machinery and can now reason about any agent system from first principles.
The CTA hands off to the final post of the day. The reader can now build a working tool-using agent; the remaining risk is the subtle, expensive ways agents break once they leave the demo.
Day 76's teaser flags the mistakes post: the failure modes — unbounded loops, vague tools, compounding errors, dangerous powers without guardrails, and no observability — that quietly wreck an agent in production even when the code runs fine.