Agents In Production

Too Many Tools, or Tools That Look Alike? Measuring How Agents Pick

0 of 19 complete

0%

Contents

Back|Agents In ProductionToo Many Tools, or Tools That Look Alike? Measuring How Agents Pick
1/19
34 min left
Prerequisites
Tool Calling Is a Contract, and the Model Will Break Itrequired
Related Topics
Evaluating RAG and Agents: One Score Detects, Components LocalizeLLM Evaluation and Error Analysis
1 of 19

A Toolbox With a Hundred Drawers

Picture a new worker at a hardware shop. On day one there are five drawers behind the counter: screws, nails, glue, tape, hooks. A customer asks for glue, and the worker opens the right drawer every time.

A year later the shop has a hundred drawers. Some are labelled almost the same: "wood screws", "metal screws", "screws for plasterboard". Now the worker sometimes opens the wrong one. Is it because there are a hundred drawers? Or because some of them look alike?

A flat illustration of a hardware shop worker reaching into one of a wall of about a hundred small wooden drawers. Underneath: right tool, out of 60 requests, with 5 tools and then 100: llama3.2:3b 60 then 55; qwen2.5:3b 60 then 56. Is it the number of drawers, or the ones that look alike?

An AI agent picks from tools the way that worker picks from drawers. Teams keep adding tools, and many say the agent gets worse at picking as the list grows. Lesson 02 of this chapter drew that as a curve, and was honest that the curve was a pattern teams report, not a measurement. This lesson measures it with two small models, and asks which of the two causes does the damage. The answer surprised me, and it pointed at a third problem nobody draws: the software between the model and your code.

The Words You Need First

Please read this slide slowly if any word is new. Every slide after it uses these words.

A hand-drawn glossary: agent, a program that lets a model take actions; tool, one action with a name, a description and the details it needs; tool call, the model's choice of tool and details; look-alikes, tools with close names and jobs, five to a family; prompt, everything the model reads, with every tool written in; token, a small piece of text. Underneath: more tools means a longer prompt, and often more look-alikes.

Model. Here, a language model: an AI that reads text and writes text, like the one behind ChatGPT.

Agent. A program that lets a model take actions, not just write text.

Tool. One action the program can do for the model, like "get the status of an order". Each tool has a name, a one-line description, and the details it needs, like an order number.

Tool call. The model's reply when it chooses a tool: the tool's name and the details to pass in. The program then runs that tool.

Look-alike tools. Tools with close names and close jobs, like get_order_status and get_order_items. In this lesson, a group of five look-alikes is called a family.

Prompt. Everything the model reads before it replies. Every tool on offer is written into the prompt, so more tools means a longer prompt.

Token. A small piece of text a model reads or writes, roughly three quarters of a word.

JSON. A fixed way to write data so a program can read it. A tool call is written in JSON, for example {"name": "get_order_status", "arguments": {"order_id": "48213"}}.

Ollama. A free tool that runs models on your own machine. Programs talk to it through its chat API, a web address that takes a message and returns the model's reply, including any tool call.

Two Reasons an Agent Could Pick Wrong

When an agent with many tools picks the wrong one, there are two different explanations, and they need different fixes.

1. Too many tools. The list is so long that the model loses track. If this is the cause, the fix is to show fewer tools at once. For example, pick a short list for each request before the model sees it.

2. Tools that look alike. The list may be short, but two tools are so similar that the model mixes them up. If this is the cause, cutting the list does not help much. The fix is to merge the look-alikes, or to rename and describe them so that each one is clearly different.

A test that only grows the list cannot tell these apart, because a longer list usually also holds more look-alikes. So this lab tests both on their own.

Three hand-drawn boxes. Too many tools: show fewer at once. Tools that look alike: merge or rename them. The lab tests each one on its own. Underneath: a longer list usually also holds more look-alikes, so growing the list alone cannot tell the two apart; only the cause tells you which fix to build.

The picture sums up the slide: two causes, two different fixes, and a test that has to pull them apart.

How the Lab Was Built

A flowchart. 60 requests, one right tool each, go to two kinds of list: 5, 10, 25, 50 and 100 tools, and 10 tools with 4 look-alikes. Each ends at a diamond: right tool called? Underneath: each bigger list contains the whole smaller one, the right tool is always there, and a program reads which tool was called, with no AI grading.

The flowchart shows the plan. Here is each part in detail.

  1. The tools. A catalogue of 100 tools, written for this lab, in 20 families of 5 look-alikes: orders, shipping, payments, refunds, accounts, flights, hotels, and so on. They look like the tool list of a real company that several teams have added to.

  2. The requests. 60 requests a user might type, such as "Has order 48213 been shipped yet?". Each one has exactly one right tool in the whole catalogue. I checked each request against its family by hand, and wrote down why no other tool fits.

  3. Growing the list. Every request is sent with 5 tools, then 10, 25, 50 and all 100. The right tool is always there. The others are drawn at random. Each bigger list contains the whole smaller list, so the only change from one size to the next is the tools that were added.

