← Blog

How to Create an AI Agent: A Step-by-Step Guide

2026-09-21 · 5 min read · SubToAPI Team

An AI agent is a program that uses a language model to decide what to do next, not just to answer a single prompt. You give it a goal, a set of tools, and a loop that lets it observe results and act again. Creating one means wiring together four things: a model that can reason and call tools, a set of functions the model can invoke, a way to track state across steps, and a runtime that keeps looping until the task is done or a limit is hit.

This guide walks through that process concretely, with working code, so you can build a real agent rather than just a chatbot with extra prompts.

What Actually Makes Something an "Agent"

A plain LLM call takes input and returns output once. An agent adds a loop:

  1. Observe – get the current state (user request, tool results, prior steps)
  2. Reason – the model decides what to do next
  3. Act – call a tool, run code, query a database, hit an API
  4. Repeat – feed the result back in until the goal is met

The core difference from a chatbot is that the model's output can trigger real actions, and those actions produce new information the model reasons over. That's what "agent" means in practice — not a specific framework, but this observe-reason-act cycle.

Step 1: Define the Goal and Boundaries

Before writing code, decide:

Skipping this step is the most common reason agent projects spiral into unpredictable behavior. Scope it tightly first, then expand.

Step 2: Choose Your Tools

Tools are just functions with a name, description, and schema for their inputs. The model doesn't execute them — it outputs a request to call one, your code runs the actual function, and you send the result back.

A minimal tool definition looks like this:

{
  "name": "get_weather",
  "description": "Get current weather for a city",
  "input_schema": {
    "type": "object",
    "properties": {
      "city": { "type": "string" }
    },
    "required": ["city"]
  }
}

Keep tool descriptions specific. Vague descriptions ("does stuff with data") lead to the model calling the wrong tool or passing malformed arguments. Write descriptions the way you'd explain the function to a new engineer.

Step 3: Build the Loop

Here's a working agent loop in JavaScript using a Claude-compatible Messages API. This example uses SubToAPI, which exposes Claude through a standard HTTPS API with streaming and tool use — useful if you already have Claude access and want an API key without separate infrastructure.

const tools = [
  {
    name: "get_weather",
    description: "Get current weather for a given city",
    input_schema: {
      type: "object",
      properties: { city: { type: "string" } },
      required: ["city"]
    }
  }
];

async function callModel(messages) {
  const res = await fetch("https://api.subtoapi.app/v1/messages", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${process.env.SUBTOAPI_KEY}`,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      model: "claude-sonnet-4",
      max_tokens: 1024,
      messages,
      tools
    })
  });
  return res.json();
}

async function runAgent(userInput) {
  let messages = [{ role: "user", content: userInput }];

  for (let step = 0; step < 8; step++) {
    const response = await callModel(messages);
    const toolUse = response.content.find(b => b.type === "tool_use");

    if (!toolUse) {
      return response.content.find(b => b.type === "text")?.text;
    }

    const result = await executeLocalTool(toolUse.name, toolUse.input);

    messages.push({ role: "assistant", content: response.content });
    messages.push({
      role: "user",
      content: [{
        type: "tool_result",
        tool_use_id: toolUse.id,
        content: JSON.stringify(result)
      }]
    });
  }

  return "Agent hit the step limit without finishing.";
}

async function executeLocalTool(name, input) {
  if (name === "get_weather") {
    return { city: input.city, tempC: 21, condition: "cloudy" };
  }
  return { error: "unknown tool" };
}

This is the entire skeleton. Everything else — memory, planning, multi-agent coordination — is built on top of this loop.

Step 4: Add Memory and State

For anything beyond a single session, you need to persist state:

Don't over-engineer this early. A simple array with a hard cap on message count solves most single-session agents.

Step 5: Handle Errors and Guardrails

Agents fail in specific, predictable ways:

Step 6: Deploy It Behind an API

Once the loop works locally, wrap it in an HTTP endpoint so other services or a frontend can call it. If you're building on Claude, you'll need an API key, streaming support, and usage tracking — a signup at /signup gives you a sub_live_... key and a free trial to test this without committing to a plan upfront. Full request and response formats are documented at /docs/messages, and the quickstart at /docs/quickstart covers authentication end to end.

Common Mistakes to Avoid

questions

Do I need a framework to build an AI agent? No. A framework like LangChain or a custom orchestration library can speed up development, but the core pattern — loop, call model, execute tool, feed result back — is simple enough to build from scratch, and doing so once makes debugging frameworks much easier later.

What's the difference between an AI agent and a chatbot? A chatbot returns text in response to text. An agent can call functions, take real actions (search, write to a database, send a request), observe the outcome, and decide on a next step — it operates in a loop rather than a single request-response exchange.

How do I control API costs when running an agent? Set a hard cap on loop iterations, track token usage per run, and use streaming so you can cancel a response early if it's going off track. Reviewing usage metadata per request (available via /docs/tools) also helps you spot expensive tool-calling patterns before they scale.

Turn your Claude access into an HTTPS API

SubToAPI gives you application API keys, streaming, tool use and usage insights on top of your existing Claude access — set up in minutes.

Start free  Read the quickstart →