Building AI Agents from Scratch

Multiple Tools and Tool Selection

Give the agent several tools and see how names and descriptions drive which one it picks.

Selection is not a classifier you train. It is the model reading names and descriptions. Bad copy makes it call the wrong function.

Two jobs, two tools

Keep list_dir. Add a fetch that only allows one host:

import json
import urllib.request

ALLOWED = "https://httpbin.org/get"


def http_get() -> dict:
    req = urllib.request.Request(
        ALLOWED,
        headers={"User-Agent": "geek-university-agents/1.0"},
    )
    with urllib.request.urlopen(req, timeout=10) as resp:
        body = resp.read(2000).decode("utf-8", errors="replace")
    return {"ok": True, "status": resp.status, "preview": body[:500]}


REGISTRY = {"list_dir": list_dir, "http_get": http_get}

The advertised description for http_get should say “GET the lesson echo endpoint. Use when the user asks you to call the demo HTTP API. Do not use this for local files.” Negative instructions matter.

Why the model picks wrong

  • Two tools that both say “get data.”
  • A catch-all run_command sitting next to a precise tool.
  • Parameters the model must invent (url) when you should have hard-coded the host.

Check it

  1. “List the files here” → only list_dir in the log.
  2. “Hit the demo HTTP endpoint” → only http_get.
  3. Rename http_get to fetch with a vague description and watch the disk question start calling it. Then put the good name back.

Print each call.function.name as you dispatch. That log is how you debug selection. Next: combine the pieces into one practical job.