A rough hand-drawn set of five nested boxes: 100 tools, holding 50, holding 25, holding 10, holding the 5 tools with the right one at the centre. Underneath: the right tool sits in the smallest list, so it is in every list; the only change from one size to the next is the tools added.

  1. Look-alikes only. Every request is also sent with 10 tools: the right one, its 4 look-alikes, and 5 random others. Compare that with the random 10: in 44 of the 60 random lists of 10, not one look-alike was drawn.

  2. The mark. A program reads which tool the model called first. Right tool, a look-alike, some other tool, a made-up name, or no tool at all. No AI grades anything.

The Path a Tool Call Takes

An isometric drawing on a grid floor with real product logos. Python agent code offering 5 to 100 tools sends a request and the tools to Ollama. Ollama passes them to qwen2.5:3b, which writes a tool_call. Ollama's parser, which dropped 20 of 360 replies, turns that into a call, and the chosen tool runs if a call arrives.

It helps to see the path a tool call travels, because the lab found trouble at two points on it. The model has to pick the right tool. Then the server's parser has to read the model's reply and turn it into a call your code can run.

A real screenshot of the Ollama documentation page on tool calling. It says Ollama supports tool calling, also known as function calling, which allows a model to invoke tools and incorporate their results into its replies, and shows a curl request to the local chat API with a tools list.

This is the Ollama feature the lab used, described in Ollama's own documentation above.

The Lab, Running

This is a real recording of the lab's report, printed on the laptop where the lab ran, in two parts. In it, n5 to n100 are the random lists of 5 to 100 tools, and near10 is the list of 10 with the 4 look-alikes.

A terminal recording of the command python3 tool_count.py --report --sections 1,2. For each model and each list size, it prints how many requests got the right tool, and what was called instead: a look-alike, another tool, a made-up name, a broken call, or nothing. Then the paired comparisons, and the largest prompt against the limit.

A terminal recording of the command python3 tool_count.py --report --sections 3,4. Section 3 compares qwen2.5:3b's raw replies with what Ollama's chat API returned, and counts dropped calls. Section 4 lists median seconds per reply and prompt tokens for each list, and calls that named the right tool but broke.

The second part shows the parser problem and the cost, both explained on later slides.

Right Tool, as the List Grows

A line chart with one line per model. Across the bottom, the number of tools offered: 5, 10, 25, 50 and 100. Up the side, how many of the 60 requests got the right tool.

tools offeredllama3.2:3bqwen2.5:3b
56060
106059
256060
506059
1005556

Each number is right tools out of 60 requests. Up to 50 tools, both models almost never missed: llama3.2:3b got every request right at every size up to 50, and qwen2.5:3b got 59 or 60. Only at 100 tools did either dip, to 55 and 56. The qwen2.5:3b numbers here come from the raw reading explained later; through the chat API its dip at 100 did not appear.

That is far flatter than the curve lesson 02 of this chapter drew from what teams report. For these two models, on these tools, a long list was not the problem it is often said to be. That may not hold for yours, which is why this lesson ends with how to measure it.

What Went Wrong Instead

When the model did not call the right tool, what did it do? This table sorts every miss into five kinds.

For each model and each list, the number of misses of each kind: a look-alike from the same family, some other tool, a name that was never offered, a call written as broken JSON, or no tool call at all.

At 100 tools, llama3.2:3b missed 5 requests. Look closely and 3 of them were not wrong choices at all: more on that on the next slide. The others were 1 look-alike and 1 other tool.

qwen2.5:3b missed 4: 2 look-alikes, 1 other tool and 1 name that was never offered. Both models, at 100 tools, called get_exchange_rate when the user wanted convert_currency: a real look-alike pair, since both involve exchange rates.

Two panels, one per model, for 100 tools. llama3.2:3b: 5 misses, 3 of them named the right tool in broken JSON; look-alike 1, other tool 1. qwen2.5:3b: 4 misses, including 1 name that was never offered; look-alike 2, other tool 1.

Side by side, the two models failed in different ways. Most of llama3.2:3b's misses were not choices at all.

Right Choice, Broken Writing

Here is one of llama3.2:3b's misses at 100 tools, exactly as it wrote it:

