InterviewPrepKit

Home / Coding / Agent Coding / The Agent Loop / Multiple Tool Calls in One Turn

Multiple Tool Calls in One Turn

medium 00:00
Solving tips
  • A single model turn can request several tools; run them all before you call the model again.
  • Append every tool result to the message list so the next model call sees the full batch.
  • Still cap total steps — a turn that fans out into many tools should count as one step, not many.

Extend the basic agent loop to handle a model turn that asks for several tools at once. Modern models batch independent tool calls into a single turn (fetch three pages, run two queries) so the agent can run them together instead of one round-trip each. Your loop must execute the whole batch before calling the model again.

How the loop works

You keep a running list of messages. Each turn you call model(messages) and it returns one of two things:

  • a final answer{"type": "final", "content": "..."} — stop and return the content.
  • a batch of tool calls{"type": "tools", "calls": [{"name": ..., "args": ...}, ...]} — run every call in the list, in order, appending one tool-result message per call, then loop again.

A turn that fans out into five tools is still one step. Cap the loop at max_steps model calls so a model that never finishes cannot run forever.

Task

Complete run_agent(model, tools, user_msg, max_steps=10):

  1. Start messages with {"role": "user", "content": user_msg}.
  2. Loop up to max_steps times, calling model(messages) once per iteration.
  3. On a "final" turn, return content.
  4. On a "tools" turn, append the assistant message, then for each call in calls look up the tool, run it with args, and append a tool-result message {"role": "tool", "name": ..., "content": <output>} for that call. Then continue the loop.
  5. If the loop runs out of steps, return a clear message like "Stopped: reached max steps.".

Example

def model(messages):
    # (mock) first turn asks for two tools at once, second turn answers
    if not any(m["role"] == "tool" for m in messages):
        return {"type": "tools", "calls": [
            {"name": "add", "args": {"a": 2, "b": 3}},
            {"name": "add", "args": {"a": 10, "b": 20}},
        ]}
    return {"type": "final", "content": "Sums are 5 and 30."}

tools = {"add": lambda args: str(args["a"] + args["b"])}

run_agent(model, tools, "add these pairs")   # -> "Sums are 5 and 30."

Constraints

  • Preserve call order: the tool-result messages must be appended in the same order as calls.
  • Handle an unknown tool name or a tool that raises gracefully — append an error result for that call rather than crashing the whole batch.
  • Do not call any real LLM or network — model and the tools are provided.

Write your solution, then hit Run tests to check it — or get a mock grade from the AI coach.

The coach remembers this session — revise your code and ask again, and it grades your progress. It gives hints, not the answer.
Report a bug