Recipe 02

Agentic loops & tools

Fable's headline talent is long-horizon agentic work. Two ways to run the loop — let the SDK drive, or drive it yourself.

The tool runner (let the SDK drive)

Define tools as typed functions; the runner calls the API, executes your functions, feeds results back, and stops when Fable is done:

import anthropic
from anthropic import beta_tool

client = anthropic.Anthropic()

@beta_tool
def get_weather(location: str) -> str:
    """Get current weather for a location.

    Call this whenever the answer depends on weather conditions
    not present in the conversation.

    Args:
        location: City and state, e.g., Austin, TX.
    """
    return fetch_weather(location)  # your implementation

runner = client.beta.messages.tool_runner(
    model="claude-fable-5",
    max_tokens=16000,
    tools=[get_weather],
    messages=[{"role": "user", "content": "Should I bike to work in Austin today?"}],
)
for message in runner:
    print(message)

The manual loop (drive it yourself)

Use this when you need approval gates, custom logging, or conditional execution:

messages = [{"role": "user", "content": user_input}]

while True:
    response = client.messages.create(
        model="claude-fable-5", max_tokens=16000,
        tools=tools, messages=messages,
    )
    if response.stop_reason == "end_turn":
        break
    if response.stop_reason == "pause_turn":  # server-side tool paused; just re-send
        messages.append({"role": "assistant", "content": response.content})
        continue

    messages.append({"role": "assistant", "content": response.content})
    results = []
    for block in response.content:
        if block.type == "tool_use":
            results.append({
                "type": "tool_result",
                "tool_use_id": block.id,
                "content": execute_tool(block.name, block.input),
            })
    messages.append({"role": "user", "content": results})

Making Fable reach for the tool

Recent Opus-tier models — Fable included — are conservative about tools: they reason instead of calling unless they're confident the call is needed. Two levers:

  • Prescriptive descriptions. Say when to call, not just what it does: "Call this when the user asks about current prices or recent events — do not answer from prior knowledge." Trigger conditions in the description measurably lift should-call rate.
  • Raise effort. high and xhigh show substantially more tool usage in agentic search and coding.
Keep the toolset small: 10–20 well-described tools beat 200 thin ones. Always parse tool input as JSON — never string-match the serialized form; Fable may escape Unicode or slashes differently than older models.

Moral: a tool description is a promise about when it's needed. Write the promise, not the manual.

This recipe in about a minute