How to Build Your First AI Agent: A Complete Step-by-Step Guide

A working, verified guide to building your first AI agent — both no-code (n8n) and code (Claude API) paths, with real runnable code and honest caveats where documentation is unclear.

By Lumis Editorial · 9 min read · September 3, 2026

How to Build Your First AI Agent: A Complete Step-by-Step Guide

An "AI agent" is not just a chatbot with a fancier name. A chatbot takes your message and produces a reply — text in, text out, nothing else happens. An agent does something in between: it can decide, on its own, to call a tool — check a calendar, run a search, hit an API, query a database — look at what that tool returns, and decide what to do next, possibly calling another tool, until it has enough to actually answer you or complete the task. The "agent" part is that loop of deciding and acting, not the model itself. Everything below builds exactly that loop, two different ways.

What you need before you start (both paths)

  • An Anthropic API key — both paths in this guide use Claude as the model. Create an account and generate a key in the Claude Console at platform.claude.com. New accounts get a small amount of free credit to start; Anthropic's own current documentation doesn't state a fixed dollar amount for this, so check your console after signup rather than assuming a number.
  • For the no-code path: either an n8n Cloud account (free trial, no credit card, capped at 1,000 workflow executions) or self-hosted n8n — see the caveat below before assuming self-hosted covers everything.
  • For the code path: Python installed on your machine, and comfort running a script from a terminal. No other libraries beyond one package install.
  • Real cost to expect: Claude API pricing is billed by tokens, not a flat fee. As a concrete reference point from Anthropic's own pricing page, processing 10,000 typical short conversations on the cheapest current model (Haiku 4.5) costs around $37 total. Building and testing your first agent — dozens of test messages, not thousands — will cost cents, not dollars.

Path 1: No-code, with n8n

