LLM Agents & Tool Use

Reviewed & published by Brayan K

An LLM agent is a language model that can do things, not just talk. You give it tools (search, code, APIs) and run it in a loop: it reasons about what to do, emits a structured call to a tool, your code runs that tool and returns the result, and the model continues until the task is done. The formula is simple: agent = LLM + tools + a loop.

Part of the free AI & Machine Learning course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

In this lesson you'll learn function/tool calling, the ReAct (reason + act) loop, planning and multi-step execution, memory, reflection, and the guardrails that keep an agent safe — the same building blocks used by frameworks like LangChain, LlamaIndex, and the native tool APIs from OpenAI and Anthropic.

What You'll Learn in This Lesson

1 Agent = LLM + tools + a loop

A plain chatbot answers once and stops. An agent can take actions in the world and react to what it sees. The three ingredients:

prompt -> model -> one answer
(no tools, no follow-up actions)

Great for a single answer, but it can't look anything up or act on the result.

loop:
  reason about the goal
  call a tool (search/code/API)
  observe the result
  stop when the task is done

The loop is what lets it break a task into steps and adapt as it learns more.

2 Function / tool calling — who runs what

This is the most misunderstood part: the model never runs your code. You describe each tool to the model, and when it wants one, it emits a structured call. Your application executes it and returns the result. The steps:

StepWho does it
🧰 Describe tools (name + JSON schema)You, once, up front.
🧠 Decide to call a toolThe model — it emits a structured call.
⚙️ Run the real functionYour code (the model can't execute anything).
🔁 Return the resultYou feed it back into the conversation.
✅ Use the resultThe model, on the next step of the loop.

Tip: a tool's schema (clear name, description, typed arguments) is part of the prompt — well-described tools get called correctly far more often.

3 The ReAct loop — reason, act, observe

ReAct stands for Reason + Act. Instead of answering in one shot, the agent interleaves thinking and doing, then observes and repeats:

"The rate is probably about 1.1"
(no tool, possibly stale or wrong)
Thought: I need the live rate.
Action: get_rate("EUR","USD")
Observation: 1.08
Answer: 1.08 (from the live tool)

Run this tiny agent. The “model” is faked so you can watch the reason → act → observe loop without an API key:

# An LLM agent is just: a model + tools + a LOOP.
# Here we FAKE the model's decision so you can watch the loop run.

def search(query):                 # a "tool" the agent can call
    return "Paris is the capital of France."

def fake_model(question, observations):
    # A real LLM would reason here. We hard-code the decision:
    if not observations:
        return {"action": "search", "input": question}   # ACT: call a tool
    return {"action": "final", "input": observations[-1]} # we have enough info

def run_agent(question, max_steps=5):
    observations = []
    for step in range(max_steps):                 # the LOOP (stops at max_steps)
        decision = fake_model(question, observations)   # REASON
        if decision["action"] == "final":
            return decision["input"]
        result = search(decision["input"])        # ACT: run the tool
        observations.append(result)               # OBSERVE: feed result back
    return "Stopped: hit the step limit."

print(run_agent("What is the capital of France?"))
# Output: Paris is the capital of France.

And here's what tool calling really looks like — the model emits a structured call, your code runs it:

# WHAT THE MODEL ACTUALLY EMITS for tool calling: a STRUCTURED call.
# The model does NOT run the function — your code does, then returns the result.
import json

# 1) The model outputs something like this (a structured tool call):
tool_call = json.loads('{"tool": "get_weather", "arguments": {"city": "Paris"}}')

# 2) YOUR code looks up the real function and runs it:
def get_weather(city):
    return f"It is 21C and sunny in {city}."

tools = {"get_weather": get_weather}
result = tools[tool_call["tool"]](**tool_call["arguments"])   # you execute it

# 3) You hand the result BACK to the model for the next step:
print("tool result:", result)
# Output: tool result: It is 21C and sunny in Paris.
# 🎯 YOUR TURN — replace each ___ using the hint beside it.
import ast
import re

def add(a, b):
    return a + b

def word_count(text):
    return len(text.split())

TOOLS = {"add": add, "word_count": word_count}

SCRIPTED_MODEL = [
    'ACTION: add(2, 3)',
    'ACTION: word_count("the quick brown fox")',
    'FINAL: 5 and 4',
]

def parse(line):
    # 1) Anchored at the start: a line that merely mentions ACTION is not one.
    m = re.___(r'ACTION: (\w+)\((.*)\)$', line)     # 👉 replace ___ with match
    if not m:
        return None
    name = m.group(1)
    raw_args = m.group(2)
    # 2) literal_eval reads numbers, strings and lists — and NOTHING else.
    #    eval() here would let the model run any Python it liked.
    args = [ast.___(a.strip()) for a in raw_args.split(",")] if raw_args else []   # 👉 replace ___ with literal_eval
    return name, args

transcript = []
for step, line in enumerate(SCRIPTED_MODEL, start=1):
    parsed = parse(line)
    if parsed is None:
        print(f"step {step}: model finished ->", line.removeprefix("FINAL: "))
        break
    name, args = parsed
    # 3) An allow-list of tools. Anything else is refused, not attempted.
    if name ___ TOOLS:                              # 👉 replace ___ with not in
        print(f"step {step}: refused unknown tool {name}")
        continue
    # 4) Call the real function with the arguments the model chose.
    result = TOOLS[name](___args)                   # 👉 replace ___ with *
    shown = ", ".join(repr(a) for a in args)
    print(f"step {step}: {name}({shown}) -> {result}")
    # 5) The observation goes back into the transcript — that feedback is
    #    what makes it an agent rather than a single call.
    transcript.___((name, result))                  # 👉 replace ___ with append

print("Tools called:", [t[0] for t in transcript])
print("Observations fed back:", [t[1] for t in transcript])

# ✅ Expected output:
# step 1: add(2, 3) -> 5
# step 2: word_count('the quick brown fox') -> 4
# step 3: model finished -> 5 and 4
# Tools called: ['add', 'word_count']
# Observations fed back: [5, 4]

4 Memory, reflection, and guardrails

A useful agent needs more than a loop. Three capabilities turn a toy into something dependable:

Memory
• short-term: the running conversation / scratchpad of steps
• long-term: a vector store of past facts and tasks to recall later

Reflection (self-correction)
• the agent critiques its own draft, spots an error, and retries
• "Check your answer against the tool result before finalising."

Guardrails & stopping conditions
• max_steps and a token/dollar budget (no infinite loops)
• an allow-list of tools and arguments (no unsafe actions)
• human confirmation before anything destructive

Together these give an agent persistence (memory), reliability (reflection), and safety (guardrails) — the difference between a demo and something you'd let run unattended.

📋 The agent loop in pseudocode

tools = { describe each tool: name, purpose, arg schema }
memory = []
for step in range(MAX_STEPS):            # stopping condition
    decision = model(goal, memory, tools)  # REASON (may emit a tool call)
    if decision.is_final:
        return decision.answer
    result = run(decision.tool, decision.args)  # ACT (your code runs it)
    memory.append(result)                       # OBSERVE / remember
return "stopped: hit the step limit"     # guardrail

Common Agent Mistakes (and the fix)

⏱ Test Yourself — Timed Quiz

10 quick questions, 12 seconds each. Instant feedback — beat the clock!

🎉 Lesson Complete

Practice quiz

What is the simplest way to describe an LLM agent?

  • An LLM plus tools plus a loop
  • A faster GPU
  • A bigger training dataset
  • A spreadsheet macro

Answer: An LLM plus tools plus a loop. An agent is an LLM given tools and run in a loop so it can decide, act, observe, and continue until the task is done.

In tool (function) calling, who actually runs the tool?

  • Nobody — the call is only logged
  • The language model executes the code itself
  • Your application code runs it and returns the result to the model
  • The user runs it by hand

Answer: Your application code runs it and returns the result to the model. The model only emits a structured request to call a tool; your code executes it and feeds the result back into the conversation.

What does the model emit when it decides to use a tool?

  • A random number
  • A structured call naming the tool and its arguments
  • A compiled binary
  • A new model weight

Answer: A structured call naming the tool and its arguments. Tool calling makes the model output a structured object (tool name plus JSON arguments) that your code can parse and execute.

What do the two parts of the ReAct loop stand for?

  • Retry and Accept
  • Read and Act
  • React and Acquire
  • Reason and Act

Answer: Reason and Act. ReAct interleaves Reasoning (thinking about what to do) and Acting (calling a tool), then observing the result and repeating.

Why give an agent a loop rather than a single model call?

  • So it can act, observe results, and adjust over multiple steps
  • Loops are required by HTTP
  • To use more tokens for billing
  • To slow it down deliberately

Answer: So it can act, observe results, and adjust over multiple steps. Multi-step tasks need the agent to observe each tool result and decide the next action — a loop enables planning and correction.

Which of these is a typical agent tool?

  • The training loss
  • A web search function
  • The model's softmax layer
  • The GPU driver

Answer: A web search function. Tools are external capabilities you expose — web search, code execution, database queries, or third-party APIs.

What role does memory play in an agent?

  • It speeds up matrix multiplication
  • It compresses the model weights
  • It replaces the need for tools
  • It lets the agent recall earlier steps, facts, or past tasks

Answer: It lets the agent recall earlier steps, facts, or past tasks. Memory (conversation history or a vector store) lets the agent carry context across steps and sessions instead of forgetting.

What is reflection (self-correction) in an agent?

  • The agent deletes its tools
  • The agent restarts the GPU
  • The agent reviews its own output and fixes mistakes before continuing
  • The agent copies the user's last message

Answer: The agent reviews its own output and fixes mistakes before continuing. Reflection has the agent critique or verify its own intermediate work, catching errors before they compound.

Why are stopping conditions and guardrails important?

  • They make the model larger
  • They prevent infinite loops, runaway costs, and unsafe actions
  • They improve image quality
  • They are only for training

Answer: They prevent infinite loops, runaway costs, and unsafe actions. Without a max-step limit, budget cap, or action allow-list, an agent can loop forever or take harmful actions.

Which of these is a framework commonly used to build agents?

  • LangChain
  • Photoshop
  • PostgreSQL
  • FFmpeg

Answer: LangChain. LangChain, LlamaIndex, and the native tool-calling APIs from providers like OpenAI and Anthropic are common ways to build agents.

Continue this course

Frequently asked questions

What exactly is an LLM agent?

An agent is a language model wired into a loop with tools. Instead of answering once, the model can decide to call a tool (search the web, run code, query an API), your code executes that tool and returns the result, and the model continues — reasoning, acting, and observing — until the task is complete. In short: agent = LLM + tools + a loop.

How does tool (function) calling actually work?

You describe each tool to the model (its name, what it does, and a JSON schema for its arguments). When the model wants to use one, it does NOT run anything itself — it emits a structured call naming the tool and the arguments. Your application code parses that, runs the real function, and passes the result back into the conversation so the model can use it on the next step.

What is the ReAct loop?

ReAct stands for Reason + Act. The agent alternates between reasoning about what to do next and acting by calling a tool, then observes the tool's result and reasons again. This reason-act-observe cycle, repeated in a loop, is what lets an agent break a hard task into steps and adapt as it learns more.

How do I keep an agent from looping forever or doing something unsafe?

Use guardrails and stopping conditions: cap the maximum number of steps, set a token or dollar budget, restrict which tools and arguments are allowed, require confirmation for destructive actions, and validate every tool result. Reflection (having the agent check its own work) and clear success criteria also help it stop at the right time.