Ga naar hoofdinhoud

Claude Fable 5.1 API-tutorial: Bouw een langlopende developeragent in Python

Leer hoe je het nieuwste vlaggenschipmodel van Anthropic gebruikt om een Python-agent te bouwen die een Flask-repository leest vóór het plannen van een wijziging. Voeg voortgangsupdates, read-only bestands-tools en kostenbeheersing toe.
Bijgewerkt 3 sep 2026  · 15 min lezen

Verkennen met AI

ChatGPTClaudePerplexity

Wanneer ik een nieuw model via een API-call probeer, zegt de eerste response me doorgaans weinig. Mijn eerste Fable 5.1-run gaf een geldige structuur en een algemeen plan. Ik wilde weten wat er gebeurt als het gesprek groeit: kan de applicatie haar geschiedenis intact houden, bestanden inspecteren zonder buiten het project te lezen, voortgang rapporteren en tonen waar de kosten vandaan kwamen?

Ons overzicht van Claude Fable 5.1 behandelt de lancering, benchmarks en bredere modelvergelijkingen. Hier beginnen we met een kleine Python-call en bouwen we de agentloop eromheen. De uiteindelijke agent ontvangt een featurerequest, leest een Flask-project en retourneert een plan gekoppeld aan bestanden die hij daadwerkelijk heeft geïnspecteerd.

We behandelen hoe je:

  • Een Claude Fable 5.1 API-call maakt en contentblokken veilig leest
  • Reasoning effort instelt en dit halverwege het gesprek aanpast (beta)
  • Een systeeminstructie tot één beurt beperkt (beta)
  • Een gestructureerd plan retourneert met Pydantic
  • Read-only repositorytools toevoegt met een projectroot-omheining
  • Een multi-turn-toolloop draait
  • De voortgangsupdates van de agent leest tussen tool-calls door (beta)
  • Thinking-blokken geldig houdt met append-only geschiedenis
  • Herhaalde context cachet en de requestkosten inschat tegen gepubliceerde tarieven
  • Weigeringen afhandelt en de agent via FastAPI exposeert

De beta-features gebruiken gedateerde headers, dus controleer ze tegen de documentatie van Anthropic voordat je live gaat.

Wat kost het om Claude Fable 5.1 in een agentloop te draaien?

Een agent stuurt bij elke beurt hetzelfde systeemprompt, tooldefinities en repositorycontext opnieuw. De rate die je rekening bepaalt, is daarom de cacheread, niet de inputrate.

Fable 5.1 kost $10 per miljoen inputtokens en $50 per miljoen outputtokens, ongewijzigd ten opzichte van Fable 5. Cachereads kosten $0,25 per miljoen, gedaald van $1, en cachewrites van vijf minuten blijven $12,50 per miljoen. Onze gids voor Claude Fable 5.1 bevat de volledige tarieftabel en Anthropic’s eigen besparingsschattingen.

Een gecachte prefix lezen is goedkoop. Hem schrijven niet, met 50 keer het lees-tarief, dus de loop loont pas als een prefix meerdere keren wordt teruggelezen. De kostenopsplitsing later laat zien hoe dat uitpakte in een echte run en welke categorie daadwerkelijk overheerste.

Het tokenceiling komt van het model, niet je budget. Fable 5.1 geeft je een contextvenster van 1M tokens met tot 128K output tokens per response, en max_tokens is een harde limiet op thinking plus responstekst samen. Bij hoge effort heb je voor beide ruimte nodig; daarom zet de agentloop hieronder 16.000 in plaats van iets ronders.

Gegevensbewaring, prioriteitstier en watermarking

Een paar toegangsdetails zijn belangrijk voordat je code schrijft. Twee daarvan stoppen je requests direct:

  • Fable 5.1 vereist 30 dagen dataretentie en is niet beschikbaar met zero data retention, tenzij Anthropic toegang autoriseert. Een request vanuit een onverenigbare workspace retourneert een 400 invalid_request_error zonder verdere hint.

  • Het model wordt niet ondersteund op Priority Tier. Fable 5 wel, dus dit pakt mensen die migreren.

  • Fable 5.1-tekstuitvoer heeft Anthropic’s tekstwatermerk. Dat voegt geen tokens toe en vereist geen wijziging van je request.

Gebruik Claude Fable 5.1 via API om een repository-bewuste developeragent te bouwen

Onze workflow kent twee fasen:

  1. Een begrensde inspectieloop leest toegestane projectbestanden.
  2. Een laatste request met gestructureerde outputs zet die context om in een plan. 

Het voorbeeldproject is een kleine Flask JSON API voor het opslaan en zoeken van bookmarks, met een appfactory, drie blueprints, een configmodule, modellen en een pytest-suite. Ik gebruik rate limiting als doorlopende taak, omdat de agent de app-setup, routes, config en tests moet inspecteren voordat hij de benodigde bestanden en tests kan identificeren. De complete code en het voorbeeldproject staan in de GitHub-repository.

