Lab 06 — Wire a tool the model can call

Scaffold: 3/5. The model has a tool and a backend; you build the loop that runs the tool when it asks.

The scenario

In Lab 03 the model filled in a schema and stopped. Here it goes a step further: given a get_delivery_status tool, it decides on its own to call the tool, waits for a result, and answers from it. That decide-call-read-continue cycle is exactly what a managed agent does under the hood. You build it by hand so the mechanics are not a mystery.

The requirement

What’s provided

Your task

Implement _resolve(response, messages). While the model’s stopReason is tool_use:

  1. Append the assistant message to messages.
  2. For each toolUse block, run _execute_tool(name, input) and build a toolResult that references the block’s toolUseId.
  3. Append those results as a user message.
  4. Call converse again and loop.

When the model stops asking for tools, return its final text. The protocol is strict about the shapes; the docstring spells them out.

Run it

# Prerequisite: Model access enabled for a tool-use-capable model, in your region.
./scripts/deploy.sh
./scripts/test.sh
./scripts/teardown.sh

What success looks like

Before you write the loop, the function raises NotImplementedError. After, “where is my order GB-1001?” returns the delivery status, which only exists in the backend the tool read, and GB-9999 returns a not-found. The third question has nothing to do with orders, and the model answers it straight off, no tool call, which is the other half of the lesson: having a tool does not mean using it. Watch the flow: the model never saw _ORDERS, it asked for the tool and you fed it the answer.

If it fails

Reveal the solution

SRC=solution ./scripts/deploy.sh && ./scripts/test.sh

What you just learned

Next

Lab 07 — Gate ingestion with a data-quality check. You move from serving to the pipeline: raw records land in S3, and you write the check that lets the clean ones through and quarantines the rest before they ever reach a model.