← chapter

A single-loop agent with tools

Chapter 20 · goal + tools + loop

The hour

The three pieces

Build them once; the frameworks stop being magic.

Tools: capable AND safe

# whitelist operators via the AST — never eval()
_OPS = {ast.Add: operator.add, ast.Mult: operator.mul, ...}

An agent is only as safe as its worst tool.

The loop

for _ in range(max_steps):        # the safety rail
    response = complete(goal, history, tools)
    calls = tool_calls(response)
    if not calls: break            # no calls = the answer
    for c in calls:
        history += run_tool(c)

The step cap turns "got confused" into "got confused, cheaply."

The goal does real work

"Never do math in your head — use the tool."

Models compute confidently and wrongly. Good agent design is good instruction design.

Put it to work — three apps

Same loop; different tools + goal.

Two failure modes

The loop makes agents powerful; logs make them debuggable.

Takeaway

Goal, tools, loop — write them by hand and frameworks read as convenience. Trust comes from safe tools, a step cap, forcing tools, and logging. Next: agents talking to agents.