How to Build an AI Agent with Claude (Step by Step)
To build an AI agent with Claude, you write a loop: send Claude a message and a list of tools, run whichever tool it asks for, send the result back, and repeat until it stops asking. Anthropic’s own tutorial describes it as a walk “from a single tool call to a production-ready agentic loop” (Claude Platform docs, fetched 2026-11-14).
That loop is about 20 lines of Python, and this guide writes it first. Then it covers what the loop leaves out, which is where most of the work sits, and shows how to get those parts from a self-hosted agent instead. The POLYROB facts below come from the public repository at release v1.7.9, and the files are listed at the end.
What does it take to build an AI agent with Claude?
An agent is a model plus four things around it.
- A loop that keeps calling the model until the task is done.
- Tools the model can ask for: read a page, write a file, run a command.
- Memory so the next session does not start cold.
- Limits so a mistake does not run all night or cost more than you meant.
The API gives you the model. Everything else is yours to write or to borrow. In POLYROB’s code the same split shows up: the Anthropic adapter in modules/llm/anthropic_client.py does one narrow job, turning Claude’s content blocks into text and tool calls. It reads a block of type tool_use and copies out its id, name and input. The loop, the tools, the memory and the limits live elsewhere in the repository.
How do you write the agent loop with the Claude API?
Install the SDK, set ANTHROPIC_API_KEY, and run this. It gives Claude one tool, the current UTC time, and loops until Claude answers in text.
import datetime
import anthropic
client = anthropic.Anthropic() # reads ANTHROPIC_API_KEY
tools = [{
"name": "get_utc_time",
"description": "Return the current UTC time as an ISO 8601 string.",
"input_schema": {"type": "object", "properties": {}},
}]
def run_tool(name, tool_input):
if name == "get_utc_time":
return datetime.datetime.now(datetime.timezone.utc).isoformat()
return f"unknown tool: {name}"
messages = [{"role": "user", "content": "What time is it in UTC?"}]
for _ in range(10): # a step cap: never loop forever
response = client.messages.create(
model="claude-sonnet-5", # use an id your key can call
max_tokens=1024,
tools=tools,
messages=messages,
)
if response.stop_reason != "tool_use":
break
messages.append({"role": "assistant", "content": response.content})
results = []
for block in response.content:
if block.type == "tool_use":
results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": run_tool(block.name, block.input),
})
messages.append({"role": "user", "content": results})
print(response.content[0].text)
Three details decide whether this works.
- Stop on
stop_reason. Claude signals a tool request withstop_reasonset totool_use, and a finished answer withend_turn. Anthropic’s tutorial uses the same two values. - Echo the assistant turn back. Append
response.contentunchanged before you add the results, or the tool call ids no longer match. - Cap the loop. The
range(10)is the smallest possible limit. Without it, one confused tool call can repeat until your balance does.
Swap get_utc_time for a real tool and you have an agent. You do not yet have one you would leave running.
What does the bare loop leave out?
Each row below is something you would write next. The right column is where POLYROB already does it, with the file that shows it.
| You need | What you write on your own | What POLYROB does at v1.7.9 |
|---|---|---|
| A step and spend limit | A counter and a cost tally per run | Interactive runs stop at 100 steps (INTERACTIVE_MAX_STEPS). Autonomous runs stop at 150 steps or $2.00 of provider spend (AUTONOMOUS_MAX_STEPS, AUTONOMOUS_RUN_BUDGET_USD), and the run records why it stopped |
| Many tools | A schema and a handler per tool | Browser, files, git, shell, email and more are registered with one controller; polyrob run --toolset picks a named set |
| Memory | A store, a search and a prompt injection step | Cross-session memory in a local SQLite file with keyword search, and an optional vector backend |
| Cost control for long chats | Cache breakpoints and a stable prompt prefix | Prompt caching is on by default; tool schemas are sorted so the cached bytes do not move |
| Provider outages | A retry and a second provider | Failover to the same model family on another provider, then to another permitted one |
| Other tools via MCP | A client for the protocol | An MCP client; none are configured out of the box |
| Reaching it from your phone | A bot per chat app | Telegram, email, WhatsApp, Discord, Slack, Signal, Feishu/Lark and DingTalk, started with polyrob gateway |
| Running while you are away | A scheduler that survives restarts | Goals and cron jobs stored in SQLite |
None of these is hard alone. Each one is code you would have to write, test and keep working. For the connection side, see how to use Claude as the model in POLYROB.
How do you start from a self-hosted agent instead?
If the loop is not the part you want to own, install an agent that already has it and point it at Claude.
curl -fsSL https://polyrob.dev/install.sh | bash
polyrob config set ANTHROPIC_API_KEY
polyrob model set-default anthropic claude-sonnet-5
polyrob doctor
polyrob config set asks for the key with hidden input. polyrob doctor checks the setup and catches a missing or malformed key first. Pinning the model matters because POLYROB picks the first provider with a usable key when you have several, and a new key can change that. The Anthropic SDK is an optional extra named anthropic in pyproject.toml.
Run one real task with explicit limits:
polyrob run "read ./src and write architecture.md: modules, dependencies, data flow" --toolset coding --max-steps 40
RUN_BUDGET_USD=0.50 polyrob run "compare the top 10 vector databases into a table"
--max-steps bounds the run, and RUN_BUDGET_USD stops it when real provider cost reaches the cap. The run is reported as stopped, not as done. RUN_BUDGET_USD is off by default (it is 0), so set it yourself for interactive use.
How do you add your own tool?
Two routes, from lighter to heavier. Connect an MCP server, which the MCP client guide walks through, or read what MCP is first if the term is new. Or write a skill, a reusable procedure the agent loads on demand; agent skills explains how they are scoped and reviewed. In POLYROB a skill the agent writes for itself waits in quarantine until you approve it.
How do you build a personal AI agent with Claude?
A personal agent adds two things to the loop: it remembers you, and it works when you are not typing. With POLYROB both are configuration.
- Memory is on by default as a local SQLite file with full-text search. At the start of each step, relevant memories are prefetched into context; after each step, new findings are written back. The AI agent memory guide covers the details.
- Schedules use
polyrob job new. This needsCRON_ENABLEDon, whichpolyrob config set CRON_ENABLED truedoes.
polyrob config set CRON_ENABLED true
polyrob job new "every day 09:00" "Check https://example.com/product/12345 and tell me if it is under \$500"
polyrob job list
Self-directed loops such as goals are off by default and turn on together only when POLYROB_LOCAL and AUTONOMY_ENABLED are both set. The autonomous AI agent guide explains the levels, and the self-hosting guide covers running it on a server.
What does it cost to run a Claude agent, and can it be free?
The Claude API is metered, so a loop you wrote has no ceiling except the one you code. Your own agent can be free to own but not free to run: POLYROB is MIT licensed, so the software costs nothing, and you pay your model provider. A local model through an OpenAI-compatible endpoint costs nothing per token, but a small local model may do agent tasks poorly, and that trade is yours to test.
On cost, three mechanisms in the code matter most:
- Prompt caching is on by default.
ANTHROPIC_CACHE_TTLtakesauto,5mor1h, and withautoan interactive chat gets a 1-hour window while an autonomous run gets 5 minutes./contextandpolyrob doctorshow the effect on spend. - Per-run caps of 150 steps and $2.00 apply to autonomous work by default. This is per run, not a daily or monthly budget, and the spend check can fail open if the probe errors.
/pausestops autonomous work and survives a restart.
Setting the budget low first and raising it after a few observed runs is the safe order. For the injection side of the same risk, read the AI agent security guide.
Where does POLYROB fall short for this?
- It is not Claude-first. Claude is one of six built-in providers. If you want to learn the raw API, write the loop above yourself.
- You operate it. You install it, update it and watch the cost. Linux, macOS and WSL2 are supported, and Windows without WSL2 is not.
- Eight chat surfaces, with no native desktop or phone apps.
- A young project with a small community. The crypto and wallet code is an opt-in extra and is unaudited.
- Writing the loop teaches more. An agent you did not write is harder to debug at first.
Questions about building an AI agent with Claude
What is having an AI agent?
It means a model that does work in a loop instead of answering once. It picks an action, a tool runs it, and the result goes back to the model until the task is done.
How do you create a free agent with Claude?
The loop above and POLYROB are both free software to run, but Claude API calls are billed by Anthropic. If you need zero per-token cost, point POLYROB at a local model through ~/.polyrob/providers.yaml instead, and test whether it handles your tasks.
Do you need to know how to code?
To write the loop, yes. To install POLYROB, you need a terminal and an API key: the install command, one config set and model set-default.
Is this the same as building agents in Claude Code?
No. Claude Code is Anthropic’s coding tool for your repository. This guide covers an agent you run yourself, with its own memory, chat apps and schedules, which can use Claude as its model.
How many steps should a Claude agent be allowed to take?
Start small. POLYROB’s defaults are 100 steps for interactive runs and 150 steps or $2.00 for autonomous ones. Lower --max-steps for a first run and raise it once you have read the run record.
Where do you start?
Write the 20-line loop once so you know what is underneath. Then install an agent that has the rest, pin Claude, and run one bounded task before you switch anything autonomous on.
Install POLYROB or read the docs. The source is MIT licensed at github.com/theselfruleorg/polyrob.
Sources
POLYROB facts are from the public repository at release v1.7.9 (github.com/theselfruleorg/polyrob).
- modules/llm/[email protected] (tool_use block parsing)
- docs/guide/[email protected] (step loop, step caps, tools, memory flow, surfaces, autonomy loops, caching, failover, sub-agents)
- docs/[email protected] (
INTERACTIVE_MAX_STEPS100,AUTONOMOUS_MAX_STEPS150,AUTONOMOUS_RUN_BUDGET_USD2.0,RUN_BUDGET_USD0,ANTHROPIC_CACHE_TTL) - docs/[email protected] (
polyrob run,polyrob job new,RUN_BUDGET_USD) - docs/guide/[email protected] (
--toolset,--max-steps,model set-default) - docs/guide/[email protected] (installer platforms,
polyrob doctor) - modules/llm/[email protected] (
claude-sonnet-5) and [email protected] (anthropicextra) - Anthropic: Tutorial: Build a tool-using agent, fetched 2026-11-14.
POLYROB is an open-source AI agent you run and own. Install it or read the docs.