Practice: Structured outputs and tool calling

Generated by Claude through GigAI 0.1.11.10 on 2026-10-11.

Main tool: Tool use / tool calling · Tool use on the Claude API exposes every piece of the lesson directly (JSON Schema tool definitions, the request and result loop, strict mode, typed outputs and gated actions), so you practise the mechanism itself and not a wrapper around it. · Alternatives: OpenAI function calling with Structured Outputs offers the same loop and strict schemas on another model family; Instructor and Pydantic AI wrap any provider in Pydantic-typed outputs with built-in retries; Vercel AI SDK does the same in TypeScript with Zod; Model Context Protocol standardises how tools are published to many clients instead of defining them per request.

Every step links into the tool's own documentation; links were checked on 2026-10-11 · version 1

Setup (one time)

  • 1. Create an API key, install the official SDK for your language in a fresh virtual environment, and export the key as an environment variable; this needs a small amount of paid API credit but no GPU and no cloud infrastructure.

    Every later step is a request against the Messages API from your laptop. A clean environment keeps the SDK version pinned for the reproduce step later.

    Explained in: Define tools - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: A plain message request with no tools returns a text reply from your terminal.

  • 2. Read where tools run, and write down for client tools, Anthropic-schema tools and server tools who executes the call.

    The whole path depends on knowing which side owns execution, because that side owns validation, side effects and approval.

    Explained in: How tool use works - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: You can say, for each of the three tool kinds, whether your code or the platform runs it.

  • 3. Query the Models API to list the available models and pick one capable model and one small fast model to use throughout.

    You will compare tool-calling behaviour across two models later, and fixing the model ids now keeps your runs comparable.

    Explained in: Models overview - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: Two model ids are stored in a config file that all your scripts read.

Steps

  • 1. Run the first ring of the tutorial: define one tool, send one user message, and print the tool request the model emits.

    This is the smallest possible tool call, and it shows that the model does not execute anything: it only returns a typed request for your code to act on.

    Explained in: Tutorial: Build a tool-using agent - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: The response stops with a tool use stop reason and contains a tool use block with a name, an id and an input object.

  • 2. Write the input schema for a second tool of your own (for example an order lookup) as JSON Schema with typed properties, an enum, descriptions and a required list.

    JSON Schema is the contract between the model and your code: everything the model knows about the arguments comes from this object. Writing one by hand makes the later SDK helpers easy to read.

    Explained in: Define tools - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: The model calls your tool with an input that passes a local JSON Schema validator against the schema you wrote.

  • 3. Run the agentic loop: execute the requested tool in your code, append the tool result to the messages, and call the model again until it stops asking for tools.

    The loop is the core of tool calling, and every agent framework is a wrapper around it. Writing it by hand once shows exactly what goes into the message history.

    Explained in: Tutorial: Build a tool-using agent - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: A question that needs two sequential tool calls ends with a final text answer and an end turn stop reason.

  • 4. Enable programmatic calling on one tool through the allowed callers field, run a request with the code execution tool, and print the caller field of each tool call in the response.

    The caller is part of the object model of a tool call: it tells you whether the model asked directly or from code it wrote. Your handler needs that to decide how to treat the request.

    Explained in: Programmatic tool calling - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: Your log shows at least one tool call whose caller is the code execution container and not the model directly.

  • 5. Rewrite the descriptions of both tools following the best practices, then run a set of ten ambiguous prompts before and after the rewrite.

    The description is the main lever on whether a model picks the right tool with the right arguments. Measuring before and after turns tool design into something you can test.

    Explained in: Define tools - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: A small table shows the count of correct tool choices for the old and the new descriptions over the same ten prompts.

  • 6. Enable strict mode on your tools and rerun a prompt that previously produced a missing or wrongly typed argument.

    Strict mode uses constrained decoding so that tool inputs always match the schema, which removes a whole class of parsing failures. It also restricts which schema features you may use.

    Explained in: Strict tool use - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: Fifty consecutive tool calls validate against the schema with zero failures, and you have noted one schema feature that strict mode rejected.

  • 7. Write a Pydantic model for an extraction task and run it through structured outputs using the SDK parse helper, then read back a typed object.

    Typed outputs let downstream code consume a model reply without parsing free text. Seeing how the SDK turns the model class into a schema shows what the validation really covers.

    Explained in: Structured outputs - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: Your script prints a validated Python object with typed fields, and a refusal or a token limit cutoff is reported as a handled case and not a crash.

  • 8. Write a tool handler that returns failures as error tool results, and add a counter that stops the loop after three failed attempts for the same call.

    Returning the error lets the model correct its own arguments, but an unbounded retry burns tokens and can loop forever. A fixed cap is the validation and bounded retry pattern in its simplest form.

    Explained in: Handle tool calls - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: A tool that always fails makes the run stop after three attempts with a clear message, and a tool that fails once succeeds on the second attempt.

  • 9. Compare the two models you picked: run the same tools and the same prompt set on each and save tool choice, argument validity, latency and token usage to a results file.

    Model choice changes tool-calling quality and cost, and a saved results file is what lets you defend that choice to a customer. It also becomes the baseline for regression checks.

    Explained in: Models overview - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: A saved file holds one row per prompt and model, and you can state which model you would ship and why.

  • 10. Configure forced tool use for the extraction call and write a test that runs your saved prompt set with pinned model id, pinned SDK version and fixed schemas.

    Forcing a specific tool removes one source of variation, which makes a tool-calling test stable enough to run on every commit. The pinned environment makes a failure reproducible by a teammate.

    Explained in: Define tools - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: The test suite passes twice in a row from a clean checkout, and fails when you deliberately break a schema.

  • 11. Compare time-based retention with compaction as a decision: run a long tool loop with the memory tool, expire memory files by age in one run and rely on compaction of the conversation in another, then record what the model could still recall.

    Expiring by age drops old tool results whether or not they still matter, while compaction keeps a summary but loses detail. Knowing which facts must be written to memory before either happens is a design decision you will make on every long-running agent.

    Explained in: Memory tool - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: A short note states which data you expire by age, which you leave to compaction and which you persist to memory, backed by the two runs.

  • 12. Deploy a production-like setup in a local container: run the browser toolset with consequential members gated behind a human approval prompt, and make your own write tool idempotent with a request key so a retried call does not act twice.

    Tools with side effects are where tool calling gets dangerous: a retried or mistaken call can submit, pay or delete. Gating consequential actions and making writes idempotent are the controls a customer will ask about first.

    Explained in: Browser and computer use with the SDK toolsets - Claude Platform Docs (platform.claude.com), checked 2026-10-11

    Done when: A consequential action waits for your approval and is skipped when you decline, and replaying the same write call twice produces exactly one effect.