How an AI agent works: a language model in a loop with tools
The reasoning – tool call – result loop on a real task over the articles of this website, three approaches and their cost in tokens, why the context grows, plan and memory, the reliability of long tasks with and without checking, and why an agent needs approval.
Series AI basics Part 50 of 52
- Map of artificial intelligence: what is what and how it all fits together
- A brief history of artificial intelligence: from Turing to language models
- Data, model, training, inference: the basic terms on a single example
- How to read mathematical notation: symbols, indices, sums and quantifiers
- Sets and relations: the building blocks of definitions in AI
- Functions and mappings: why every AI model is a function
- Logic and proofs: the rules AI reasons by
- Graphs and trees: the structure that both search and neural networks stand on
- Linear algebra for machine learning: vectors, matrices and why AI mostly multiplies
- Derivatives, the gradient and the chain rule: how a model finds out which way to learn
- Gradient descent: how a model learns
- What probability is: from rolling dice to the Kolmogorov axioms
- Conditional probability and Bayes’ theorem: how to update your estimate when you learn something new
- Random variables and the cumulative distribution function: one function that tells you everything about a distribution
- Probability density and probability mass functions: why a continuous variable has zero probability at a point
- Expected value, variance and covariance: where a distribution lies, how wide it is and what goes with what
- Overview of probability distributions: Bernoulli, binomial, Poisson, uniform, normal and exponential
- Law of large numbers and central limit theorem: why averages behave so predictably
- Statistics and parameter estimation: maximum likelihood, MAP and confidence intervals
- Information theory: entropy, cross-entropy and KL divergence — where loss functions come from
- State-space search: BFS, DFS, UCS and A* with animations
- Games and adversaries: minimax, alpha-beta pruning and Monte Carlo tree search
- Constraint satisfaction: backtracking, constraint propagation and AC-3 on sudoku and a map of Czech regions
- Logic and knowledge systems: forward and backward chaining, resolution and expert systems
- Planning: STRIPS, the blocks world, heuristics from relaxation and planning in AI agents
- Local search and simulated annealing: a travelling salesman through the Czech regional capitals
- Genetic algorithms: population, crossover, mutation and selection on a backpack for a hike
- Evolution strategies and genetic programming: from the one-fifth rule to Kepler’s law
- Ant colony optimization: how a pheromone trail finds a short path
- Particle swarm optimisation: inertia, personal experience and the swarm’s experience
- Neuroevolution: evolving the weights and shape of neural networks, and the NEAT algorithm
- Fuzzy sets and membership functions: how to write down “somewhat warm”
- Fuzzy logic and probability: why “somewhat warm” does not mean “probably warm”
- Fuzzy logic: t-norms, implications and IF–THEN rules
- Fuzzy control: Mamdani and Sugeno from a fan to a pole on a cart
- Fuzzy clustering: the fuzzy c-means algorithm and points between clusters
- Neuro-fuzzy systems (ANFIS): fuzzy rules that learn from data
- Markov chains: the transition matrix, the stationary distribution and PageRank
- Hidden Markov models: the Viterbi algorithm and the dishonest casino
- Bayesian networks: why the grass is wet and what it means for the sprinkler
- The Kalman filter: how to estimate where a car is and how fast it goes from imprecise measurements
- Types of machine learning: supervised, unsupervised, semi-supervised and more
- Prompts, context and RAG: how to give a model the right information
- Variational autoencoders (VAE): new images from a continuous latent space
- Generative adversarial networks (GAN): the forger versus the detective
- Diffusion models: how pure noise becomes an image
- Markov decision processes: states, actions, rewards and the Bellman equations
- Q-learning and DQN: learning the value of actions, from a table to a neural network
- Policy gradient and PPO: learning the policy directly
- How an AI agent works: a language model in a loop with tools
- Programming with AI agents: the task, tests and review
- Evaluating and securing AI systems: how to measure and how to keep watch
Full series syllabus 52 of 83 topics published
- What happens inside an agent step by step, and what the model does and what the harness does.
- Why context is expensive and how good agents save it.
- Why long tasks without checking fail and how tests and approval help.
Useful to know first: Prompts, context and RAG: how to give a model the right information, Markov decision processes: states, actions, rewards and the Bellman equations
On its own, a language model only answers: it gets text and returns text. An agent is a model we give hands — tools with which it can find something out or do something — and let work in a loop until it finishes the task. That is how coding agents work, reading code, running tests and fixing bugs on their own, and assistants that search the web. And that is how the agent you control from your phone with coden works. In this part we take the loop apart on a real task and work out what it costs and where it breaks.
It builds on the parts Prompts, context and RAG, Tokenization and Markov decision processes.
1. A model in a loop
Definition — AI agent
In general, an agent is a function that assigns an action to every history of percepts so far (the agent function from the map of AI). An AI agent in the narrower sense of this part is the following specific construction. Let
- T be the set of all texts (finite sequences of tokens) and ⊕ : T × T → T appending text at the end;
- M : T → T be a language model that writes the next step from the context (a model with sampling is in fact random; here we take one fixed run);
- F ⊆ T be the set of steps that are a final answer; the other steps v ∈ T ∖ F are tool calls;
- N : T ∖ F → T be the harness: it actually carries out a tool call and returns its result as text;
- c1 ∈ T be the initial context (the system prompt, the tool descriptions and the task) and Kmax ∈ ℕ, Kmax ≥ 1, the step budget.
A run of the agent is the sequence of contexts c1, c2, … and steps v1, v2, … given for k = 1, 2, …, Kmax by
vk = M(ck), ck+1 = ck ⊕ vk ⊕ N(vk) (if vk ∉ F).
The run stops at the first step k for which vk ∈ F — the output is the answer vk — or after step Kmax if no step was a final answer — the output is “step budget exhausted”.
So the agent alternates a model step and running a tool until the model answers or the budget runs out. Alternating reasoning and acting was described by Shunyu Yao et al. (2022) under the name ReAct (reason + act); the notation above is a simplified formalization for this part.
A clever colleague on the phone who can’t see your computer. They say “open the src folder”, you read out what is in it, they say “now the file server.js, lines 100 to 150” — and so on, until they have the answer. The model is that colleague, the harness is your hands and eyes. In the language of reinforcement learning: the state is the conversation so far, the action is a tool call.
vk = M(ck), ck+1 = ck ⊕ vk ⊕ N(vk)
- ck
- the context before the k-th model call: the system prompt, the task and everything that has happened so far. It is the agent’s whole “state” — the model remembers nothing else
- M
- the language model; from the context it writes the next step. The only part that “thinks”, and the only one that cannot be fully trusted
- vk
- the model’s step: reasoning and a tool call, or the final answer (then the loop ends)
- N(vk)
- the tool result, computed by the harness; it adds to the context what the model cannot know by itself (the contents of a file, the output of tests)
kontext = [system prompt, tool descriptions, task]
for k = 1 … K_max: # step budget
krok = model(kontext) # reads the WHOLE context
kontext += krok
if krok is the final answer: return it
if the tool needs approval and the human did not give it:
kontext += "denied"; continue
výsledek = proveď(krok.nástroj, krok.parametry) # the harness
kontext += výsledek
return "step budget exhausted"
2. Tools
Definition — tool use (function calling)
Let the agent have m ≥ 1 tools. A tool i ∈ {1, …, m} is given by
- a name ji (the names of different tools are different),
- a verbal description of what it is for,
- a parameter schema Si — a description of which parameters of which types the tool accepts (typically as a JSON schema),
- a procedure that the harness runs for valid parameters and that returns the result as text.
The name, description and schema of all tools are put into the prompt. A tool call is a structured output of the model of the form (j, x) — a name and parameters, for example {"nastroj": "hledej", "text": "KL divergence"}. The model is fine-tuned so that it can write such an output instead of ordinary text. The harness handles a call (j, x) as follows:
- if there is an i with j = ji and the parameters x match the schema Si, it runs the procedure of tool i with the parameters x and appends its result to the context as another message;
- otherwise it appends an error message to the context and does not run the tool.
So the model itself runs nothing — it only writes what should be run; the harness runs it (or refuses to).
A menu and an order. The model gets the menu (“these are your tools and this is how you order them”) and writes the order in exactly the form the kitchen understands. The kitchen cooks, not the guest. That is why the kitchen can be told not to serve some dishes without approval.
Our agent works over the texts of 21 older articles of this website (the same ones as in the parts on tokenization and RAG; they are in Czech, so the agent works in Czech) and has three tools. Its whole system prompt has 157 tokens:
Jsi agent, který odpovídá na otázky podle článků webu. Máš nástroje:
- seznam(): Vypíše články a jejich délku ve znacích.
- hledej(text, max): Najde výskyty textu ve všech článcích; vrátí článek, pozici a okolí.
- cti(clanek, od, do): Vrátí úsek článku od pozice do pozice (znaky).
V každém kroku napiš krátkou úvahu a zavolej jeden nástroj, nebo napiš konečnou odpověď s odkazem na článek. Když něco nenajdeš, zkus jiný dotaz.
Real coding agents have similar tools: search in files, read part of a file, edit it, run a command in the terminal. Since 2024, tools can also be connected through the shared MCP protocol (Model Context Protocol), so the same tool — a database, a calendar, a browser — can be used by any agent.
3. One question, three approaches
The question: “Why is KL divergence not a distance? Give an example from the articles.” (in the original: „Proč KL divergence není vzdálenost? Uveď příklad z článků.“). The answer is in the article on information theory: KL divergence is not symmetric, DKL(0.7 ‖ 0.5) = 0.119, but DKL(0.5 ‖ 0.7) = 0.126. We wrote the agent’s steps by hand — we wrote the reasoning and the calls in place of the model. The tools, their results and the tokens are real, though.
Example — why DKL(0.7 ‖ 0.5) ≠ DKL(0.5 ‖ 0.7)
For two yes/no distributions (rain with probability p, the model says q; p, q ∈ (0, 1)), DKL(p ‖ q) = p log2 p/q + (1 − p) log2 1 − p/1 − q bits (information theory).
DKL(0.7 ‖ 0.5) = 0.7 · log2 0.7/0.5 + 0.3 · log2 0.3/0.5 = 0.7 · log2 1.4 + 0.3 · log2 0.6 = 0.340 − 0.221 = 0.119.
DKL(0.5 ‖ 0.7) = 0.5 · log2 5/7 + 0.5 · log2 5/3 = −0.243 + 0.368 = 0.126.
Each time the average is taken over a different distribution (whichever is the reality), so swapping the arguments gives a different number — and a distance (a metric) must be symmetric. This is the answer the agent is looking for.
-
I search for the exact words of the question.
hledej(text: "KL divergence není metrika")nic nenalezeno
+34 tokens, context 209 -
Nothing. I will try just the name of the concept.
hledej(text: "KL divergence")5 výskytů: informace:3258: … minimum je tam, kde model říká pravdu. KL divergence Definice — Kullbackova–Leiblerova diver… informace:3656: …,222 bitu. Podle Gibbsovy nerovnosti je KL divergence vždy nezáporná a nulová jen pro q = p .… informace:3717: …záporná … (310 more characters)
+205 tokens, context 414 -
It is in the article informace. I will read the surroundings.
cti(clanek: "informace", od: 3660, do: 3960)ivergence vždy nezáporná a nulová jen pro q = p . Pozor, KL divergence není vzdálenost: není symetrická. D KL (0,7 ‖ 0,5) = 0,119, ale D KL (0,5 ‖ 0,7) = 0,126. Záleží na tom, co je skutečnost a co model. Informační zisk Definice — podmíněná entropie H ( Y | X … (40 more characters)
+146 tokens, context 560
Three tool calls, and the fourth model call writes the answer. The first search finds nothing — the words of the question are not in the text. The agent sees that and tries a more general query; that is the advantage of a loop over a one-off retrieval. At the end the context has 560 tokens.
-
I don’t know where it is. I will go through the articles one by one.
cti(clanek: "co-je-pravdepodobnost")Jazykový model nevybírá další slovo, ale pravděpodobnosti všech slov. Klasifikátor neříká „je to kočka“, ale „s pravděpodobností 0,93 je to kočka“. Celé strojov … (7,175 more characters)
+1,933 tokens, context 2,108 -
Not here, next article.
cti(clanek: "csp")Rozvrh hodin, ve kterém žádný učitel neučí dvě třídy naráz. Sudoku. Rozmístění součástek na desce, směny v nemocnici, přidělení letadel k branám. Všechny tyhle … (11,914 more characters)
+3,148 tokens, context 5,256 - … 8 more steps of the same kind (context at the end 24,927 tokens)
Without searching, the agent goes through the articles in alphabetical order. It only comes across the answer in article number 10, and by then the context has grown to 24,927 tokens.
And the third approach, one-off RAG from the previous part: retrieve the three most similar chunks and put them into the prompt. All three chunks come from the right article (informace, informace, informace), but none of them contains the example with the numbers 0.119 and 0.126 — the answer would have no example. An agent in a loop can say to itself “this is not enough, I’ll read on”. A one-off retrieval cannot.
4. Context is expensive
Definition — the cost of the loop
The model has no memory between calls; at every call it reads the whole context again — the system prompt, the task and all the steps and tool results so far. Let a run of the agent (definition above) end after K ≥ 1 model calls and for k = 1, …, K let ck ∈ ℕ be the length of the context (the number of tokens) before the k-th call. The cost of the loop is the number of tokens the model processes on input during the run:
Z = ∑k=1K ck.
Because the context grows with every step, Z grows roughly with the square of the number of steps (theorem below).
As if before every sentence of a letter you had to read the whole letter again from the start. A short letter is fine. A long letter into which you have also pasted ten books you have read is expensive — and the important part easily gets lost among all those pages.
The “read everything” approach costs 141,820 processed tokens, “search and read an excerpt” only 1,358 — 104 times fewer, for the same answer. That is why good coding agents search first (grep) and read only pieces of files. And that is why a long session is compacted from time to time: the older part of the conversation is replaced by a summary, so that the context fits and the model doesn’t get lost in it. Caching the beginning of the prompt (prompt caching) also helps: re-reading the same beginning is then billed at a lower price.
Z = ∑k=1K ck, ck = c1 + ∑j<k (vj + oj)
- Z
- the total number of processed tokens — what you pay for and wait for
- K
- the number of model calls (steps with a tool + the final answer); each call reads the context again from the start
- c1
- the system prompt and the task; they are in the context from the first call, so they are paid for K times — which is why it pays to keep them short and cache them
- vj + oj
- the tokens added by step j: the call and the tool result. Step j is read in all later calls, so a long tool result is paid for many times
Theorem — the cost grows with the square of the number of steps
Let K ∈ ℕ, K ≥ 1, be the number of model calls, c1 ≥ 0 the length of the initial context and d ≥ 0 the number of tokens that every step adds (the call and the tool result together), so that ck = c1 + (k − 1) d for k = 1, …, K. Then
Z = K c1 + d · K(K − 1)/2.
Proof: Z = ∑k=1K (c1 + (k − 1) d) = K c1 + d ∑k=1K (k − 1) and ∑k=1K (k − 1) = 0 + 1 + … + (K − 1) = K(K − 1)/2. ∎ For large K the second term ≈ d K²/2 dominates: a session twice as long costs roughly four times as much. (The colours correspond to the terms of the breakdown above: d is the constant value of vj + oj.)
Example — recomputing both approaches
Search and read an excerpt. The system prompt has 157 tokens, the question 18, so c1 = 175. After the three steps the context has 209, 414, 560 tokens. The four model calls read Z = 175 + 209 + 414 + 560 = 1,358 tokens (colours as in the formula above).
Read everything. K = 11 calls, the context grows from 175 to 24,927 tokens, on average by d = 24,927 − 175/10 ≈ 2,475 per step. By the theorem, Z ≈ 11 · 175 + 2,475 · 11 · 10/2 = 138,050; the reality is 141,820 (the articles differ in length, so the steps don’t add exactly the same amount). The system prompt with the question accounts for only 1,925 tokens of that — almost everything is re-reading the articles.
5. Plan and memory
Definition — agent planning and memory
These concepts are not mathematical; they are the roles of parts of an agent run (the definition of an AI agent above, the contexts c1, c2, …, the tools N). One session is one run of the agent from c1 until it stops.
- A plan is text in the context — a numbered list of steps that the agent writes as one of its steps vk at the start of the session and rewrites repeatedly in later steps (ticking off what is done, changing what remains). The model reads it like any other part of the context; nothing enforces it.
- Working memory is the context ck of a single session. It ends with the session and is limited by the context length the model can handle.
- Long-term memory is data stored outside the model and outside the context (files, databases) that outlasts the end of the session. The agent writes to it and reads from it only through tool calls; in the next session it gets into the context only if the agent reads it or the harness puts it into c1.
- A subagent is another agent run that the main agent starts as a tool: the subagent begins with its own initial context (only the description of the subtask), works in its own loop, and only its final answer comes back into the main agent’s context, as the tool result N(vk). The details of its work thus do not fill the main context.
A tradesman on a longer job writes a list on paper and in the evening notes down in a notebook what he found out — in the morning he doesn’t have to remember everything, he just opens the notebook. He sends an apprentice to do the odd jobs and only wants to hear “done, it was over here”.
For coding agents, long-term memory is usually a plain text file in the project (rules, commands, things to watch out for) that the agent reads at the start of every session. It is the simplest and most transparent kind of memory: a person can read it and correct it too.
6. Long tasks and checking
An agent that takes the right step 90% of the time looks reliable. But a task consists of many steps, and an error in any of them spoils it. If a step succeeds with probability p, the whole task of n steps succeeds with probability pn — as long as the agent doesn’t recognize its errors.
Definition — closed loop with feedback
Let p ∈ [0, 1], d ∈ [0, 1], r ∈ ℕ ∪ {0} and n ∈ ℕ, n ≥ 1. A step with checking (a closed loop) goes as follows:
- the agent carries out the step; the attempt succeeds with probability p;
- the agent checks the result (runs the tests, reads the output of a command, compares it with what it expected); the check always accepts a successful attempt and recognizes a failed one as wrong with probability d;
- the attempt succeeded ⇒ the step ends in success;
- the attempt failed, the check recognized it and the agent has so far repeated fewer than r times ⇒ the agent repeats the step from point 1;
- otherwise (the error got past the check, or the repetitions ran out) the step ends in failure.
The outcomes of the individual attempts and checks are mutually independent. The success rate of a step q is the probability that the step ends in success; a task is n such steps in a row, independent, and it succeeds if and only if all of them succeed. Then
q = p ∑k=0r ((1 − p) d)k, P(the task succeeds) = qn.
Term k is the probability that the first k attempts fail and the failure is recognized (each with probability (1 − p) d) and attempt k + 1 succeeds; these possibilities are mutually exclusive, so they add up. Without checking (d = 0 or r = 0), q = p.
Whoever writes a long program without running it almost certainly has a bug in it. Whoever runs the tests after every change finds the bug right away, while it is still small and it is clear where it is. Agents are no different.
q = p ∑k=0r ((1 − p) d)k = p + p (1 − p) d + p ((1 − p) d)² + …
- p
- the attempt succeeds; every term ends with exactly one successful attempt
- 1 − p
- the attempt fails; every failure before the success costs one such factor
- d
- the check recognizes the failure; only then does the agent repeat the step — an unrecognized error slips through and spoils the task
- ∑k=0r, k
- k = how many attempts failed before one worked; at most r repetitions, so that the agent doesn’t keep trying forever
With p = 0.9 and twenty steps, only 12% of tasks succeed without checking, and 79% with checking. A simulation of 20,000 tasks gives 12% and 79%, so the formula fits. Even a very good step (p = 0.99) fails more often than it succeeds over a hundred steps without checking (37%); with checking it succeeds in 90%. This is the main reason coding agents work so well: code can be run and tested, so almost every step gets feedback. The organization METR (2025) measures that the length of tasks agents manage half the time doubles roughly every seven months.
Example — p = 0.9, d = 0.9, r = 2, twenty steps
Success rate of a step (colours as in the formula above): q = 0.9 + 0.9 · 0.1 · 0.9 + 0.9 · (0.1 · 0.9)² = 0.9 + 0.081 + 0.00729 = 0.98829.
The whole task: without checking 0.920 = 0.122, with checking 0.9882920 = 0.790. The step only improved from 90% to 98.8%, but the task from 12% to 79% — the power n inflates small differences in a step.
Definition — the length of task an agent manages half the time
Let q ∈ (0, 1) be the success rate of a step and let a task of n independent steps succeed with probability qn (definition above). The length of task manageable half the time is the real number n50% > 0 for which qn50% = 1/2, that is
n50% = ln 0.5/ln q = ln 2/−ln q ≈ 0.69/1 − q for q close to 1
(the approximate equality follows from −ln q ≈ 1 − q for q → 1). Because qn decreases as n grows, qn ≥ 1/2 holds if and only if n ≤ n50%; the largest whole number of steps the agent manages at least half the time is therefore ⌊n50%⌋.
In our model: p = 0.9 without checking 6.6 steps, with checking 58.8; p = 0.99 without checking 69.0, with checking 686. The task an agent manages half the time grows roughly in proportion to how many times the error rate of a step 1 − q drops.
METR measures the same quantity (the length of task an agent manages in 50% of cases) — only not in steps, but in the time the task would take a human (Thomas Kwa et al., Measuring AI Ability to Complete Long Tasks, 2025). Our formula is a simplified model with independent steps, not their method.
7. Permissions and oversight
An agent that may run commands may also do damage — by mistake (it deletes the wrong folder) or on an instruction it read in someone else’s text (prompt injection). The defence does not rest on the model but on the harness: tools with limited rights, running in an isolated environment, and above all approval — dangerous or irreversible steps are carried out only after a human agrees. coden is built on this too: the agent works on your computer and you approve its steps from your phone.
8. Summary
- Agent = a language model in a loop: reasoning, a tool call, the result into the context, again.
- The model only describes tools with a structured call; they are run by the harness, which can enforce rules.
- A loop can recover from an unsuccessful search — one-off RAG cannot.
- Every call reads the whole context: “read everything” cost 141,820 tokens, “search and read an excerpt” 1,358.
- A plan, notes in files and subagents keep the context small and clear.
- Without checking, the success rate falls with the length of the task as pn; tests and verification change that (20 steps at p = 0.9: 12% → 79%).
Want to get a feel for it? Ask an AI agent to describe every tool call it makes during a task, and at the end to estimate how many tokens the task cost. Then give it the same task with the instruction “search first, read only excerpts”.
Do you see it differently? Write to support@coden-app.com.