Build your first agent
An agent is a model wired to a tool and a loop. This walks through the smallest version that actually works: one goal, one tool, a loop that requests, executes, and returns, and the guardrails that keep it from running away from you.
What you’ll learn
- Pick a goal narrow enough to need exactly one tool, and state both the goal and the tool in a single sentence each.
- Write a tool definition, name, description, input schema, that gives the model enough signal to decide when to use it.
- Build the request, execute, return loop that turns a single tool call into a working agent.
- Add a stop condition and a hard step cap so the loop cannot spin forever on a broken tool or an underspecified goal.
- Add a human approval checkpoint before any tool call that sends, spends, deletes, or otherwise touches something real.
An agent is not a special kind of model. It is a model wired to two things: a tool it can call, and a loop that keeps talking to it until the job is done. This walks through building the smallest version of that, one goal, one tool, and a loop tight enough to see exactly what happens at every step. Skip everything else for now, memory, planning, multiple tools, until this one works end to end.
1. Pick a small goal and the one tool it needs
Start narrower than feels useful. A good first goal has one clear tool need and an obvious way to tell whether it succeeded: "check whether a website is up and report its status code," not "monitor my infrastructure." "Look up an exchange rate and convert an amount," not "manage my budget." If the goal needs three tools, you are building three agents worth of complexity, not testing the loop.
Name the one tool the goal needs before writing any code. For "is this site up," the tool is a function that takes a URL and returns a status code. That is the entire surface area the model gets for this exercise. Everything else, it has to answer from its own knowledge, or say it does not know.
2. Define the tool: name, what it does, its inputs
A tool definition is not the function itself, it is the description of the function that you hand to the model. The model never sees your code. It sees three things: a name, a description of what the tool does and when to use it, and a schema for the inputs it needs to make the call. The description does most of the work, it is the only signal the model has for deciding whether this tool is relevant to the current turn.
tool = {
name: "check_url",
description:
"Checks whether a URL is reachable and returns its HTTP status code. Use this when the user asks whether a site or endpoint is up, down, or reachable.",
inputs: {
url: {
type: "string",
required: true,
description: "The full URL to check, including https://"
}
}
}3. Call the model and let it decide
Send the model the goal and the tool definition together, then give it a request that tool could plausibly answer. Do not force the tool call. The model should read the description and decide on its own whether the request needs it. This is also the test that the description from step 2 actually works: give it a request the tool cannot help with, and a well-described tool leads to a plain answer, or an honest "I do not know," not a forced, irrelevant call.
response = model.call(
system: "You have access to tools. Use one only when it helps answer the request.",
tools: [tool],
messages: [{ role: "user", content: "Is https://example.com up right now?" }]
)4. Run the loop: request, execute, return, repeat
This is the part that turns a single tool call into an agent. The model never runs your code, it requests a call by name and arguments, your code executes it, and you hand the result back as part of the conversation so the model can use it in its next reply.1 Then you check whether it is done. If not, you go around again.
- 1Send goal + tool listyour code, to the model
- 2Model respondsplain text, or a tool call request
- 3Execute the toolyour code runs it, never the model
- 4Return the resultappended back into the conversation
- 5Check for donefinal answer, stop signal, or step cap
messages = [{ role: "user", content: goal }]
steps = 0
while steps < MAX_STEPS:
reply = model.call(messages, tools=[tool])
messages.append(reply)
if reply.type == "final_answer":
break
if reply.type == "tool_call":
result = run_tool(reply.tool_name, reply.tool_input)
messages.append({ role: "tool_result", content: result })
steps += 15. Add a stop condition and a step cap
Two separate guards, not one. A stop condition is the agent's own signal that it is done: a final answer, a specific tool result that means the goal is reached, or a deliberate "give up" response you define. A step cap is a hard number, MAX_STEPS above, and it is not a scenario you expect to hit, it is a circuit breaker. A tool that never resolves, a model that keeps re-requesting the same call, or a goal that was underspecified would otherwise loop forever, burning tokens on every pass with nothing to show for it.
Set the cap low at first, five or ten iterations, and only raise it once you have watched the loop run a few times and understand why it needs more. A loop that needs fifty steps to check a URL is not a bigger version of the same agent. It is a bug.
6. Keep a human in the loop for anything real
Everything above is safe to let run unattended because nothing in it touches the outside world. The moment a tool can send a message, spend money, delete something, or write to a system another person depends on, the loop needs a checkpoint, not a log line after the fact.
- Add an approval step between "model requests the call" and "your code executes it" for anything irreversible: sending an email, making a purchase, deleting a record, pushing to production.
- Show the exact call and its inputs at that checkpoint, not a summary. "Send an email" is not enough, show the recipient, subject, and body.
- Log every tool call and its result regardless of stakes. Low-risk actions still need a trail for when something goes wrong.
- Treat a tool's own output as untrusted on the next loop. A scraped page or an API response can carry text aimed at steering the model, not just data for it to use.
This is the shortest path from a model that talks to one that acts. Once the loop works for a single tool, adding a second is mostly repetition: another entry in the tool list, a name-based dispatch in the executor, and tighter descriptions so the model does not confuse the two. For the concepts underneath all of this, models, tools, memory, and where the loop sits, see What an AI agent actually is. For a fuller build with real code across multiple lessons, the Building with AI course covers this same loop plus what comes after it: memory, planning, and agents with more than one tool.
Sources
Verified against primary sources: August 2026.
- Tool use with Claude. Anthropic (official docs). https://platform.claude.com/docs/en/agents-and-tools/tool-use/overview