← chapter

Multi-tool calling and tool loops

Chapter 7 · an agent is a while loop with a dispatch dict

The hour

The problem

"Which items under $30 are in stock, and what would one of each cost?"

No single call answers that. Discover first, then price, then filter, then add.

The three moving parts

DISPATCH = {"list_products": list_products,
            "get_product": get_product}
  1. A dispatch dict: tool name → Python function
  2. A conversation you keep appending to
  3. A bounded while loop

The loop (OpenAI)

for _ in range(10):                # the safety rail
    response = client.responses.create(
        model="gpt-5.4-nano",
        input=input_list, tools=TOOLS)
    calls = [i for i in response.output
             if i.type == "function_call"]
    if not calls:
        break                      # no calls = the answer
    input_list += response.output
    for call in calls:
        result = DISPATCH[call.name](
            **json.loads(call.arguments))
        input_list.append({...call_id, output...})

The loop (Gemini)

for _ in range(10):
    response = client.models.generate_content(
        model="gemini-3.1-flash-lite",
        contents=contents, config=CONFIG)
    if not response.function_calls:
        break
    contents.append(response.candidates[0].content)
    # one function_response part per call, batched

Models batch several calls per turn — handle a list.

Errors are data

return {"error": f"no product called {name!r}"}

The model reads it, fixes the name, retries. Raise instead, and a recoverable mistake becomes a 500.

Never ship an open loop

range(10), not while True.

A confused model will request the same tool forever. The cap is the difference between a bad answer and an outage.

Put it to work — three apps

Each one is a docker compose up web app.

Verify side effects from state

The home-automation reply appends a Python-computed before/after diff. Models misreport what they did; the state doesn't.

Takeaway

An agent is a while loop with a dispatch dict. Production-worthy means: bounded, errors-as-data, side effects verified from computed state.