Lesson 4. Tools

For an LLM to call a tool, a contract is needed: name, description, and parameters. The model reads the list of tools in the prompt and responds with a JSON call, and the Harness from lesson 3 executes it.

What to read

  • [Calling tools] — how the model turns a decision into a call
  • [Five categories of tools] — what kinds of tools there are in general
  • [MCP protocol] — standard for connecting tools (in our course — simple local functions; MCP is a topic for a separate guide)

In the code

Tool spec for the system prompt:

python
TOOLS_SPEC = """
- calc(expr: string) — calculates an arithmetic expression, e.g. "123*45"
- time() — current time and date
"""

The tools themselves:

python
import datetime

def calc(expr):
    # eval cannot import inside __builtins__ — the first safeguard
    return eval(expr, {"__builtins__": {}}, {})

def time():
    return datetime.datetime.now().strftime("%H:%M %d.%m.%Y")
js
const TOOLS = {
  calc: (args) => Function('"use strict"; return (' + args.expr + ')'),
  time: () => new Date().toLocaleString("ru-RU"),
};

JSON call that we expect from the model (exactly what parse_tool from lesson 2 parses):

json
{"tool": "calc", "args": {"expr": "123*45"}}

Try calc("abs(-3)") — it will fall over with an error because abs is not available. This is not a bug, but a safeguard: the tool can do exactly what it was allowed to.

Practice

Add a third tool for your agent — for example, dice(sides) or flip(). Write its spec (what it does, what parameters it takes) and implementation in Python and JS. Manually check the call and JSON response.

Related: [Lesson 3. Harness and safeguards], [Lesson 5. Assembling a CLI agent]