← all notes

AI agents: a language model with tools and a loop

What turns a chatbot into an agent, and the ReAct pattern that lets it decide which tool to use, from my master's thesis.

agentsLLMsLumen

A language model on its own is a closed box. It can reason about text, but it can’t look anything up, can’t do reliable arithmetic and can’t act in the world. An AI agent gives it tools and a loop: the model decides what to do, a tool does it, the model reads the result and decides again, until it’s done. This is the core of Lumen, the agent I built for my master’s thesis.

Three parts

The orchestration loop asks the model what to do next, runs the tool it picked, and feeds the result back, until the model gives a final answer.
  • The model is the brain: it reads the question and everything so far, and writes down the next step. For an agent it matters less how eloquent the model is and more how reliably it follows a format, so instruction-tuned models fit best. Lumen uses Solar 10.7B Instruct, run on my own GPU (how such a model even knows word order is its own note).
  • The tools are how it reaches outside itself. They come in three kinds: extensions that call outside services through an API (Lumen’s email), functions that run code in the system itself (its Python interpreter) and data stores the agent can search, usually through RAG (how that works). Each tool is described to the model in words: its name, what it does and what input it expects.
  • The orchestration is the loop around them. It keeps the conversation and the steps taken so far, sends them to the model, runs whichever tool the model asks for, and repeats until the model says it has the answer.

The ReAct pattern

How does the model “ask for a tool”? It writes text in an agreed format, and the loop reads it. The most common format is ReAct (reasoning + acting), with these fields:

  • Thought: the model thinks out loud about what to do next.
  • Action: the tool it picks.
  • Action Input: what to send to that tool.
  • Observation: what the tool returned. The loop writes this, not the model.
  • Final Answer: what the user gets, once the model decides it knows enough.

Thought, Action, Action Input and Observation repeat as many times as needed. Here’s a real trace from Lumen, asked for a random number:

Lumen's trace, from the thesis. The first attempt fails, and the error message itself tells the model what to fix.

The first attempt fails with NameError: name 'random' is not defined, and that’s the interesting part: the error comes back as an observation, the model reads it, imports the module and tries again. Nobody programmed that recovery. The loop just keeps showing the model what happened.

Why bother with tools

Language models are famously unreliable at arithmetic, because they predict text rather than calculate. Asked for 321413², Lumen didn’t guess: it ran print(321413**2) and reported 103306316569. In the same way, the web search tool gives it today’s weather instead of whatever its training data said, and the image tool lets it draw.

Risks

Tools make mistakes more expensive. A hallucinating chatbot writes something wrong; a hallucinating agent can do something wrong, like send an email or run code. A Python tool in particular can run anything on the server, so in production it belongs in an isolated sandbox with filtered input, or should be swapped for a narrower calculator tool. And every extra tool makes the choice harder: the more tools a small model sees, the more often it picks the wrong one. Lumen kept to four.