← Blog

How to Build an AI Agent with Claude (Step by Step)

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.

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.

  1. Stop on stop_reason. Claude signals a tool request with stop_reason set to tool_use, and a finished answer with end_turn. Anthropic’s tutorial uses the same two values.
  2. Echo the assistant turn back. Append response.content unchanged before you add the results, or the tool call ids no longer match.
  3. 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 needWhat you write on your ownWhat POLYROB does at v1.7.9
A step and spend limitA counter and a cost tally per runInteractive 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 toolsA schema and a handler per toolBrowser, files, git, shell, email and more are registered with one controller; polyrob run --toolset picks a named set
MemoryA store, a search and a prompt injection stepCross-session memory in a local SQLite file with keyword search, and an optional vector backend
Cost control for long chatsCache breakpoints and a stable prompt prefixPrompt caching is on by default; tool schemas are sorted so the cached bytes do not move
Provider outagesA retry and a second providerFailover to the same model family on another provider, then to another permitted one
Other tools via MCPA client for the protocolAn MCP client; none are configured out of the box
Reaching it from your phoneA bot per chat appTelegram, email, WhatsApp, Discord, Slack, Signal, Feishu/Lark and DingTalk, started with polyrob gateway
Running while you are awayA scheduler that survives restartsGoals 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.

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:

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?

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).


POLYROB is an open-source AI agent you run and own. Install it or read the docs.