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):
- Start
messageswith{"role": "user", "content": user_msg}. - Loop up to
max_stepstimes, callingmodel(messages)once per iteration. - On a
"final"turn, returncontent. - On a
"tools"turn, append the assistant message, then for each call incallslook up the tool, run it withargs, and append a tool-result message{"role": "tool", "name": ..., "content": <output>}for that call. Then continue the loop. - 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 —
modeland the tools are provided.