Diagram van een featurerequest die door een Claude Fable 5.1-agent, een pad-allowlist en een voorbeeldproject stroomt om vervolgens een gestructureerd plan te retourneren

Requests bereiken bestanden via één grens. Afbeelding door auteur.

De agent mag slechts drie tools gebruiken: list_project_files, read_project_file, en get_project_metadata. Claude benadert het filesystem nooit direct. Het vraagt om een pad en jouw code beslist of dat pad is toegestaan.

De Claude Fable 5.1 API instellen in Python

Begin met een aparte Python-omgeving en bewaar de API-sleutel op de server.

Vereisten

Je hebt Python 3.10 of nieuwer nodig en een Anthropic API-sleutel met toegang tot claude-fable-5-1

Om een API-sleutel te maken, meld je aan bij de Claude Console, open de API-keys-pagina, klik op Create key en kopieer de sleutel. Het is best practice om hem een naam te geven die je aan het doel herinnert, een vervaldatum te kiezen en de sleutel veilig op te slaan.

Installeer de SDK en voeg de API-sleutel toe

Maak een virtual environment en installeer de packages:

python -m venv .venv
source .venv/bin/activate          # macOS of Linux
.venv\Scripts\Activate.ps1         # Windows PowerShell
pip install anthropic==1.3.0 pydantic fastapi uvicorn python-dotenv

Houd de SDK gepind omdat beta-features vaak veranderen. Voortgangsupdates vereisen minimaal 1.1.0, en de voorbeelden gebruiken 1.3.0.

Plaats de sleutel in een .env-bestand en voeg .env toe aan .gitignore vóór je eerste commit. Hij hoort op een server die je zelf beheert, nooit in een browser of een toegankelijke repository. Blootstelling kan ongeautoriseerd API-gebruik en kosten voor input, output en cache-operaties mogelijk maken.

ANTHROPIC_API_KEY=sk-ant-your-key-here

Daarmee vindt de client de sleutel vanzelf.

Doe je eerste Claude Fable 5.1 API-call in Python

Stuur de kleinste API-request die je kunt, voordat je erbovenop gaat bouwen.

Stuur de eerste API-request

Initialiseer de client, stuur één user-bericht en print de response-metadata:

from anthropic import Anthropic
from dotenv import load_dotenv

load_dotenv()

client = Anthropic()
MODEL = "claude-fable-5-1"

response = client.messages.create(
    model=MODEL,
    max_tokens=512,
    messages=[{"role": "user", "content": "Reply in one sentence to confirm the API connection is working."}],
)

text = next((b.text for b in response.content if b.type == "text"), None)
print(text if text is not None else f"No text returned ({response.stop_reason})")
print(f"Model: {response.model}")
print(f"Stop reason: {response.stop_reason}")
print(f"Input tokens: {response.usage.input_tokens}")
print(f"Output tokens: {response.usage.output_tokens}")
print(f"Request ID: {response._request_id}")

Terminal met een Claude Fable 5.1 API-response met het model-ID, stopreden, token-tellingen en request-ID

Eerste call retourneert tekst plus metadata. Afbeelding door auteur.

De next(...)-aanroep selecteert het eerste tekstblok. Adaptive thinking staat altijd aan en kan niet worden uitgeschakeld, dus een response kan beginnen met een thinking-blok; thinking: {"type": "disabled"} sturen geeft een 400 in plaats van het uit te zetten. Wanneer een thinking-blok eerst komt, gooit response.content[0].text een exceptie.

De oplossing is filteren op bloktype in plaats van een vaste positie aannemen. Log ook response._request_id, omdat Anthropic support die gebruikt om een request te traceren.

Hier is de request die in die planning- en effortvoorbeelden is gebruikt. Hij vereist dat de agent meerdere bestanden inspecteert:

feature_request = (
    "Add rate limiting to the public API endpoints so one client cannot exhaust "
    "the search endpoint or brute force the token endpoint."
)

Houd die tekst ongewijzigd bij het vergelijken van effortniveaus en tokentellingen. De resultaten beschrijven dan de API-instellingen in plaats van een andere prompt.

Stel reasoning effort in met output_config

Stel de reasoning effort in via output_config. Het accepteert low, medium, high, xhigh en max. De API-standaard is high.

response = client.messages.create(
    model=MODEL,
    max_tokens=8192,
    output_config={"effort": "high"},
    messages=[{"role": "user", "content": feature_request}],
)

Effort kan invloed hebben op tokengebruik, toolgedrag en latency. Ik draaide dezelfde featurerequest drie keer op elk van vier effortniveaus; de tabel toont de gemiddelden:

Effort

Seconden

Thinking-tokens

Totale outputtokens

Kosten

low

7,7

111

173

$0,0093

medium

8,1

129

186

$0,0099

