Always free. For everyone.
Course outline
Module 11 of 20 · Reliable automation

Control tool use and agent loops

Validate tool proposals and bound the work an AI agent can request. This module has 3 lessons and takes about 1h 50m. Each lesson has a practice exercise that runs real Python in your browser and a short quiz.

Start module 11 in the Learning Lab
LESSON 1 OF 3

Allow only named tools

25 minAI automation
WHAT YOU WILL DO

Return allowed for lookup_hours or create_draft, and denied for every other tool name.

A model can propose a tool call, but application code decides whether to execute it. A fixed allowlist keeps the available actions visible.

This example permits lookup_hours and create_draft. Every other name is denied. Never evaluate an arbitrary function name or generated code from a model.

Tool permissions must come from application policy, not from a statement in the model output.

See it in action

example.pyPython 3
def solve(tool_name):
    return "allowed" if tool_name in ("lookup_hours", "create_draft") else "denied"
print(solve("lookup_hours"))
Keep this in mind

Tool permissions must come from application policy, not from a statement in the model output.

LESSON 2 OF 3

Bound the agent loop

25 minAI automation
WHAT YOU WILL DO

For non-negative step counts, return finished when done, continue below the step limit, and stop at limit otherwise.

An agent may alternate between model responses and tool results. Each step can cost time or money. Set a maximum number of steps before starting.

Given a completed-step count and a limit, allow another step only while completed is less than limit. A completed result stops immediately, even if budget remains.

A limit prevents unbounded work but does not make individual tool calls safe. Validate every call separately.

See it in action

example.pyPython 3
def solve(completed, limit, done):
    if done:
        return "finished"
    return "continue" if completed < limit else "stop at limit"
print(solve(0, 3, False))
Keep this in mind

A limit prevents unbounded work but does not make individual tool calls safe. Validate every call separately.

LESSON 3 OF 3

Practical: Build a restricted tool dispatcher

60 minAI automation
WHAT YOU WILL DO

Implement the two simulated tools with exact argument checks. Return {"status":"denied"} for all other proposals.

A dispatcher maps approved tool names to known code. The simulation can read workshop hours or create a local draft result. It sends nothing.

lookup_hours accepts no arguments. create_draft requires exactly one non-empty string text field. Invalid arguments or names return denied.

A real dispatcher also checks user permissions, timeouts, output shape, and durable action records. An allowlist is a starting point.

GUIDED PRACTICAL · 60 MIN

Your experiment plan

Use the browser editor or the notebook. All records and AI responses are fictional. No network calls, credentials, or real messages are used.

  1. Draw the model proposal, validation, dispatcher, and result steps.
  2. Run the example and predict its result before changing it.
  3. Complete the function in Practice and run the checks. Add your own normal, empty, and failure cases.
  4. Test an unknown tool, blank text, and an extra argument.
  5. Save the notebook with your observations and explain one limitation of the simulation.

What to hand in

  • A restricted dispatcher and a denied-call test table.
  • A test table with inputs, expected outputs, actual outputs, and one revision.
Reflect on your results

Which tool would need a separate human approval?

The automatic exercise checks the core code behaviour. Review observations and written deliverables yourself or with a mentor.

See it in action

example.pyPython 3
def solve(name, args):
    if not isinstance(args, dict):
        return {"status":"denied"}
    if name == "lookup_hours" and not args:
        return {"hours":"09:00 to 17:00"}
    if name == "create_draft" and set(args) == {"text"} and isinstance(args["text"], str) and args["text"].strip():
        return {"status":"draft", "text":args["text"]}
    return {"status":"denied"}
print(solve("lookup_hours", {}))
Keep this in mind

A real dispatcher also checks user permissions, timeouts, output shape, and durable action records. An allowlist is a starting point.

ABOUT THE LEARNING LAB

Free, open and run by a nonprofit.

This page is part of AI Automation, a free course of 20 modules and 60 lessons in the engineering.fit( ) Learning Lab. The Learning Lab is built and run by engineering.fit( ), a nonprofit founded by Abdullateef Opeyemi Bakare that helps African engineering students gain research experience. You do not need an account or pay a fee to learn.

Course outline · Project lab · Visit engineering-fit.org