n8n now has a dedicated Agents feature (separate from, and newer than, the older "drop an AI node into a workflow" pattern you'll see in some older tutorials). As of this writing it's in Preview, meaning n8n itself says it can still change.

  1. In your n8n project, open the Agents tab and click Create Agent. Give it a name.
  2. In the agent's Model field, choose Anthropic as the provider, pick a Claude model, and add your API key when prompted.
  3. Write instructions for the agent: its role, its tone, and — this matters more than people expect — what it should not do. A boundary you state explicitly is one the agent won't accidentally cross.
  4. Go to the Tools section and click Add tool. You can wire up a built-in integration (Slack, Google Sheets), another n8n workflow, a custom tool defined by a JSON schema, or an MCP server. Start with exactly one tool. Resist adding five.
  5. Click Preview to test in a chat panel without publishing anything. Send it a message that should trigger the tool and watch what happens.
  6. When it behaves the way you want, click Publish. Only the published version is live — your draft changes in Preview don't affect anything running in production until you publish again.

What the documentation doesn't confirm: n8n's documentation says agents aren't yet available on self-hosted Enterprise. It does not explicitly say whether they work on self-hosted Community (the free, open-source edition) — there is no clear statement either way. If you're planning to self-host specifically to avoid the Cloud trial's execution cap, verify this in your own n8n instance before committing to that plan, rather than assuming it works because Community usually gets everything Enterprise does.

Path 2: Code, with the Claude API directly

This path gives you more control and teaches you what's actually happening under the no-code version's hood. The core idea: you describe a tool to Claude (a name, a description, and a schema for its inputs), send a message, and Claude replies either with plain text or with a request to call that tool. When it asks to call a tool, your code runs it and sends the result back. Repeat until Claude has what it needs to give you a real answer.

Install the SDK:

pip install anthropic

Set your API key as an environment variable so your code never has it hardcoded (never put an API key directly in a script you might share or commit to git):

# macOS/Linux
export ANTHROPIC_API_KEY="your-key-here"

# Windows (PowerShell)
$env:ANTHROPIC_API_KEY = "your-key-here"

Here's a complete, runnable agent — adapted from Anthropic's own official tutorial. It defines one tool (creating a calendar event), sends a request, and loops until Claude stops asking for tool calls:

import json
import anthropic

client = anthropic.Anthropic()

tools = [
    {
        "name": "create_calendar_event",
        "description": "Create a calendar event with attendees and optional recurrence.",
        "input_schema": {
            "type": "object",
            "properties": {
                "title": {"type": "string"},
                "start": {"type": "string", "format": "date-time"},
                "end": {"type": "string", "format": "date-time"},
                "attendees": {
                    "type": "array",
                    "items": {"type": "string", "format": "email"},
                },
                "recurrence": {
                    "type": "object",
                    "properties": {
                        "frequency": {"enum": ["daily", "weekly", "monthly"]},
                        "count": {"type": "integer", "minimum": 1},
                    },
                },
            },
            "required": ["title", "start", "end"],
        },
    }
]

def run_tool(name, tool_input):
    if name == "create_calendar_event":
        # Replace this with a real calendar API call.
        return {"event_id": "evt_123", "status": "created", "title": tool_input["title"]}
    return {"error": f"Unknown tool: {name}"}

messages = [
    {
        "role": "user",
        "content": "Schedule a weekly team standup every Monday at 9am for the next 4 weeks. Invite alice@example.com, bob@example.com, carol@example.com.",
    }
]

response = client.messages.create(
    model="claude-sonnet-5",
    max_tokens=1024,
    tools=tools,
    tool_choice={"type": "auto", "disable_parallel_tool_use": True},
    messages=messages,
)

while response.stop_reason == "tool_use":
    tool_use = next(block for block in response.content if block.type == "tool_use")
    result = run_tool(tool_use.name, tool_use.input)

    messages.append({"role": "assistant", "content": response.content})
    messages.append({
        "role": "user",
        "content": [
            {"type": "tool_result", "tool_use_id": tool_use.id, "content": json.dumps(result)}
        ],
    })

    response = client.messages.create(
        model="claude-sonnet-5",
        max_tokens=1024,
        tools=tools,
        tool_choice={"type": "auto", "disable_parallel_tool_use": True},
        messages=messages,
    )

final_text = next(block for block in response.content if block.type == "text")
print(final_text.text)

Run it with python your_file.py. Claude will call create_calendar_event once for each of the four weekly occurrences, your run_tool function will "create" each one (fake, in this example — swap in a real calendar API and it's a real agent), and the loop exits once Claude has enough to summarize what it did. Note the model used here is claude-sonnet-5 — a cheaper, fully capable choice for a first agent; swap in claude-opus-5 if you need stronger reasoning for a more complex tool later.

Common mistakes beginners make

Writing the tool description for a human, not for the model. Claude decides whether to call a tool based entirely on its description field. "Handles calendar stuff" tells the model almost nothing about when to use it versus not. "Create a calendar event with attendees and optional recurrence" tells it exactly when this tool applies.

Forgetting the loop can run more than once. A beginner's first version often makes one API call, gets a tool_use response, and just prints it — instead of executing the tool and sending the result back. The agent never actually finishes the task; it just announces what it's about to do.

Starting with five tools instead of one. More tools means more chances for Claude to pick the wrong one, and more surface area for you to debug when it does. Get one tool working end to end before adding a second.

Treating "agent" as a magic upgrade. It's not more autonomous than the code you wrote to execute its tool calls. If run_tool doesn't handle a failure case, the agent doesn't either — it just calls the tool, gets an error back, and has to decide what to do with that, same as any code path you didn't handle.

Publishing before testing the failure case. In n8n, it's easy to test the happy path in Preview and publish. Try the request that should not work — a missing required field, an ambiguous instruction — before you publish, so you know what the agent does when things go wrong, not just when they go right.

What to build next

Once one tool works, add a second and see how Claude chooses between them — this is where description quality actually starts to matter. Look at Anthropic's server tools (web search, code execution) if you want new capability without writing an execution handler yourself. If you built the n8n version, try publishing it to an actual channel — Slack or a scheduled trigger — instead of just testing in Preview. And if you want to see the exact same tool-use pattern handle a more complex, multi-step task, that's the natural next thing to build: not a new concept, just this same loop with more at stake.