high

7,9

136

199

$0,0106

xhigh

20,0

151

1.764

$0,0888

Thinking-tokens zijn inbegrepen in de totale outputtokens, tel die twee kolommen dus niet op. In deze runs bleven low, medium en high dicht bij elkaar qua latency en kosten.

xhigh duurde tweeënhalf keer zo lang, produceerde bijna negen keer zoveel outputtokens en kostte acht keer zoveel. 

Conclusie: Begin op high, verlaag naar medium voor routine-stappen en gebruik hogere niveaus alleen wanneer je eigen tests een meetbare verbetering laten zien. Bij low effort kan het model uit het geheugen antwoorden in plaats van een retrievaltool te gebruiken. Als een beurt frisse informatie nodig heeft, zeg dat dan of verhoog het niveau.

Beperk de scope van de agent met een systeemprompt

De systeemprompt definieert het gedrag van de agent:

SYSTEM_PROMPT = """You are a senior engineer who turns feature requests into implementation plans for an existing codebase.

Stay inside the requested feature. Do not propose unrelated refactors, dependency upgrades, or style changes.

If a file or dependency you need does not exist, say so plainly instead of inventing it.

Write in plain sentences and do not use em dashes.

Finish with concrete guidance: what changes, where, in what order, what could break, and which tests to add."""

Anthropic’s promptingrichtlijnen merken op dat het model de taak kan uitbreiden of te vroeg kan stoppen. De prompt zegt dat het binnen scope moet blijven en afsluiten met concrete aanwijzingen. Een schema regelt later het outputformaat.

Geef een gestructureerd plan terug met Pydantic

Definieer het plan met Pydantic zodat je applicatie het kan valideren en doorgeven aan andere code:

from pydantic import BaseModel, Field

class FeaturePlan(BaseModel):
    summary: str = Field(description="One or two sentences on what will be built.")
    implementation_steps: list[str]
    files_to_modify: list[str]
    risks: list[str]
    tests: list[str]

response = client.messages.parse(
    model=MODEL,
    max_tokens=8192,
    system=SYSTEM_PROMPT,
    messages=[{"role": "user", "content": feature_request}],
    output_format=FeaturePlan,
)

if response.stop_reason == "refusal":
    category = (
        response.stop_details.category
        if response.stop_details and response.stop_details.category
        else "unspecified"
    )
    print(f"Declined: {category}")
elif response.parsed_output is None:
    print(f"No plan. Stop reason: {response.stop_reason}")
else:
    print(response.parsed_output.summary)

messages.parse() zet het Pydantic-model om in een JSON-schema, stuurt het, valideert het antwoord en retourneert een getypt object op parsed_output. Gestructureerde outputs zijn algemeen beschikbaar, dus er komt geen beta-header aan te pas. Check eerst stop_reason omdat een weigering, verderop behandeld, het schema overslaat en je niets te parsen laat.

Dat generieke resultaat uit de introductie deed één ding goed: het noemde geen bestanden die het niet kon zien. Een schema valideert de structuur, niet de feitelijke onderbouwing.

Claude Fable 5.1 vs. Fable 5: API-migratiewijzigingen

Voordat je tools toevoegt, hou rekening met beperkingen rond geforceerde toolselectie, compatibiliteit van thinking-blokken en append-only geschiedenis.

  • Fable 5.1 wijst geforceerde toolselectie af. Het toolloop-gedeelte hieronder toont de fout en de gebruikte auto-configuratie.

  • Thinking-blokken zijn slechts in één richting compatibel. Fable 5.1 leest blokken van eerdere Claude-modellen, maar geen eerder model kan zijn blokken lezen. 

Wanneer een router of fallback het gesprek naar een ouder model verplaatst, verwijdert de API de onverenigbare blokken voordat het doelmodel ze ziet. De resterende geschiedenis blijft staan, maar het oudere model moet zonder die blokken plannen.

Het bewerken van eerdere beurten maakt de daaropvolgende thinking-blokken ongeldig. Dit kan history trimming en client-side samenvatten breken.

De migratiegids dekt de volledige set wijzigingen.

Voeg read-only repositorytools toe

Geef het model nu repositorycontext via read-only tools.

Definieer de read-only tools

De toollaag heeft twee delen: de Python-functies die toegangsregels afdwingen en de schema’s die Claude kan aanroepen.

Beperk paden tot de projectroot

Read-only is niet hetzelfde als veilig. Een model kan net zo makkelijk om ../../.env vragen als om config.py, dus de guard hoort in je code en niet in je prompt:

