Module 2 · Tools, Knowledge, Memory & Research Design · scripted
Discovering Tools: The Catalog, Not the Toolbox
Search doesn't have to happen to the agent
One small step first, to set up a bigger one. RAG, as we built it, acts on the agent from outside: the librarian stacks the desk before the model speaks. But we already know the other posture — everything can be a tool. So hand the search itself over:
Does the harbor allow night deliveries during the herring season?
Tools: search_knowledge(query, top), read_piece(id).
⟨tool_use⟩
search_knowledge(query = "deliveries outside working hours during
herring season", top = 3)⟨tool_result⟩
1. §142 night deliveries — permitted at Quay 3… 2. §142a herring
season exception — quiet period extends to all quays… 3. §8
definitions.⟨tool_use⟩
read_piece(id = "142a")No — during herring season (weeks 45–2) the quiet period extends to all quays, so night deliveries are suspended. Outside those weeks, Quay 3 allows them.
The toolbox we carry everywhere
Now the setup for the real lesson. Every agent so far received its language the same way: a fixed list of tools, stated up front — and we know, from the economics, exactly what that list costs. Every name, every description, every parameter spec is part of the preamble, reprinted on every single iteration, needed or not:
The price of a large vocabulary
And the pressure this creates is perverse: every new capability makes EVERY conversation more expensive — so we resist adding tools, or we make each tool broader and vaguer to keep the list short.
Read that last line again, because it names a dilemma we've been carrying since the case studies: specific tools are better — easier to reason about, safer, harder to misuse — but specific means many, and many means a preamble nobody can afford. The fixed list forces a choice between a good language and an affordable one.
The catalog
Here is the move that dissolves the dilemma, and you already own every part of it. A tool has a name and a description — text. Text has an address in meaning-space. So: embed the catalog of tools, and give the agent two words instead of seventy-four:
The discovery pair
search_tools(need) "describe what you want to do" —
returns the tools nearest in meaning,
with their descriptions
use(tool, args) call a tool you've discovered
At registry time: each tool's name + description is embedded.
At task time: the agent's stated NEED is embedded, and the
nearest tools come back — exactly RAG, pointed at the language
itself.The drone survey data from the fjord came in — convert it to the
municipality's coordinate system and package it for their portal.
Tools: search_tools(need), use(tool, args).
⟨tool_use⟩
search_tools(need = "convert geospatial data between coordinate
reference systems")⟨tool_result⟩
3 matches:
· reproject_raster(file, from_crs, to_crs) — converts raster
geodata between coordinate reference systems (EPSG codes)
· transform_points(file, from_crs, to_crs) — reprojects vector
point data
· validate_crs(file) — reports the CRS a file actually uses⟨tool_use⟩
use(tool = "validate_crs", args = { file = "survey.tif" })⟨tool_result⟩
EPSG:4326 (WGS 84).⟨tool_use⟩
search_tools(need = "package geodata for a government portal
upload, Norwegian municipality")⟨tool_result⟩
2 matches: · geonorge_package(files, metadata) — bundles geodata
to Geonorge portal standards · zip_files(files) — generic archive.⟨tool_use⟩
use(tool = "reproject_raster", args = { file = "survey.tif",
from_crs = "EPSG:4326", to_crs = "EPSG:25832" })search_tools sits a registry of hundreds — highly specific tools
like geonorge_package, exactly the kind we'd never afford in a
fixed list — and the agent pulled the four it needed by describing
its need. Notice it even discovered a tool it didn't know to want:
validate_crs surfaced as a neighbor, and checking the CRS first
is the correct first move.And watch what happened to the wall: the discovered descriptions enter the conversation only after discovery — paid from the moment of need onward, not from turn zero. The vocabulary arrives the way the JIT lessons taught: connection unlocked tools, errors delivered chapters — and now search finds words. Same principle, third trigger.
What discovery buys
The fixed list vs. the catalog
That last row is the deep one. Recall the coverage law: the promise sets the language, and a big promise seemed to force either a huge preamble or the universal word. The catalog opens a third path — a large language of small words: hundreds of specific, auditable, hard-to-misuse tools, none of them paid for until needed. The agent stops being limited by what fits on the wall:
The dictionary principle
A speaker's vocabulary is not what they hold in mind — it is what they can look up. Don't carry the toolbox. Carry the catalog. The language is as large as the registry, and the wall only ever holds the words in use.
One design consequence turns out to matter more than ever: the search sees only names and descriptions — they are now the tool's address, not just its label. A vague description files the tool in the wrong neighborhood, and it will simply never be found: the lying name, upgraded to a lost tool. Everything the language lessons taught about naming now decides discoverability too.
- In Example 2, what would happen if
geonorge_packagewere described only as "packages files"? Where would it live in the space — and what generic tool would the agent wrongly use instead? - Your agent's dream registry: name five highly specific tools you'd build if adding a tool were free. What stopped you before?
Searching everything
Step back and see how wide this pattern just became. Knowledge, searchable by meaning. Tools, searchable by meaning. And from the memory lesson — the journal comes back the same way. In fact anything the system has ever produced can be embedded and addressed:
Make a figure like that calibration-drift one you did for me a
while back, but for the Q3 data. Tools: search_artifacts( query), search_memory(query), read_artifact(id), plotting
tools via search_tools(need).
⟨tool_use⟩
search_artifacts(query = "calibration drift figure, sensors over
time")⟨tool_result⟩
1. fig-2211 "Sensor calibration drift, Q2" (plot spec + caption,
conversation of 2026-05-14) · 2. fig-1877 "Drift table"…⟨tool_use⟩
search_memory(query = "user preferences for figures and reports")⟨tool_result⟩
"Reports: max one page, findings first." · "Figures: colorblind-
safe palette; the user presents on projectors — thick lines."⟨tool_use⟩
read_artifact(id = "fig-2211")Recreating the Q2 drift figure's design for Q3: same axes and layout, colorblind-safe palette, thick lines. [proceeds]
The addressable world
knowledge what the world wrote → searchable tools what the agent can DO → searchable memories what the agent learned → searchable artifacts what the agent has MADE → searchable One space, one mechanism. The agent's whole world becomes addressable by meaning — and the wall carries only what the current step is using.
This is the completion of a long arc: the wall has edges, and we have spent lesson after lesson deciding what deserves to be inside them. The answer has now fully inverted from where we began. Almost nothing lives on the wall. Everything lives in spaces the agent can search — and the craft is in the addresses.
Design the registry for an agent in your domain that you previously would have given 10 broad tools. (1) Explode it: 40+ specific tools, each with a one-line description written to be found — test each by writing the need-query that should retrieve it. (2) Find the collision: two tools whose descriptions land too close, and rewrite them apart. (3) Trace one full task through search_tools/use: what does the wall hold at each step, and what would the fixed-list version have paid by the same point?