Session 5· 16· 25 min

Errors, Refusals & Mini Assistant

What you'll learn
  • Handle tool execution errors gracefully
  • Detect model refusals inside a tool-using conversation
  • Put it all together in a complete mini assistant

The Phase 2 capstone. Combine: tool definitions, a generic router, a loop, parallel handling, error catching, and refusal detection. This is the closest thing to a real production agent you have built so far.

16_tool_errors_refusal_final_mini_assistant.py
def call_tool_safe(name, args):
    try:                                                        ①
        return route(name, args)
    except Exception as e:
        return {"error": str(e)}                                 ②

for _ in range(MAX_ITERS):                                      ③
    response = client.chat.completions.create(...)
    msg = response.choices[0].message
    messages.append(msg)

    if msg.refusal:                                              ④
        print("Refusal:", msg.refusal); break
    if not msg.tool_calls:
        print(msg.content); break

    for call in msg.tool_calls:
        result = call_tool_safe(call.function.name, json.loads(call.function.arguments))
        messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
Wrap the tool call in try/except. Errors are normal — log them and send to the model as an error result.
Return the error as a tool result so the model can apologise or retry.
Capped loop — NEVER use while True in production.
Refusal check happens first. If set, stop the loop immediately.
$ python 16_tool_errors_refusal_final_mini_assistant.py
Phase 2 complete
You can now define tools, execute them in a loop, handle parallel calls, handle errors, and handle refusals. This is the full tool-calling skill set. Phase 3 revisits structured output with the modern Pydantic-based parse methods.
Knowledge Check
When a tool raises an exception, what should you do?
Recap — what you just learned
  • Wrap tool calls in try/except — return errors as results, not exceptions
  • Always cap iterations (MAX_ITERS) in production
  • Check msg.refusal before tool_calls/content
  • This is the pattern every real agent uses
Next up: 17 — Parse Calendar Event