def _resolve(self, relative_path: str) -> Path:
    relative = Path(relative_path)
    if relative.is_absolute() or relative.drive:
        raise ToolError(f"path is outside the project root: {relative_path}")

    cursor = self.root
    for part in relative.parts:
        cursor /= part
        if cursor.is_symlink():
            raise ToolError(f"symlinks are not followed: {relative_path}")

    candidate = (self.root / relative).resolve()

    # After resolving "..", the path still has to sit under the allowed root.
    if candidate != self.root and self.root not in candidate.parents:
        raise ToolError(f"path is outside the project root: {relative_path}")
    if candidate.name in DENY_NAMES:
        raise ToolError(f"reading {candidate.name} is not allowed")

    return candidate

Wijs absolute paden en symlinkcomponenten af, los dan het pad op en bevestig dat het onder de projectroot blijft. Vragen om ../.env geeft “path is outside the project root.” De geretourneerde toolfout laat de agent doorgaan met toegestane bestanden.

Definieer strikte toolschema’s

De readerklasse bepaalt wat Python mag openen. Claude heeft ook JSON-schema’s nodig die de drie acties beschrijven die het kan verzoeken:

EMPTY_SCHEMA = {
    "type": "object",
    "properties": {},
    "additionalProperties": False,
}

TOOLS = [
    {
        "name": "list_project_files",
        "description": "List readable text files in the project.",
        "input_schema": EMPTY_SCHEMA,
        "strict": True,
    },
    {
        "name": "read_project_file",
        "description": "Read one text file relative to the project root.",
        "input_schema": {
            "type": "object",
            "properties": {"path": {"type": "string"}},
            "required": ["path"],
            "additionalProperties": False,
        },
        "strict": True,
    },
    {
        "name": "get_project_metadata",
        "description": "Read project metadata and dependency manifests.",
        "input_schema": EMPTY_SCHEMA,
        "strict": True,
    },
]

strict controleert de argumenten wanneer het model een tool kiest. Het forceert geen toolcall, wat relevant is voor Fable 5.1.

Draai de multi-turn-toolloop

Begin met de basisloop: stuur de tools, inspecteer stop_reason, voer uit wat is gevraagd, voeg de resultaten toe en herhaal.

MAX_AGENT_TURNS = 8
reader = ProjectReader("sample_project")
messages = [{"role": "user", "content": feature_request}]

for turn in range(1, MAX_AGENT_TURNS + 1):
    response = client.messages.create(
        model=MODEL,
        max_tokens=16000,
        system=SYSTEM_PROMPT,
        tools=TOOLS,
        messages=messages,
    )

    if response.stop_reason == "refusal":
        return declined(response.stop_details.category)
    if response.stop_reason == "max_tokens":
        return cutoff()
    if response.stop_reason != "tool_use":
        messages.append({"role": "assistant", "content": response.content})
        break

    messages.append({"role": "assistant", "content": response.content})
    results = []
    for block in response.content:
        if block.type != "tool_use":
            continue
        output, is_error = reader.run(block.name, block.input)
        results.append({
            "type": "tool_result",
            "tool_use_id": block.id,
            "content": output,
            "is_error": is_error,
        })

    messages.append({"role": "user", "content": results})
else:
    return turn_limit()

MAX_AGENT_TURNS begrens modelverzoeken, niet uitgaven, dus handhaaf desnoods een aparte kostenlimiet. De loop handelt refusal, max_tokens en tool_use direct af; andere stopredenen beëindigen de inspectiefase. Het veld is_error vertelt het model dat een pad is geweigerd, zodat het een andere actie kan kiezen.

Waarom geforceerde toolkeuze een 400 geeft

Op Fable 5 kon je de eerste call forceren met tool_choice: {"type": "any"}. Fable 5.1 geeft deze fout vóór de uitvoering van de request:

tool_choice: type "tool" and "any" are not supported for this model.

Geforceerde calls zouden de altijd-actieve thinking overslaan. Laat tool_choice op auto staan, gebruik de hierboven gedefinieerde strikte schema’s en noem de tools in de prompt wanneer een stap er één nodig heeft.

Fable 5.1 doet soms één toolcall per beurt, terwijl Fable 5 er meerdere batchte. Dat voegt round-trips toe. Voeg deze regel toe aan de prompt: “Vraag onafhankelijke bestanden in dezelfde beurt in plaats van één per beurt.” Een voorbeelduitvoering batchte negen onafhankelijke bestandsverzoeken, al varieert het aantal.

Stream Claude Fable 5.1-responses en voortgangsupdates

Tekststreaming geeft responsecontent zodra die wordt gegenereerd; voortgangsupdates dekken pauzes tussen tool-calls.

Stream tekstresponses

Het volledige project gebruikt context_system() om SYSTEM_PROMPT te combineren met een projectsamenvatting voordat de stream start:

with client.messages.stream(
    model=MODEL,
    max_tokens=8192,
    system=context_system(),
    messages=[{"role": "user", "content": feature_request}],
) as stream:
    for chunk in stream.text_stream:
        print(chunk, end="", flush=True)
    final = stream.get_final_message()

print(f"\nOutput tokens: {final.usage.output_tokens}")