{"name":"track_parcel",""parameters":{"tracking_number":"BD8812345"}}

The tool is right: the user wanted to track a parcel. But there is a stray quote mark before parameters, so it is not valid JSON, and no program can read it. 3 of its 5 misses at 100 tools were like this: the right tool, written wrongly.

That is a different failure from picking the wrong tool, and it needs a different fix. A long prompt seems to have made the small model's writing sloppier, not its choice. A server that enforces the tool-call format, the way lesson 104 enforced a JSON answer, is built to stop exactly this. This lab did not test that.

All 3 of these came at 100 tools and at no smaller size. So a long list may harm the writing even when it does not harm the choice.

A figure-kit page. What it wrote: track_parcel, the right tool, with an extra quote mark before parameters. Valid JSON would read the same with one quote mark fewer. Underneath: 3 of its misses at 100 tools were like this, right choice and unreadable call.

One stray character is the whole difference between a working call and a failed request.

The Calls That Vanished on the Way Back

qwen2.5:3b writes a tool call wrapped in its own markers, <tool_call> and </tool_call>. Ollama has a parser, code that reads the model's reply and pulls the tool call out of it, and hands that back to your program. Sometimes nothing came back.

On 20 of the 360 chat replies from qwen2.5:3b, the chat API returned no text and no tool call. Yet the model had written 22 to 30 tokens each time, about the size of one tool call. Something was written, and nothing arrived.

To see what the model had meant, the lab ran each prompt a second time without the chat API. It read the raw reply, the model's text exactly as written, with its own simple parser. Where the chat run did return a call, the second run picked the same tool 336 of 339 times, so the second run is a close stand-in. In that second run, every one of the 20 empty replies held a valid tool call.

That changes the story. Through the chat API, qwen2.5:3b looked worst at 25 tools, 53 of 60. The drops came at every size up to 50, not just with long lists. Read raw, the same prompts gave 60 of 60 at 25 tools. A team looking only at the chat API could blame the tool list for a parser problem.

A sequence diagram with four lifelines: agent code, Ollama, the model and the parser inside Ollama. Step 1, the agent sends the request and tool list. Step 2, the model writes a tool call. Step 3, the parser finds no call. Step 4, Ollama returns an empty reply. Underneath: the model wrote 22 to 30 tokens each time, and the agent got nothing back.

A hand-drawn Excalidraw sketch with real Python and Ollama logos. A request goes to agent code offering 5 to 100 tools, then to Ollama. Four outcomes: wrong choice, 2 and 4 at 100 tools; right tool with broken JSON, 3 of llama's 5 misses; call dropped by the parser, 20 of 360 qwen replies; and right tool runs, 59 or 60 of 60 up to 50 tools. Red notes: only the wrong choice is about the tool list, and for the dropped calls the model wrote a call but nothing came back. Takeaway: read the raw replies before you blame the tool list.

Put together, three different failures can all look like "the agent picked the wrong tool" from outside. Only the wrong choices are clearly about which tools you offer. The broken JSON appeared only at 100 tools, so a long list may cause that too.

Is It the Count, or the Look-Alikes?

Here is the test that separates the two causes. Both lists below hold 10 tools. One is random. The other holds the right tool's 4 look-alikes.

A bar chart of right tools out of 60 for three lists, per model: 10 random tools, 10 tools with 4 look-alikes, and 50 random tools.

With 4 look-alikes packed into a list of 10, llama3.2:3b got 60 and qwen2.5:3b got 59, the same as with 10 random tools, 60 and 59. Look-alikes on their own did no harm here.

They did show up at 100 tools, where 3 of the misses were a look-alike. So look-alikes may matter more once the list is also long, but with 60 requests that is a hint, not a finding.

Is the Difference Real?

Every list was tried on the same 60 requests. So we can compare two lists request by request, and look only at the requests where they disagree: right with one list, wrong with the other.

For each model, two comparisons: 5 tools against 100 tools, and 10 random tools against 10 tools with look-alikes. For each, the requests right only with the first list, only with the second, and how likely a split like that is by luck.

5 tools against 100: llama3.2:3b was right only with 5 tools on 5 requests, and only with 100 on 0. A split like that happens by luck about 6 times in 100. For qwen2.5:3b it was 4 to 0, which happens by luck about 13 times in 100. Neither passes the usual bar of less than once in 20, so with 60 requests the dip at 100 tools is a hint, not proof.

10 random tools against 10 with look-alikes: 0 to 0 for llama3.2:3b, 1 to 1 for qwen2.5:3b. No difference at all.

Think of each request where two lists disagree as a coin flip. If the two lists were equally good, each would win about half of those flips. The "by luck" numbers say how rarely a split at least this uneven would happen if they were equally good.

Every Tool Costs Tokens, Every Time

A table of the average prompt size, in tokens, for 5, 10, 25, 50 and 100 tools, for each model.

Every tool on offer is written into the prompt, on every single request, whether the model uses it or not.

On llama3.2:3b, the prompt grew from 428 tokens with 5 tools to 5,862 with all 100. On this laptop, the median reply time grew from 2.7 seconds to 35.5: about 13 times slower, to pick the same tool.

The median is the middle reply when all replies are sorted by speed. That cost is certain, and it lands on every request. The accuracy cost was small and uncertain. For these models the strongest reason to show fewer tools was speed and tokens, which cost money on a paid API, not accuracy.

Every Tool Slows Every Reply

A line chart of median seconds per reply on one laptop against tools offered, one line per model. Both climb steadily from about 3 seconds at 5 tools to about 35 at 100. Underneath: llama3.2:3b took 2.7 seconds with 5 tools and 35.5 with 100; the accuracy barely moved and the wait grew about 13 times.

Four isometric cylinders drawn to scale, the average prompt tokens for llama3.2:3b: 428 with 5 tools, 1,576 with 25, 3,000 with 50, and 5,862 with 100. Underneath: every tool on offer is written into every prompt, used or not.

The two pictures tell the same story. The prompt grows with every tool, and the time to answer grows with it.

One Common Fix for Speed

A block diagram with real Python and Ollama logos. A request, where all 100 tools exist, goes to a short-list step that keeps a few that fit, then to the model, which sees only those. Underneath: this lab did not test a short-list step; it measured the reason to want one, since every tool offered cost time on every reply.

A common fix is a short-list step: a quick search that picks a handful of tools that fit the request, before the model sees any. This lab did not test one, so it cannot say how well it works. It only measured the reason to want it.

Compare Two Lists Yourself

This box holds the real results for all 60 requests on llama3.2:3b. For each list, one character per request: 1 if the model called the right tool, 0 if not. Press Run to count them and compare two lists request by request.

Then change A and B, for example to "n10" and "near10".

What This Lab Cannot Tell You

Two columns. What the lab shows: how often two small models called the right tool from 5 to 100 tools, whether look-alikes or the count did more harm, and what each extra tool cost in prompt size. What it cannot show: big models from API companies, your own tool names and descriptions, requests that need two tools or none, or a second run.

Please keep these limits in mind before you quote any number from this lesson.

Two small models. Big models from companies that sell them over the internet may be better at picking tools, and the curve may look very different for them. Measure the model you run.

My tools, not yours. I wrote these 100 tools. How much your own look-alikes hurt depends on how close your names and descriptions really are.

One tool per request. Every request needed exactly one tool. Real agents also get requests that need two tools in a row, or no tool at all.

One run. Temperature 0 gives nearly the same reply to the same input, so a rerun should give nearly the same numbers. Other requests or other tools could give different ones.

One parser. The dropped calls are Ollama's parser meeting qwen2.5:3b's reply format. Other servers and other model versions may parse the same reply correctly. Check yours.

What to Do on Monday

A hand-drawn list of five steps for anyone adding tools to an agent.

  1. Measure your own curve. Send the same requests with more and more tools, each list containing the last, and count right tools. It takes an afternoon.

  2. Read the raw replies. Count calls that name the right tool but break the JSON, and calls your server returns as empty. Both hide inside "picked wrong".

  3. Test look-alikes on their own. A short list with the look-alikes, against a short list without. If look-alikes hurt, rename them or merge them.

  4. Show fewer tools for speed. Even when accuracy holds, every tool costs time and tokens on every request. Pick a short list per request.

  5. Force the format where you can. Where your server can enforce the tool-call format, turn it on, then check that broken calls actually stop.

A take-away card titled speed paid, not accuracy. In large type: 13x slower, llama3.2:3b with 100 tools against 5, to pick the right tool nearly as often. Underneath: show fewer tools for speed; read the raw replies for accuracy.

That is the lesson in one line. The long tool list cost time on every request; the accuracy problems came from how replies were written and read.

Knowledge Check

Knowledge Check

4 questions - Score 80% to pass

Q1

Your agent picks the wrong tool more often since you grew its list from 10 tools to 60. Why can't you conclude that the number of tools is the cause?

Q2

Why did every bigger list in the lab contain the whole smaller list?

Q3

All 100 tools made a prompt of thousands of tokens. Why did the lab measure the size of every prompt?

Q4

Every tool you add is written into the prompt. What does that cost?

  • The models. Two small models that run on a laptop, llama3.2:3b and qwen2.5:3b, through Ollama, both at temperature 0. At temperature 0 a model always picks its most likely next word, so the same input gets nearly the same reply.

  • One more check. All 100 tools make a long prompt, about 5,868 tokens. A model only reads a fixed amount of text, and anything past that limit is silently cut off, which would look exactly like a model picking badly. The lab's limit was 16,384 tokens, and every prompt was measured to fit.