Claude Seekho

Tool Use (Function Calling)

Tool use lets Claude interact with the outside world: database queries, a weather API, sending email, running code. Claude does not run the function itself (for client tools) — it tells you which tool to call and with what input; your code runs it and sends the result back.

7.1 Agentic loop

Tool use loop
  1. 1.1. Request: messages + tools definitions
  2. 2.2. Claude: stop_reason: tool_use
  3. 3.3. Your code: run the function
  4. 4.4. tool_result: send back in a user message
  5. 5.5. Claude: reads the result and moves on
  6. 6.6. Final answer: stop_reason: end_turn

The loop continues until Claude stops asking for tools

7.2 Tool definition and manual loop

tools = [{
    "name": "get_order_status",
    "description": "Returns the current status of an order by order ID. Use it when the user tracks an order.",
    "input_schema": {
        "type": "object",
        "properties": {"order_id": {"type": "string", "description": "For example ORD-1234"}},
        "required": ["order_id"],
        "additionalProperties": False,
    },
    "strict": True,            # will match the input schema exactly
}]

messages = [{"role": "user", "content": "Where is my order ORD-1234?"}]
while True:
    r = client.messages.create(model="claude-opus-5-5", max_tokens=4000,
                               tools=tools, messages=messages)
    messages.append({"role": "assistant", "content": r.content})
    if r.stop_reason != "tool_use":
        break
    results = []
    for b in r.content:
        if b.type == "tool_use":
            out = get_order_status(**b.input)          # your function
            results.append({"type": "tool_result", "tool_use_id": b.id, "content": out})
    messages.append({"role": "user", "content": results})   # all results in ONE message

7.3 Tool Runner (SDK helper)

Instead of writing the loop yourself, you can use the SDK's Tool Runner — it runs the request → run tool → send back cycle for you.

from anthropic import beta_tool

@beta_tool
def get_weather(location: str) -> str:
    """Tells the weather of a city.
    Args:
        location: Name of the city, for example Delhi.
    """
    return f"{location}: 31°C, sunny"

runner = client.beta.messages.tool_runner(
    model="claude-opus-5-5", max_tokens=16000, tools=[get_weather],
    messages=[{"role": "user", "content": "Weather in Delhi?"}],
)
for message in runner:      # each iteration is one message; stops when Claude is done
    print(message)

7.4 Important concepts

ConceptDetail
tool_choiceauto (default, Claude decides), none (no tools). On newer models (Opus 5.5, Sonnet 5.5, Fable 5.1) forced any / tool gives a 400 — name the tool in the prompt instead
Parallel tool useSeveral tool_use blocks in one response. Send all the results in a single user message
is_error: trueIf a tool fails, send the tool_result with the error; do not drop it
strict: trueGuarantee that the tool input matches the schema exactly
Good descriptionWhat the tool does, when to use it, when not to — the biggest quality factor
Tool searchWith very many tools, use defer_loading + the tool search tool; only the needed tools get loaded
Programmatic tool callingClaude calls your tools from inside code execution (fewer round trips)

7.5 Anthropic's built-in tools

ToolWhere it runsWhat it does
Web searchServer (Anthropic)Internet search, with citations
Web fetchServerFetches the content of a URL that appears in the conversation
Code executionServer sandboxRun Python/bash, create files, data analysis
BashClient (your system)Shell commands — schema-less, Anthropic-defined
Text editorClientView/create files, edit with str_replace
Computer useClient or hostedLook at screenshots and drive the mouse/keyboard
Memory toolClientRemember things in files across conversations
Advisor toolServerA smaller model gets advice from a bigger model
MCP connectorServerTools of a remote MCP server straight from the API
r = client.messages.create(
    model="claude-opus-5-5", max_tokens=16000,
    tools=[{"type": "web_search_20260209", "name": "web_search", "max_uses": 5}],
    messages=[{"role": "user", "content": "Tell me this week's AI news"}],
)   # server tool: no loop to write, the result comes in this same response