get_final_message() geeft je het samengevoegde bericht met usage en stopreden zodra de stream leegloopt. Streaming-chunks bevatten niet gegarandeerd volledige JSON, dus wacht met parsen op het final-bericht.

Toon voortgang tussen tool-calls

Tekststreaming dekt geen vertragingen tijdens tool-calls. Fable 5.1 kan korte voortgangsupdates schrijven vóór tool-calls. Onder de standaard thinking.display van "omitted" zijn de voortgangsspecifieke thinking-blokken leeg, al kan het model nog steeds een normale tekst-inleiding produceren.

Met display: "updates" en de thinking-display-updates-2026-08-18 beta-header definieert de API-documentatie een leesbare voortgangsupdate als een niet-leeg thinking-blok terwijl de redenering verborgen blijft. In de live-runs voor dit project bleef het thinking-veld leeg en kwam de leesbare status als een normaal text -blok direct vóór tool_use. De helper controleert daarom beide bloktypen, en de loop roept hem alleen aan in beurten die eindigen met tool_use:

PROGRESS_BETA = "thinking-display-updates-2026-08-18"

response = client.beta.messages.create(
    model=MODEL,
    max_tokens=16000,
    betas=[PROGRESS_BETA],
    thinking={"type": "adaptive", "display": "updates"},
    system=SYSTEM_PROMPT,
    tools=TOOLS,
    messages=messages,
)

def status_lines(response) -> list[str]:
    lines = []
    for block in response.content:
        if block.type == "thinking":
            text = (block.thinking or "").strip()
        elif block.type == "text":
            text = (block.text or "").strip()
        else:
            continue
        if text:
            lines.append(text)
    return lines

De voortgangsberichten beschrijven de bestanden die het model wil lezen: "Ik lees de app-wiring, config, extensions, de public en auth routes en de bestaande tests, want daar zou rate limiting inhaken." Toon die berichten en negeer lege blokken.

Terminal die een Claude Fable 5.1-agentloop toont met tokengebruik per beurt, voortgangsberichten en gebatchte bestandslezingen

Agent leest bestanden en rapporteert voortgang. Afbeelding door auteur.

Fable 5.1 schrijft er minder van dan Fable 5 deed, vooral bij hogere effort. Als je interface regelmatige updates vereist, vraag dan om een openingsregel, voortgangsberichten en een afsluitende samenvatting.

Wijzig Claude Fable 5.1-effort halverwege het gesprek

De volgende feature is erg handig. Zoals we weten heeft de repositoryagent niet in elke beurt dezelfde diepte van redeneren nodig.

Wijzig effort tussen beurten

Verlaag in een agentloop de effort voor routine-ophaalbeurten en verhoog hem weer voor de laatste planningsbeurt.

Met de mid-conversation-output-config-2026-07-01 beta-header kun je een systeembericht toevoegen dat alleen het effortniveau wijzigt:

EFFORT_BETA = "mid-conversation-output-config-2026-07-01"

messages.append({"role": "system", "content": [], "output_config": {"effort": "low"}})
messages.append({"role": "user", "content": "Summarize the repository evidence in five words."})

response = client.beta.messages.create(
    model=MODEL,
    max_tokens=4096,
    betas=[EFFORT_BETA],
    output_config={"effort": "high"},
    messages=messages,
)

Het nieuwe niveau geldt vanaf de volgende user-beurt, niet halverwege de huidige, en het maakt de promptcache niet ongeldig. Het wijzigen van de top-level output_config.effort tussen requests maakt deze wel ongeldig. 

De agent houdt de top-level instelling op high, voegt een per-bericht- medium directive toe vóór routine-ophalen en een high directive vóór het finale plan. Een gekoppelde test gebruikte 18 outputtokens bij lagere effort versus 76 bij de vorige instelling. Zie dat als voorbeeld, niet als verwachte reductie.

Pas een systeeminstructie toe op één beurt

Gebruik een turn-scoped instructie om extra bestandslezingen tijdens de laatste planning te blokkeren.

Zet clear_at: "next_user_message" op een systeembericht met de mid-conversation-system-clear-at-2026-08-21 beta-header. De API behandelt de tekst als een systeeminstructie voor de huidige beurt en stopt met renderen na het volgende user-bericht. Het blijft in messages, dus de eerdere geschiedenis verandert niet, de cache blijft matchen en het gewiste bericht kost geen inputtokens.

SCOPED_SYSTEM_BETA = "mid-conversation-system-clear-at-2026-08-21"

messages.append({"role": "system", "content": [], "output_config": {"effort": "high"}})
messages.append({"role": "user", "content": "Write the implementation plan now."})
messages.append({
    "role": "system",
    "content": (
        "For this turn only: do not request more files. Base the plan on what "
        "you have already read, and name only paths you actually opened."
    ),
    "clear_at": "next_user_message",
})

