What are AI Agents?

April 14, 2026
#genai #ai #ai-agents #llm #tool-use

You’ve probably used ChatGPT or a similar LLM — you type a question, it gives you an answer. That’s a single turn of input and output. An AI agent is something more: it’s an LLM that can take actions, observe results, and decide what to do next in a loop. Instead of just answering questions, agents can browse the web, run code, query databases, call APIs, and chain multiple steps together to accomplish a goal.

If you’ve followed the earlier tutorials on calling LLM APIs and prompt engineering, you know how to get an LLM to generate text. This tutorial is about giving LLMs the ability to do things.

Chat vs Agent

A regular LLM chat works like this:

User: What's the weather in Seattle?
LLM:  I don't have access to real-time data, but Seattle typically...

The LLM can only generate text based on its training data. It can’t actually check the weather.

An agent works differently:

User:  What's the weather in Seattle?
Agent: I need to check the weather. Let me call the weather API.
       → calls get_weather("Seattle")
       ← { temp: 58, condition: "cloudy" }
Agent: It's currently 58°F and cloudy in Seattle.

The agent recognized it needed external data, chose the right tool, called it, and incorporated the result into its response. That loop — think → act → observe → repeat — is what makes an agent an agent.

The Agent Loop

Every agent follows the same basic pattern, often called the ReAct (Reasoning + Acting) loop:

┌─────────────────────────────────────┐
│  1. Receive task or user message    │
│  2. Think: What do I need to do?    │
│  3. Act: Call a tool / take action  │
│  4. Observe: Read the result        │
│  5. Repeat 2-4 until task is done   │
│  6. Return final answer to user     │
└─────────────────────────────────────┘

Here’s what that looks like in pseudocode:

async function agentLoop(userMessage, tools) {
    const messages = [{ role: "user", content: userMessage }];

    while (true) {
        const response = await callLLM(messages);

        // If the LLM wants to call a tool
        if (response.toolCall) {
            const result = await tools[response.toolCall.name](response.toolCall.args);
            messages.push({ role: "assistant", content: response.text, toolCall: response.toolCall });
            messages.push({ role: "tool", content: JSON.stringify(result) });
            continue;
        }

        // Otherwise, the LLM is done — return the final answer
        return response.text;
    }
}

The LLM decides on each iteration whether to call a tool or return a final answer. The developer provides the tools; the LLM decides when and how to use them.

Tools and Function Calling

Tools are the actions an agent can take. They’re regular functions that you define and describe to the LLM. Most LLM providers (OpenAI, Anthropic, etc.) support function calling — a structured way for the model to request a tool invocation.

Here’s how you define tools for the OpenAI API:

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

When you send this tool definition along with a user message, the model can choose to call it:

import OpenAI from "openai";

const client = new OpenAI();

const response = await client.chat.completions.create({
    model: "gpt-4o",
    messages: [{ role: "user", content: "What's the weather in Seattle?" }],
    tools: tools,
});

const toolCall = response.choices[0].message.tool_calls[0];
console.log(toolCall.function.name);      // "get_weather"
console.log(toolCall.function.arguments); // '{"city":"Seattle"}'

The model doesn’t execute the function — it tells you which function to call and with what arguments. You execute it, then send the result back:

// Execute the tool
const weatherResult = await getWeather("Seattle");

// Send the result back to the model
const followUp = await client.chat.completions.create({
    model: "gpt-4o",
    messages: [
        { role: "user", content: "What's the weather in Seattle?" },
        response.choices[0].message,
        {
            role: "tool",
            tool_call_id: toolCall.id,
            content: JSON.stringify(weatherResult),
        },
    ],
    tools: tools,
});

console.log(followUp.choices[0].message.content);
// "It's currently 58°F and cloudy in Seattle."

A Complete Agent Example

Let’s build a simple agent that can look up the weather and do math. This ties together the agent loop, tool definitions, and function calling:

import OpenAI from "openai";

const client = new OpenAI();

// Define the actual tool implementations
const toolImplementations = {
    get_weather: async ({ city }) => {
        // In a real app, this would call a weather API
        const data = { Seattle: "58°F, cloudy", Tokyo: "72°F, sunny" };
        return data[city] || "Weather data not available";
    },
    calculate: async ({ expression }) => {
        try {
            return String(Function(`"use strict"; return (${expression})`)());
        } catch {
            return "Invalid expression";
        }
    },
};

// Define tool schemas for the LLM
const tools = [
    {
        type: "function",
        function: {
            name: "get_weather",
            description: "Get current weather for a city",
            parameters: {
                type: "object",
                properties: { city: { type: "string" } },
                required: ["city"],
            },
        },
    },
    {
        type: "function",
        function: {
            name: "calculate",
            description: "Evaluate a math expression",
            parameters: {
                type: "object",
                properties: { expression: { type: "string" } },
                required: ["expression"],
            },
        },
    },
];

async function runAgent(userMessage) {
    const messages = [
        { role: "system", content: "You are a helpful assistant. Use tools when needed." },
        { role: "user", content: userMessage },
    ];

    while (true) {
        const response = await client.chat.completions.create({
            model: "gpt-4o",
            messages,
            tools,
        });

        const message = response.choices[0].message;
        messages.push(message);

        // If no tool calls, we're done
        if (!message.tool_calls) {
            return message.content;
        }

        // Execute each tool call and add results
        for (const toolCall of message.tool_calls) {
            const fn = toolImplementations[toolCall.function.name];
            const args = JSON.parse(toolCall.function.arguments);
            const result = await fn(args);

            messages.push({
                role: "tool",
                tool_call_id: toolCall.id,
                content: String(result),
            });
        }
    }
}

// Try it
const answer = await runAgent("What's 15% tip on $84.50, and what's the weather in Tokyo?");
console.log(answer);

The agent handles both questions in a single run — it calls calculate for the tip and get_weather for Tokyo, then combines the results into a natural response.

When to Use Agents

Agents are powerful but not always necessary. Here’s a quick guide:

Use an agent when:

  • The task requires external data (APIs, databases, web search)
  • The task has multiple steps that depend on each other
  • The user’s request is open-ended and you can’t predict the exact steps

Use a simple LLM call when:

  • You just need text generation, summarization, or classification
  • The input and output are well-defined
  • You don’t need external data

Agent Patterns

As agents get more sophisticated, a few patterns emerge:

  • ReAct — the think/act/observe loop we covered above. The most common pattern.
  • Plan and Execute — the agent creates a full plan first, then executes each step. Better for complex multi-step tasks.
  • Multi-Agent — multiple specialized agents collaborate. One agent might research while another writes code.

We’ll explore function calling in more depth and build more complex agents in upcoming tutorials.

What’s Next

Now that you understand what agents are and how the agent loop works, the next step is diving deeper into Function Calling & Tool Use to learn how to design effective tools and handle edge cases like validation and error recovery.

Thanks for visiting
We are actively updating content to this site. Thanks for visiting! Please bookmark this page and visit again soon.
Sponsor