Chapter 47
47 / 50

Advanced Tool Use with the Claude API

⏱️ 40 min

Tool use usually fails for one of three reasons: tool definitions consume the context window, the model sends invalid arguments, or large intermediate results repeatedly pass through the model. Diagnose the failure first, then choose Tool Search, Programmatic Tool Calling, or input_examples. They solve different problems.


Choose the control that matches the failure

SymptomStart withWhyAvoid
The catalogue has 20+ tools but each task uses only a fewTool SearchLoad definitions only when relevantPutting every schema in the system prompt
A task needs loops, filtering, or fan-out callsProgrammatic Tool CallingKeep intermediate data in the execution environmentSending 10,000 raw rows through the model
The right tool is selected but nested or date arguments are wronginput_examplesShow conventions that JSON Schema cannot express wellHiding every edge case in one vague description
There are only a few tools and a short call chainStandard tool useLowest implementation overheadAdding a sandbox only to look advanced

Tool Search reduces the definitions loaded up front. Programmatic calls reduce tool_result round trips. Prompt caching lowers the cost of stable prefixes, while context editing can remove results that no longer help the task.


1. Tool Search: load definitions on demand

Tool Search is useful when the catalogue itself affects baseline context. Marking a tool with defer_loading: true keeps its full definition out of the initial prompt. Claude searches first, then loads matching tools through a tool reference.

import os
from anthropic import Anthropic

client = Anthropic()

tools = [
    {"type": "tool_search_tool_regex_20251119", "name": "tool_search"},
    {
        "name": "get_customer_orders",
        "description": "Return orders for one customer. Use for order history, not account details.",
        "defer_loading": True,
        "input_schema": {
            "type": "object",
            "properties": {"customer_id": {"type": "string"}},
            "required": ["customer_id"],
        },
    },
]

response = client.messages.create(
    model=os.environ["ANTHROPIC_MODEL"],
    max_tokens=1200,
    tools=tools,
    messages=[{"role": "user", "content": "Show the three latest orders for C-1042"}],
)

Acceptance checks

  • Deferred schemas are absent from the initial prompt.
  • Search distinguishes tools with similar names but different responsibilities.
  • Each description says when to use the tool and when not to use it.
  • Traces record search hit rate, added latency, and input tokens.

2. Programmatic Tool Calling: keep batch work in the sandbox

Programmatic Tool Calling lets Claude write code in a Code Execution environment and call authorised tools from that code. It works well for fan-out, aggregation, filtering, and conditional branches because intermediate results do not have to enter the conversation one item at a time.

tools = [
    {"type": "code_execution_20260120", "name": "code_execution"},
    {
        "name": "get_service_health",
        "description": "Return health and latency for one service.",
        "allowed_callers": ["code_execution_20260120"],
        "input_schema": {
            "type": "object",
            "properties": {"service": {"type": "string"}},
            "required": ["service"],
        },
    },
]

For “find every service above 500 ms latency,” the useful data path is:

Claude writes a loop
  → sandbox calls get_service_health concurrently
  → sandbox filters latency_ms > 500
  → only anomalous services enter the model context

Do not use this pattern when every step needs a fresh model judgement. In that case, code execution adds overhead without removing model turns.


3. input_examples: fix valid-looking but wrong arguments

JSON Schema expresses types and required fields, but team conventions are often more specific: timestamps need a business timezone, two optional fields must appear together, or evidence links are mandatory for a high-severity action.

{
    "name": "create_incident",
    "description": "Create an incident after an alert is verified. Do not use for unverified alerts.",
    "input_schema": {
        "type": "object",
        "properties": {
            "service": {"type": "string"},
            "severity": {"type": "string", "enum": ["sev1", "sev2", "sev3"]},
            "started_at": {"type": "string", "description": "ISO 8601 with timezone"},
            "evidence_urls": {"type": "array", "items": {"type": "string"}},
        },
        "required": ["service", "severity", "started_at", "evidence_urls"],
    },
    "input_examples": [{
        "service": "checkout-api",
        "severity": "sev2",
        "started_at": "2026-08-25T09:42:00+10:00",
        "evidence_urls": ["https://monitor.example/incidents/abc"],
    }],
}