response = client.beta.messages.create(
    model=MODEL,
    max_tokens=16000,
    betas=[EFFORT_BETA, SCOPED_SYSTEM_BETA],
    tool_choice={"type": "none"},
    output_config={"format": {"type": "json_schema", "schema": plan_schema()}},
    system=agent_system(),
    tools=TOOLS,
    messages=messages,
)

tool_choice={"type": "none"} voorkomt dat de laatste request nog een tool aanroept. De gescopeerde instructie beperkt het plan tot bestanden die de agent al heeft geïnspecteerd. Voeg geen herinnering toe en verwijder die niet bij de volgende request. Die edit maakt latere thinking-blokken ongeldig.

Los Claude Fable 5.1 thinking-block 400-fouten op

Een The block is bound to a different conversation-fout betekent dat de geschiedenis vóór een thinking-blok is gewijzigd. Elk Fable 5.1-thinkingblok is gebonden aan de exacte systeemprompt, tooldefinities en berichten die eraan voorafgingen.

Het resultaat hangt af van wanneer je account is aangemaakt. 

  • Accounts aangemaakt op of na 31 augustus 2026 krijgen een 400 met de melding dat het blok aan een ander gesprek is gebonden. 

  • Voor eerder aangemaakte accounts registreert de API de mismatch, maar handelt die alleen af wanneer de request thinking.block_binding.prefix_mismatch_behavior zet. 

Je kunt dit detecteren met de thinking-binding-controls-2026-08-01 beta-header, thinking.block_binding.prefix_mismatch_behavior op "drop_block" en de array input_transformations. Een bewerkte geschiedenis verschijnt als reason: "prefix_binding_mismatch". Voer deze check één keer uit tegen je integratie.

De volgende handelingen veroorzaken de mismatch:

  • Een eerdere beurt bewerken, herschikken of verwijderen terwijl latere beurten behouden blijven

  • Per-request tekst in een eerdere beurt injecteren en die in de volgende request verwijderen

  • De inhoud of volgorde van de top-level system-prompt of de tools-array halverwege het gesprek wijzigen

  • Andere bytes serveren vanaf een image- of document-URL bij een latere request

Voor elk is er een vervanger die de bindings intact houdt:

  • Voeg instructies toe met mid-conversation-systeemberichten in plaats van system te bewerken. 

  • Wijzig tools met mid-conversation-wijzigingen in plaats van de top-level array aan te passen. 

  • Kort geschiedenis in met server-side context editing of compaction die niet als edits tellen. 

  •  Geef thinking-blokken onveranderd terug.

Het verplaatsen van cache_control -markeringen en het wijzigen van effort op requestniveau zijn beide veilig en maken thinking-blockbindings niet ongeldig. Het wijzigen van top-level effort herstart echter promptcaching, dus gebruik per-bericht effort wanneer de gecachte prefix moet blijven staan.

Promptcaching en Claude Fable 5.1 API-kosten

De volgende run splitst kosten op in verse input, cachewrites, cachereads en output.

Voeg automatische promptcaching toe

Promptcaching verlaagt de kosten van context die zich herhaalt over beurten. De groeiende geschiedenis verandert waar de breeklijn moet liggen, dus automatische caching past hier eenvoudiger.

Een top-level cache_control-veld verplaatst de breeklijn naar het laatste cachebare blok bij elke request:

response = client.beta.messages.create(
    model=MODEL,
    cache_control={"type": "ephemeral"},
    system=system,
    tools=TOOLS,
    messages=messages,
    # Other request fields...
)

Een cachebare prefix korter dan 512 tokens wordt niet gecachet op Fable 5.1, zelfs niet wanneer gemarkeerd met cache_control. De API verwerkt hem normaal en retourneert nul voor beide cachecounters. Het schrijven van een prefix van 583 tokens kostte $0,0073; het lezen ervan in de volgende beurt kostte $0,00015. De tweede beurt moest zijn nieuwe deel nog steeds naar de cache schrijven, dus een cachehit verwijderde niet elke inputkost.

Schat cache-bewuste API-kosten

response.usage rapporteert verse input, cachecreatie, cachereads en output apart. Prijs alle vier de tellers los; alleen input en output optellen verbergt cachewrite-kosten en overschat de prijs van cachehits.

Hier is de kostenopsplitsing van één volledige run die 12 bestanden las over drie beurten en een eindplan produceerde:

Post

Tokens

Geschatte kosten

Aandeel

Output

5.713

$0,2857

59,4%

Cachewrites

15.426

$0,1928

40,1%

Verse input

50

$0,0005

0,1%

Cachereads

6.549

$0,0016

0,3%

Totaal

27.738

$0,4806

100%

Cachereads vormden minder dan een halve procent van deze schatting. Tegen Fable 5’s oude tarief had de run ongeveer $0,4855 gekost in plaats van $0,4806. De besparingen groeien wanneer elke beurt veel meer context hergebruikt.

