
Kill the 40-Line Agentic Loop: The Claude SDK tool_runner Handles Multi-Turn Tool Calls For You
Chris Harper
2 min read
Aug 1, 2026 · 04:15 UTC
The standard agentic loop — check stop_reason, dispatch tool calls, append results, repeat — is 30+ boilerplate lines. The Claude SDK's tool_runner collapses it to an iterable.
Every multi-turn tool-using agent follows the same cycle: call the API, check if stop_reason == "tool_use", run each tool_use block, append tool_result messages, call the API again. The client.beta.messages.tool_runner (beta, available in Python, TypeScript, Go, C#, Java, Ruby, PHP) handles all of that internally.
Minimal working example
pip install anthropic
from anthropic import Anthropic, beta_tool
import json
client = Anthropic()
@beta_tool
def get_price(ticker: str) -> str:
"""Fetch current stock price.
Args: ticker: Stock symbol, e.g. AAPL.
Returns: JSON with price and daily change.
"""
return json.dumps({"ticker": ticker, "price": 182.50, "change": "+1.2%"})
@beta_tool
def search_news(query: str, limit: int = 3) -> str:
"""Search recent news headlines.
Args: query: Search topic. limit: Max number of results (default 3).
Returns: JSON list of headline strings.
"""
return json.dumps([f"Headline about {query} #{i}" for i in range(limit)])
runner = client.beta.messages.tool_runner(
model="claude-sonnet-5",
max_tokens=2048,
tools=[get_price, search_news],
messages=[{"role": "user", "content": "Research AAPL: get the price and two recent headlines."}],
)
for msg in runner:
pass # runner iterates through every tool-call/result cycle
print(runner.get_final_message().content[0].text)
Three things the runner does for you:
@beta_toolgenerates the schema. The decorator reads your function signature and docstring and builds the full JSON schema — no manualinput_schemadict.- Parallel dispatch by default. When Claude requests multiple tools in one turn, the runner fans them all out before the next iteration.
- Error wrapping. If your tool throws, the runner returns the exception message as an
is_error: truetool result — Claude sees the error and can adapt, rather than your process crashing.
The 5-ring official tutorial walks through writing the manual loop first (rings 1–4), then collapsing it with tool_runner (ring 5) — worth reading to understand what happens under the hood.
Sources: Tool Runner (SDK) — Claude Platform Docs · Tutorial: Build a tool-using agent — Claude Platform Docs · Agent SDK overview — Claude API Docs