Examples consume tokens too. Add them only where argument errors are common. Improve the description first, add an example second, and add prompt rules only when those controls are insufficient.


A rollout that produces evidence

  1. Classify trace failures as wrong tool, invalid arguments, or oversized result.
  2. Change one control for each failure class.
  3. Build an eval set of 30–100 real tasks, including empty results and permission errors.
  4. Compare success rate, input tokens, tool rounds, P95 latency, and total cost.
  5. Roll out gradually and retain standard tool use as a fallback.

Definition of done

  • Tool-selection accuracy has not regressed.
  • Schema validation failures are below the team threshold.
  • Large results are filtered before entering the model.
  • Every claimed saving is backed by traces or billing data.

Common mistakes

MistakeCauseFix
Search cannot find the right toolGeneric name and descriptionState the business object, inclusion rule, and exclusion rule
Deferred tools disrupt cachingUnstable tool arrays or misplaced cache breakpointsKeep a stable prefix and place breakpoints on non-deferred tools
Programmatic output is still hugeCode batches calls but does not filterAggregate in the sandbox and return decision fields only
Examples barely helpThe model is selecting the wrong toolRepair overlapping responsibilities first
Offline eval passes but production regressesThe task set contains only happy pathsSample production traces and cover timeouts, empty results, and access errors

Practice task

For a catalogue of 35 order, customer, refund, inventory, and shipping tools:

  1. Identify the 3–5 tools needed to investigate a delayed order.
  2. Defer the remaining definitions.
  3. Query order and shipping status programmatically.
  4. Add a refund input example with a timezone and evidence link.
  5. Compare the old and new approach on the same 20 tasks.

Self-check

  • I can explain which failure each technique reduces.
  • I have not treated version strings in examples as permanent constants.
  • I record cost, latency, and accuracy separately.
  • I can fall back to standard tool use.

Official references

📚 Related resources

Common questions

Open a question to review the practical answer.

Do these features still require a beta header?

No. Tool Search, Programmatic Tool Calling (PTC), and input_examples are all generally available on the Claude API — a plain messages.create call works. The advanced-tool-use-2025-11-20 header from early coverage is obsolete. Mind platform gaps: PTC isn't available on Amazon Bedrock or Google Cloud, and Tool Search on Bedrock only works through the InvokeModel API.

How much does Tool Search save, and does it break prompt caching?

Per Anthropic's docs, a typical multi-MCP-server setup burns ~55k tokens on definitions; Tool Search usually cuts that by over 85%, loading only the 3-5 tools each request needs. It's cache-friendly by design: deferred tools stay out of the prompt prefix and discovered tools are appended as tool_reference blocks, so the cache survives. The one constraint: cache_control breakpoints must sit on non-deferred tools, or you get a 400.

When should I not use Programmatic Tool Calling?

Skip it for strictly sequential workflows — when every call depends on Claude reasoning over the previous result, the script can't eliminate model turns, and container overhead makes you pay extra: Anthropic measured unchanged scores but ~8% higher cost on τ²-bench. PTC shines on fan-out (checking 50 servers), filtering large results before they hit context, and loops with conditionals. Also note strict: true tools, MCP-connector tools, and disable_parallel_tool_use are all incompatible with PTC.

Which comes first: input_examples or a better description?

Description first — Anthropic states plainly that detailed descriptions are the single biggest factor in tool-use quality. input_examples supplements what a schema can't express: date formats, which optional parameters travel together, how nested structures are shaped. Each example must validate against the input_schema (400 otherwise) and costs prompt tokens (~20-50 simple, ~100-200 for nested objects), so add them only to your most error-prone tools rather than everywhere.