In deze run leverde output bijna 60% van de schatting op, en cachewrites zo’n 40%. Tegen het vijfminutentarief in dit voorbeeld kost een cachewrite-token 50 keer zoveel als een cacheread-token. Een cachewrite van één uur kost 80 keer zoveel.

Ga om met Claude Fable 5.1-weigeringen en fallbacks

Een weigering en een mislukte request vragen om verschillend applicatiegedrag.

Detecteer weigeringen vóór je output parseert

Een weigering vóór output komt binnen als HTTP 200 met stop_reason: "refusal", lege content en stop_details. De categorie kan null zijn. Een weigering later in een stream kan volgen op gedeeltelijke output, die de applicatie moet negeren. Een try/except rond de call vangt geen van beide gevallen.

response = client.messages.create(model=MODEL, max_tokens=8192, messages=messages)

if response.stop_reason == "refusal":
    category = (
        response.stop_details.category
        if response.stop_details and response.stop_details.category
        else "unspecified"
    )
    return f"This request was declined ({category})."

Behandel het als een applicatiestaat. Als een toegestane request onduidelijk is, herschrijf hem preciezer. Bouw geen retrylogica met als doel de classifier te omzeilen.

Een weigering komt als HTTP 200. Afbeelding door auteur.

Configureer server-side fallback

Server-side fallback kan een geweigerde request opnieuw proberen op een ander model met fallbacks: "default" en de server-side-fallback-2026-07-01 beta-header. De toegestane doelen voor Fable 5.1 zijn Opus 4.8 en Opus 5

Standaard fallback draait alleen wanneer de weigeringscategorie een aanbevolen doel heeft. Een geteste reasoning_extraction -weigering triggerde geen fallback; inspecteer usage.iterations in plaats van aan te nemen dat elke weigering opnieuw wordt geprobeerd. Zoals eerder vermeld, verwijdert verplaatsen naar een ouder model ook Fable 5.1-thinkingblokken.

Serve de Claude Fable 5.1-agent met FastAPI

De lokale agent kan nu dezelfde workflow via een HTTP API aanbieden.

Maak de plan-endpoint

Als je alleen een lokaal script nodig hebt, sla dit gedeelte dan over. Voor een webservice gebruik je FastAPI met AsyncAnthropic. Maak één client voor het proces in een lifespan-handler. Importeer het schema en de prompts uit de bestaande agentmodule.

@asynccontextmanager
async def lifespan(_: FastAPI):
    global client
    client = AsyncAnthropic()
    try:
        yield
    finally:
        await client.close()


@app.post("/plan", response_model=PlanResponse)
async def create_plan(body: PlanRequest):
    reader = resolve_project(body.project)
    messages, totals, turns, tool_calls = await inspect(reader, body.feature_request)
    plan, final_usage = await write_plan(messages)
    totals.add(final_usage)
    return PlanResponse(plan=plan, turns=turns, tool_calls=tool_calls, usage=as_usage(totals))

Let op: de aanroeper stuurt een projectnaam, geen pad. resolve_project() mapt die naar één van een kleine set toegestane roots, zodat een request de server niet zomaar ergens kan laten lezen. Deze service mapt weigeringen naar 422 als applicatiekeuze. De Claude API zelf retourneert ze als HTTP 200.

Draai hem met uvicorn app:app --reload. De interactieve documentatie staat op http://localhost:8000/docs.

Endpoint retourneert een plan met een geschatte kostprijs. Video door auteur.

De /plan/stream-endpoint draait de inspectie in een achtergrondtaak, plaatst voortgangs- en toolevents op een asyncio.Queue en zendt ze uit via StreamingResponse. Wanneer de stream sluit, annuleert de generator de achtergrondtaak. De Streamlit-interface in de repository rendert dezelfde eventstream.

Streamlit toont de live voortgang van de agent. Video door auteur.

Claude Fable 5.1 agent-deploymentchecklist

De limieten en checks die eerder zijn gebouwd, blijven onderdeel van de service. Voeg vóór deployment de operationele stukken toe die in een lokale run niet zichtbaar zijn.

  • Bekijk de standaard twee retries van de SDK voor 429- en 5xx-responses en stel vervolgens max_retries en time-outs in op het latencybudget van de service

  • Stel een request-time-out in en bevestig dat de bestaande SSE-taakannulering lopend werk stopt wanneer een client verbreekt

  • Log voor elke run het model-ID, de SDK-versie, de request-ID, de stopreden en de vier tokencategorieën

  • Alert bij stijgende cachewrites, outputtokens, weigeringen en runs die de beurtencap bereiken

  • Bevestig dat de retentie-instelling van het account overeenkomt met de modelvereiste

  • Pin de SDK en controleer de beta-headers opnieuw vóór elke release

Wanneer gebruik je Claude Fable 5.1 in plaats van Opus 5 of Sonnet 5

  • Anthropic raadt Opus 5 aan als redelijk standaardkeuze.
  • Test Fable 5.1 wanneer Opus 5 tekortschiet bij lange repository-analyses, lastige debugging of agentische taken met grote context.
  • Vergelijk voor repositorywerk en alledaagse taken Sonnet 5 en Opus 5 op kwaliteit, latency en kosten.
  • Voor classificatie, extractie, korte antwoorden en eenvoudigere verzoeken is Sonnet 5 een goede standaard; voor de allermakkelijkste taken kan Haiku 4.5 ook sterk genoeg zijn.

Kies Fable 5.1 niet simpelweg omdat het nieuwer is. Eén enkele request kan nog steeds effort en gestructureerde outputs gebruiken; streaming werkt ook. Het profiteert niet van de loop of herhaalde-prefixcaching die hier is gebruikt.

Slotgedachten

Het generieke plan van mijn eerste call werd pas nuttig nadat de agent de repository had gelezen. In de voltooide run inspecteerde hij 12 bestanden over drie beurten, terwijl output en cachewrites samen 99,5% van de geschatte kosten uitmaakten. Ik zou de padgrens en append-only geschiedenis behouden en dan testen of lagere effort de kosten verlaagt zonder dat het model repositorytools overslaat.

Als één response de taak kan beantwoorden, stop dan bij gestructureerde outputs. Gebruik de toolloop wanneer het antwoord moet afhangen van repositorybestanden of voortgang tussen calls moet rapporteren.

Voor details over modelselectie raad ik onze cursus Introductie tot Claude-modellen aan. Voor prompting en agentworkflows: zie onze cursus Softwareontwikkeling met Cursor.

FAQs

Kan Claude Fable 5.1 naast code ook afbeeldingen lezen?

Ja. Het accepteert beeldinput en kan grafieken en pdf’s lezen. Ik heb vision buiten het hoofdvoorbeeld gelaten omdat het repositoryplan het niet nodig heeft. Als ik deze agent zou uitbreiden voor een UI-wijziging, zou ik de huidige screenshot met de featurerequest meesturen. Schaal hem eerst omlaag als kleine visuele details de taak niet beïnvloeden.

Waarom werd mijn agent trager na het overschakelen van Fable 5?

Controleer de toolresultaten voordat je het model de schuld geeft. Als de batching-instructie van eerder al aanwezig is, vergelijk dan zowel hun aantal als grootte. De huidige reader kapt elk bestand af op 40.000 bytes. Als dat nog te groot is, voeg line-range- of zoekargumenten toe zodat de tool alleen de relevante secties kan retourneren.

Waarom geeft Claude Fable 5.1 een 400 invalid_request_error?

Probeer niet eerst te retrypen. Een invalid_request_error wijst meestal op een requestvorm of accountinstelling die moet worden aangepast. In dit project zijn waarschijnlijke oorzaken: geforceerde tool_choice, een onverenigbare retentie-instelling, een bewerkt prefix met behouden thinking of een betaveld zonder bijbehorende header. Los de aangegeven oorzaak op en stuur de request opnieuw.

Moet ik bronbestanden of een samenvatting cachen?

Ik gebruik deze regel: cache bronbestanden wanneer exacte code over meerdere beurten belangrijk is. Als latere stappen alleen de architectuur of bestandskaart nodig hebben, cache dan een samenvatting. De samenvatting kost minder tokens, maar kan net die ene regel weglaten die het eindplan nodig heeft.

Kan de Batch API deze agent draaien?

Niet op zichzelf. De Batch API dient individuele Messages-requests in; hij draait deze client-side toolloop niet. Ik zou hem gebruiken voor op zichzelf staande repositoryreviews wanneer live voortgang niet vereist is. De volledige loop in batches draaien vereist eigen code die de toolverzoeken van één batch verwerkt voordat de volgende wordt ingediend.


Khalid Abdelaty's photo
Author
Khalid Abdelaty
LinkedIn

Ik ben een data-engineer en communitybouwer die werkt aan datapijplijnen, cloud en AI-tools, en tegelijkertijd praktische, impactvolle tutorials schrijft voor DataCamp en beginnende developers.

Onderwerpen

Leer AI met DataCamp!

Leerpad

Associate AI Engineer voor ontwikkelaars

26 Hr
Leer hoe je AI in softwareapplicaties kunt integreren met behulp van API's en open-sourcebibliotheken. Begin vandaag nog aan je reis om AI-ingenieur te worden!
Bekijk detailsRight Arrow
Begin Met De Cursus
Meer zienRight Arrow
Gerelateerd

blog

AI vanaf nul leren in 2026: een complete gids van de experts

Ontdek alles wat je moet weten om in 2026 AI te leren, van tips om te beginnen tot handige resources en inzichten van industrie-experts.
Adel Nehme's photo

Adel Nehme

15 min

Meer ZienMeer Zien