Sari la conținutul principal

Tutorial API Claude Fable 5.1: Construiește un agent de dezvoltare de lungă durată în Python

Învață cum să folosești cel mai nou model de vârf al Anthropic pentru a construi un agent Python care citește un repository Flask înainte de a planifica o schimbare. Adaugă actualizări de progres, tool-uri de fișiere read-only și controale de cost.
Actualizat 3 sept. 2026  · 15 min. citire

Explorează cu AI

ChatGPTClaudePerplexity

Când încerc un model nou printr-un apel API, primul răspuns îmi spune foarte puține. Prima mea rulare cu Fable 5.1 a returnat o structură validă și un plan generic. Voiam să știu ce se întâmplă după ce conversația crește: poate aplicația să-și păstreze istoricul intact, să inspecteze fișiere fără să citească în afara proiectului, să raporteze progresul și să arate de unde a venit costul?

Prezentarea noastră Claude Fable 5.1 acoperă lansarea, benchmark-urile și comparațiile mai largi între modele. Aici, vom porni de la un apel Python mic și vom construi în jurul lui bucla agentului. Agentul final primește o cerere de funcționalitate, citește un proiect Flask și întoarce un plan legat de fișierele pe care chiar le-a inspectat.

Vom acoperi cum să:

  • Faci un apel API Claude Fable 5.1 și să citești block-urile de conținut în siguranță
  • Setezi efortul de raționare și să-l schimbi pe parcursul conversației (beta)
  • Limitezi o instrucțiune de sistem la o singură tură (beta)
  • Returnezi un plan structurat cu Pydantic
  • Adaugi tool-uri de repository read-only cu o limită la rădăcina proiectului
  • Rulezi o buclă de tool-uri pe mai multe ture
  • citești actualizările de progres ale agentului între apelurile de tool (beta)
  • Păstrezi block-urile de thinking valide cu istoric doar-adăugare
  • Cache-uiești contextul repetat și estimezi costul cererii la tarifele publicate
  • Gestionezi refuzurile și expui agentul prin FastAPI

Funcțiile beta folosesc antete datate, așa că verifică-le în documentația Anthropic înainte de lansare.

Cât costă să rulezi Claude Fable 5.1 într-o buclă de agent?

Un agent retrimite același prompt de sistem, definiții de tool-uri și context al repository-ului la fiecare tură, astfel că rata care îți determină factura este citirea din cache, nu rata de input.

Fable 5.1 costă 10 $ pe milionul de tokeni de input și 50 $ pe milionul de tokeni de output, neschimbat față de Fable 5. Citirile din cache costă 0,25 $ pe milion, în scădere de la 1 $, iar scrierile în cache pe cinci minute rămân la 12,50 $ pe milion. Ghidul nostru Claude Fable 5.1 are tabelul complet de tarife și estimările de economii ale Anthropic.

Citirea unui prefix cache-uit e ieftină. Scrierea nu, la 50 de ori rata de citire, așa că bucla merită doar când un prefix este recitit de mai multe ori. Defalcarea de cost de mai târziu arată cum a ieșit într-o rulare reală și ce categorie a dominat de fapt.

Plafonul de tokeni vine de la model, nu de la bugetul tău. Fable 5.1 îți oferă o fereastră de context de 1M tokeni cu până la 128K tokeni de output per răspuns, iar max_tokens este o limită dificilă pentru thinking plus textul răspunsului împreună. La effort ridicat ai nevoie de loc pentru ambele, motiv pentru care bucla de mai jos setează 16.000, nu ceva mai „rotund”.

Retenția datelor, nivelul de prioritate și watermarking

Câteva detalii de acces contează înainte să scrii cod. Două dintre ele îți vor opri cererile direct:

  • Fable 5.1 necesită retenție de date de 30 de zile și nu este disponibil cu retenție zero de date decât dacă Anthropic autorizează accesul. O cerere dintr-un workspace incompatibil întoarce un 400 invalid_request_error fără alt indiciu.

  • Modelul nu este acceptat pe Priority Tier. Fable 5 este, așa că îi prinde pe cei care migrează.

  • Outputul de text Fable 5.1 poartă watermark-ul de text al Anthropic. Nu adaugă tokeni și nu necesită schimbări în cerere.

Folosește Claude Fable 5.1 prin API pentru a construi un agent de dezvoltare conștient de repository

Fluxul nostru are două etape:

  1. O buclă de inspecție limitată citește fișierele permise ale proiectului.
  2. O cerere finală folosind outputuri structurate transformă contextul în plan. 

Proiectul de exemplu este un mic API Flask JSON pentru salvarea și căutarea bookmark-urilor, cu un app factory, trei blueprints, un modul de config, modele și un set de teste pytest. Folosesc limitarea ratei ca sarcină curentă pentru că agentul trebuie să inspecteze configurarea aplicației, rutele, configul și testele înainte să poată identifica fișierele și testele necesare. Codul complet și proiectul exemplu sunt disponibile în repository-ul GitHub.

Diagramă a unei cereri de feature care trece printr-un agent Claude Fable 5.1, o listă albă de căi și un proiect exemplu înainte de a returna un plan structurat

Cererile ajung la fișiere printr-o singură limită. Imagine de Autor.

Agentul poate folosi doar trei tool-uri: list_project_files, read_project_file și get_project_metadata. Claude nu accesează niciodată filesystem-ul direct. Cere o cale, iar codul tău decide dacă acea cale e permisă.

Configurarea API-ului Claude Fable 5.1 în Python

Pornește cu un mediu Python separat și păstrează cheia API pe server.

Cerințe preliminare

Ai nevoie de Python 3.10 sau mai nou și o cheie Anthropic API cu acces la claude-fable-5-1

Pentru a crea o cheie API, autentifică-te în Claude Console, deschide pagina API keys, fă clic pe Create key, apoi copiază cheia. Cel mai bine e să-i dai un nume care te ajută să-i reții scopul, să alegi o dată de expirare și să păstrezi cheia în siguranță.

Instalează SDK-ul și adaugă cheia API

Creează un mediu virtual și instalează pachetele:

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

Ține SDK-ul „pinned” deoarece funcțiile beta se schimbă frecvent. Actualizările de progres au nevoie de cel puțin 1.1.0, iar exemplele folosesc 1.3.0.

Pune cheia într-un .env fișier și adaugă .env la .gitignore înainte de primul commit. Aparține unui server pe care îl controlezi, niciodată într-un browser sau într-un repository accesibil. Expunerea ei poate permite utilizare neautorizată a API-ului și costuri pe input, output și operațiuni de cache.

ANTHROPIC_API_KEY=sk-ant-your-key-here

Cu asta la locul ei, clientul găsește singur cheia.

Fă primul tău apel API Claude Fable 5.1 în Python

Trimite cel mai mic request API posibil înainte de a construi ceva peste el.

Trimite primul request API

Inițializează clientul, trimite un singur mesaj de la utilizator și afișează metadatele răspunsului:

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 care arată un răspuns API Claude Fable 5.1 cu ID-ul modelului, motivul opririi, numărul de tokeni și ID-ul cererii

Primul apel returnează text plus metadate. Imagine de Autor.

Apelul next(...) selectează primul block de text. „Adaptive thinking” este mereu activ și nu poate fi dezactivat, astfel că un răspuns poate începe cu un block de thinking; trimiterea thinking: {"type": "disabled"} returnează un 400 în loc să-l oprească. Când un block de thinking vine primul, response.content[0].text ridică o excepție.

Soluția este să filtrezi după tipul block-ului în loc să presupui o poziție fixă. Loghează și response._request_id, deoarece suportul Anthropic îl folosește pentru a urmări o cerere.

Iată cererea folosită în acele exemple de planificare și efort. Îi cere agentului să inspecteze mai multe fișiere:

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

Păstrează textul neschimbat în timp ce compari nivelurile de efort și numărul de tokeni. Rezultatele descriu astfel setările API, nu un prompt diferit.

Setează efortul de raționare cu output_config

Setează efortul prin output_config. Acceptă low, medium, high, xhigh și max. Implicitul API este high.

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

Efortul poate afecta utilizarea de tokeni, comportamentul tool-urilor și latența. Am rulat aceeași cerere de feature de trei ori la fiecare dintre patru niveluri de efort; tabelul arată mediile:

Efort

Secunde

Tokeni de thinking

Total tokeni output

Cost

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

Tokenii de thinking sunt incluși în totalul tokenilor de output, deci nu aduna cele două coloane. În aceste rulari, low, medium și high au rămas apropiate ca latență și cost.

xhigh a durat de două ori și jumătate mai mult, a produs aproape de nouă ori mai mulți tokeni de output și a costat de opt ori mai mult. 

Concluzia: Pornește la high, coboară la medium pentru pașii de rutină și folosește niveluri mai mari doar când propriile teste arată o îmbunătățire măsurabilă. La low efort, modelul poate răspunde din memorie în loc să cheme un tool de retrieval. Dacă o tură are nevoie de informații proaspete, spune asta sau ridică nivelul.

Restrânge domeniul agentului cu un prompt de sistem

Promptul de sistem definește comportamentul agentului:

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."""

Ghidul de prompting Anthropic notează că modelul poate extinde sarcina sau se poate opri prea devreme. Promptul îi spune să rămână în scope și să încheie cu recomandări concrete. Un schema va gestiona formatul de output mai târziu.

Returnează un plan structurat cu Pydantic

Definește planul cu Pydantic astfel încât aplicația ta să-l poată valida și transmite altui cod:

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() convertește modelul Pydantic într-un schema JSON, îl trimite, validează răspunsul și returnează un obiect tipizat în parsed_output. Outputurile structurate sunt în general disponibile, deci nu e implicat niciun antet beta. Verifică mai întâi stop_reason pentru că un refuz, discutat mai târziu, sare peste schema și nu îți lasă nimic de parsat.

Acel rezultat generic din introducere a făcut un lucru corect: nu a numit fișiere pe care nu le putea vedea. Un schema validează structura, nu ancorarea factuală.

Claude Fable 5.1 vs. Fable 5: schimbări de migrare API

Înainte de a adăuga tool-uri, ia în calcul restricțiile de forțare a tool-urilor, compatibilitatea block-urilor de thinking și istoricul doar-adăugare.

  • Fable 5.1 respinge selecția forțată a tool-urilor. Secțiunea de buclă de tool-uri de mai jos arată eroarea și configurația auto folosită în schimb.

  • Block-urile de thinking sunt compatibile într-o singură direcție. Fable 5.1 citește block-uri de la modele Claude anterioare, dar niciun model anterior nu le poate citi pe ale lui. 

Când un router sau un fallback mută conversația pe un model mai vechi, API-ul elimină block-urile incompatibile înainte ca modelul țintă să le vadă. Istoricul rămas rămâne la locul lui, dar modelul mai vechi trebuie să planifice fără acele block-uri.

Editarea tururilor anterioare invalidează block-urile de thinking care au urmat. Asta poate strica tăierea istoriei și sumarizarea pe client.

Ghidul de migrare acoperă setul complet de schimbări.

Adaugă tool-uri read-only pentru repository

Acum oferă modelului context de repository prin tool-uri read-only.

Definește tool-urile read-only

Stratul de tool-uri are două părți: funcțiile Python care impun regulile de acces și schemele pe care Claude le poate apela.

Restricționează căile la rădăcina proiectului

Read-only nu înseamnă același lucru cu sigur. Un model poate cere la fel de ușor ../../.env ca pe config.py, deci protecția aparține codului tău, nu promptului:

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

Respinge căile absolute și componentele symlink, apoi rezolvă calea și confirmă că rămâne sub rădăcina proiectului. Cererea pentru ../.env va întoarce „path is outside the project root.” Eroarea returnată de tool îi permite agentului să continue cu fișierele permise.

Definește scheme stricte pentru tool-uri

Clasa de citire controlează ce poate deschide Python. Claude are de asemenea nevoie de scheme JSON care descriu cele trei acțiuni pe care le poate cere:

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 verifică argumentele când modelul alege un tool. Nu forțează un apel de tool, lucru important la Fable 5.1.

Rulează bucla de tool-uri pe mai multe ture

Pornește cu bucla de bază: trimite tool-urile, inspectează stop_reason, rulează ce a fost cerut, atașează rezultatele și repetă.

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 limitează cererile modelului, nu cheltuiala, deci impune o limită separată de cost dacă e nevoie. Bucla gestionează refusal, max_tokens și tool_use direct; alte motive de oprire încheie etapa de inspecție. Câmpul is_error îi spune modelului că o cale a fost refuzată, astfel încât să poată alege altă acțiune.

De ce alegerea forțată a tool-ului întoarce un 400

Pe Fable 5, puteai forța primul apel cu tool_choice: {"type": "any"}. Fable 5.1 întoarce această eroare înainte ca cererea să se execute:

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

Apelurile forțate ar sări peste thinking-ul mereu activ. Ține tool_choice pe auto, folosește schemele stricte definite mai sus și numește tool-urile în prompt când un pas are nevoie de unul.

Fable 5.1 uneori emite un apel de tool pe tură, în timp ce Fable 5 le grupa pe mai multe. Asta adaugă drumuri dus-întors. Adaugă această linie în prompt: „Cere fișierele independente în aceeași tură în loc de unul pe tură.” O rulare exemplu a grupat nouă cereri de fișiere independente, deși numărul variază.

Fă streaming la răspunsuri și actualizări de progres Claude Fable 5.1

Streaming-ul de text emite conținutul răspunsului pe măsură ce este generat; actualizările de progres acoperă pauzele dintre apelurile de tool.

Fă streaming la răspunsuri text

Proiectul complet folosește context_system() pentru a combina SYSTEM_PROMPT cu un rezumat al proiectului înainte de a porni stream-ul:

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() îți dă mesajul asamblat cu usage și motivul opririi odată ce stream-ul se golește. Bucățile de streaming nu garantează JSON complet, deci așteaptă mesajul final înainte de parsare.

Arată progresul între apelurile de tool

Streaming-ul de text nu acoperă întârzierile în timpul apelurilor de tool. Fable 5.1 poate scrie scurte actualizări de progres înainte de apelurile de tool. Sub thinking.display implicit de "omitted", block-urile de thinking specifice progresului sunt goale, deși modelul poate totuși produce un text de introducere normal.

Cu display: "updates" și antetul beta thinking-display-updates-2026-08-18 , documentația API definește o actualizare de progres lizibilă ca un block thinking nenul în timp ce raționarea rămâne ascunsă. În rularile live pentru acest proiect, câmpul thinking a rămas gol, iar statusul lizibil a sosit ca un block normal de text imediat înainte de tool_use. Helper-ul de aceea verifică ambele tipuri de block, iar bucla îl apelează doar pe turele care se termină cu 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

Mesajele de progres descriu fișierele pe care modelul plănuiește să le citească: „Voi citi cablarea app-ului, configul, extensiile, rutele publice și de auth și testele existente, deoarece acolo s-ar conecta limitarea de rată.” Afișează aceste mesaje și ignoră block-urile goale.

Terminal care arată o buclă de agent Claude Fable 5.1 cu utilizare de tokeni pe tură, mesaje de progres și citiri de fișiere grupate

Agentul citește fișiere raportând progresul. Imagine de Autor.

Fable 5.1 scrie mai puține dintre acestea decât Fable 5, mai ales la efort mai mare. Dacă interfața ta cere actualizări regulate, cere o linie de deschidere, mesaje de progres și un rezumat de închidere.

Schimbă efortul Claude Fable 5.1 pe parcursul conversației

Următoarea funcție e foarte reușită. După cum știm, agentul de repository nu are nevoie de aceeași profunzime de raționare la fiecare tură.

Schimbă efortul între ture

Într-o buclă de agent, scade efortul pentru turele de retrieval de rutină și ridică-l din nou pentru tura finală de planificare.

Cu antetul beta mid-conversation-output-config-2026-07-01 poți adăuga un mesaj de sistem care schimbă doar nivelul de efort:

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,
)

Noul nivel se aplică din următoarea tură a utilizatorului, nu la jumătatea turei curente, și nu invalidează prompt cache-ul. Schimbarea output_config.effort la nivel de cerere între apeluri îl invalidează. 

Agentul păstrează setarea de top la high, adaugă o directivă medium per mesaj înainte de retrieval-ul de rutină și adaugă o directivă high înainte de planul final. Un test în pereche a folosit 18 tokeni de output la efort mai mic față de 76 la setarea anterioară. Tratează acel rezultat ca exemplu, nu ca reducere așteptată.

Aplică o instrucțiune de sistem la o singură tură

Folosește o instrucțiune limitată la tură pentru a bloca citiri suplimentare de fișiere în timpul planificării finale.

Setează clear_at: "next_user_message" pe un mesaj de sistem cu antetul beta mid-conversation-system-clear-at-2026-08-21 . API-ul tratează textul său ca instrucțiune de sistem pentru tura curentă, apoi oprește randarea lui după următorul mesaj al utilizatorului. Rămâne în messages, deci istoricul anterior nu se schimbă, cache-ul continuă să se potrivească, iar mesajul șters nu costă tokeni de input.

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"} împiedică cererea finală să mai cheme un tool. Instrucțiunea limitată restrânge planul la fișierele pe care agentul le-a inspectat deja. Nu adăuga un reminder și să-l ștergi la următoarea cerere. Acea editare invalidează block-urile de thinking ulterioare.

Rezolvă erorile 400 ale block-urilor de thinking Claude Fable 5.1

O eroare The block is bound to a different conversation înseamnă că istoricul dinaintea unui block de thinking s-a schimbat. Fiecare block de thinking Fable 5.1 este legat de exact promptul de sistem, definițiile de tool-uri și mesajele care l-au precedat.

Rezultatul depinde de momentul în care a fost creat contul tău. 

  • Conturile create pe sau după 31 august 2026 primesc un 400 care spune că block-ul este legat de o conversație diferită. 

  • Pentru conturile create mai devreme, API-ul înregistrează nepotrivirea dar acționează asupra ei doar când cererea setează thinking.block_binding.prefix_mismatch_behavior

Poți detecta asta cu antetul beta thinking-binding-controls-2026-08-01, thinking.block_binding.prefix_mismatch_behavior setat la "drop_block" și array-ul input_transformations. Un istoric editat apare ca reason: "prefix_binding_mismatch". Rulează această verificare o dată împotriva integrării tale.

Următoarele operațiuni declanșează nepotrivirea:

  • Editarea, reordonarea sau eliminarea unei ture anterioare păstrându-le pe cele ulterioare

  • Injectarea de text per-cerere într-o tură anterioară și eliminarea lui la cererea următoare

  • Schimbarea conținutului sau ordinii promptului de top system sau a array-ului tools pe parcursul conversației

  • Servirea unor octeți diferiți de la o adresă URL de imagine sau document la o cerere ulterioară

Fiecare are un înlocuitor care păstrează legăturile:

  • Adaugă instrucțiuni cu mesaje de sistem în mijlocul conversației în loc să editezi system

  • Schimbă tool-urile cu schimbări mid-conversation în loc să schimbi array-ul de top. 

  • Taie istoricul cu context editing sau compaction pe server, care nu se contorizează ca editări. 

  •  Trimite înapoi block-urile de thinking neschimbate.

Mutarea markerelor cache_control și schimbarea efortului la nivel de cerere sunt ambele sigure și nu invalidează legăturile block-urilor de thinking. Totuși, schimbarea efortului de top repornește caching-ul de prompt, așa că folosește efort per-mesaj când prefixul cache-uit ar trebui să rămână neschimbat.

Prompt caching și costul API-ului Claude Fable 5.1

Rularea următoare separă inputul proaspăt, scrierile în cache, citirile din cache și costurile de output.

Adaugă prompt caching automat

Prompt caching reduce costul contextului care se repetă între ture. Istoricul care crește schimbă locul unde ar trebui să stea pragul, deci caching-ul automat se potrivește mai bine aici.

Un câmp de top cache_control mută pragul la cel mai nou block cache-uibil la fiecare cerere:

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

Un prefix cache-uibil mai scurt de 512 tokeni nu este cache-uit pe Fable 5.1, chiar dacă e marcat cu cache_control. API-ul îl procesează normal și întoarce zero la ambii contori de cache. Scrierea unui prefix de 583 tokeni a costat 0,0073 $, iar citirea lui la următoarea tură a costat 0,00015 $. A doua tură tot a trebuit să-și scrie partea nouă în cache, deci o lovire de cache nu a eliminat orice cost de input.

Estimează costul API-ului cu cache

response.usage raportează separat inputul proaspăt, crearea cache-ului, citirile din cache și outputul. Prețuiește toate cele patru contoare pe cont propriu; însumarea doar a inputului și outputului ascunde costul de scriere în cache și exagerează prețul loviturilor de cache.

Iată defalcarea costurilor dintr-o rulare completă care a citit 12 fișiere în trei ture și a produs un plan final:

Linie de cost

Tokeni

Cost estimat

Pondere

Output

5.713

$0.2857

59,4%

Scrieri în cache

15.426

$0.1928

40,1%

Input proaspăt

50

$0.0005

0,1%

Citiri din cache

6.549

$0.0016

0,3%

Total

27.738

$0.4806

100%

Citirile din cache au reprezentat o fracțiune de mai puțin de jumătate de procent din această estimare. La vechea rată a lui Fable 5, rularea ar fi costat aproximativ 0,4855 $ în loc de 0,4806 $. Economiile cresc când fiecare tură reutilizează mult mai mult context.

În această rulare, outputul a produs aproape 60% din estimare, iar scrierile în cache aproximativ 40%. La rata de cinci minute folosită aici, un token de scriere în cache costă de 50 de ori mai mult decât un token de citire din cache. O scriere în cache de o oră costă de 80 de ori mai mult.

Gestionează refuzurile și fallback-urile Claude Fable 5.1

Un refuz și o cerere eșuată au nevoie de comportamente diferite în aplicație.

Detectează refuzurile înainte de a parsa outputul

Un refuz înainte de output vine ca HTTP 200 cu stop_reason: "refusal", conținut gol și stop_details. Categoria sa poate fi null. Un refuz mai târziu într-un stream poate veni după output parțial, pe care aplicația ar trebui să-l arunce. Un try/except în jurul apelului nu va prinde niciunul dintre cazuri.

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})."

Gestionează-l ca stare de aplicație. Dacă o cerere permisă e neclară, rescrie-o mai precis. Nu construi logică de retry al cărei scop este să ocolească clasificatorul.

Un refuz sosește ca HTTP 200. Imagine de Autor.

Configurează fallback pe server

Fallback-ul pe server poate reîncerca o cerere respinsă pe alt model, folosind fallbacks: "default" cu antetul beta server-side-fallback-2026-07-01 . Țintele permise pentru Fable 5.1 sunt Opus 4.8 și Opus 5

Fallback-ul implicit rulează doar când categoria refuzului are o țintă recomandată. Un refuz reasoning_extraction testat nu a declanșat fallback; inspectează usage.iterations în loc să presupui că fiecare refuz va reîncerca. După cum am menționat mai devreme, trecerea la un model mai vechi renunță și la block-urile de thinking Fable 5.1.

Servește agentul Claude Fable 5.1 cu FastAPI

Agentul local poate acum servi același flux printr-un API HTTP.

Creează endpoint-ul de plan

Dacă ai nevoie doar de un script local, sari peste această secțiune. Pentru un serviciu web, folosește FastAPI cu AsyncAnthropic. Creează un singur client pentru proces într-un lifespan handler. Importează schema și prompturile din modulul agent existent.

@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))

Observă că apelantul trimite un nume de proiect, nu o cale. resolve_project() îl map-ează la unul dintr-un set mic de rădăcini permise, astfel încât o cerere nu poate cere serverului să citească ceva arbitrar. Acest serviciu map-ează refuzurile la 422 ca alegere de aplicație. API-ul Claude însuși le returnează ca HTTP 200.

Rulează-l cu uvicorn app:app --reload. Documentația interactivă este disponibilă la http://localhost:8000/docs.

Endpoint-ul returnează un plan cu un cost estimat. Video de Autor.

Endpoint-ul /plan/stream rulează inspecția într-o sarcină de fundal, plasează evenimentele de progres și tool pe un asyncio.Queue și le emite prin StreamingResponse. Când stream-ul se închide, generatorul anulează sarcina de fundal. Interfața Streamlit din repozitoriu redă același flux de evenimente.

Streamlit arată progresul live al agentului. Video de Autor.

Listă de verificare pentru deploy-ul agentului Claude Fable 5.1

Limitările și verificările construite mai devreme rămân parte a serviciului. Înainte de deploy, adaugă piesele operaționale care nu sunt vizibile într-o rulare locală.

  • Revizuiește cele două retry-uri implicite ale SDK-ului pentru răspunsuri 429 și 5xx, apoi setează max_retries și timeouts în acord cu bugetul de latență al serviciului

  • Setează un timeout pe cerere și confirmă că anularea existentă a task-ului SSE oprește munca în desfășurare când un client se deconectează

  • Loghează pentru fiecare rulare ID-ul modelului, versiunea SDK-ului, ID-ul cererii, motivul opririi și cele patru categorii de tokeni

  • Alertează la creșterea scrierilor în cache, a tokenilor de output, a refuzurilor și a rulărilor care ating plafonul de ture

  • Confirmă că setarea de retenție a contului se potrivește cu cerința modelului

  • „Pinează” SDK-ul și reverifică antetele beta înainte de fiecare release

Când să folosești Claude Fable 5.1 în loc de Opus 5 sau Sonnet 5

  • Anthropic recomandă Opus 5 ca implicit rezonabil.
  • Testează Fable 5.1 când Opus 5 nu face față la analiză pe repository lungi, debugging dificil sau sarcini agentice cu context mare.
  • Pentru munca pe repository și sarcini cotidiene, compară Sonnet 5 și Opus 5 la calitate, latență și cost.
  • Pentru clasificare, extragere, răspunsuri scurte și cereri mai simple, Sonnet 5 e un implicit bun; pentru cele mai ușoare sarcini, Haiku 4.5 ar putea fi suficient de puternic.

Nu alege Fable 5.1 doar pentru că e mai nou. O cerere unică poate folosi tot effort și outputuri structurate; și streaming-ul funcționează. Nu beneficiază de buclă sau de caching-ul de prefix repetat folosite aici.

Gânduri finale

Planul generic din primul apel a devenit util abia după ce agentul a citit repository-ul. În rularea finalizată, a inspectat 12 fișiere în trei ture, în timp ce outputul și scrierile în cache au reprezentat 99,5% din costul estimat. Aș păstra limita pe căi și istoricul doar-adăugare, apoi aș testa dacă efortul mai mic reduce costul fără ca modelul să sară peste tool-urile de repository.

Dacă un singur răspuns poate rezolva sarcina, oprește-te la outputuri structurate. Folosește bucla de tool-uri când răspunsul trebuie să depindă de fișiere din repository sau să raporteze progresul între apeluri.

Pentru detalii despre selecția modelului, îți recomand cursul nostru Introducere în modelele Claude. Pentru prompting și fluxuri de lucru cu agenți, vezi cursul nostru Software Development with Cursor.

Întrebări frecvente

Poate Claude Fable 5.1 să citească imagini la fel ca și cod?

Da. Acceptă input de imagine și poate citi grafice și PDF-uri. Am lăsat partea de viziune în afara exemplului principal pentru că planul de repository nu are nevoie de ea. Dacă aș extinde acest agent pentru a planifica o schimbare de UI, aș trimite captura de ecran curentă odată cu cererea de feature. Redu-i rezoluția mai întâi dacă detaliile vizuale mici nu afectează sarcina.

De ce agentul meu a devenit mai lent după trecerea de la Fable 5?

Verifică rezultatele tool-urilor înainte să dai vina pe model. Dacă instrucțiunea de batching de mai devreme este deja prezentă, compară atât numărul, cât și dimensiunile lor. Cititorul curent limitează fiecare fișier la 40.000 de octeți. Dacă tot e prea mare, adaugă argumente pentru interval de linii sau căutare astfel încât tool-ul să poată returna doar secțiunile relevante.

De ce returnează Claude Fable 5.1 un 400 invalid_request_error?

Nu îl retrimite întâi. Un invalid_request_error de obicei indică o formă a cererii sau o setare de cont care trebuie schimbată. În acest proiect, cauzele probabile sunt tool_choice forțat, o setare de retenție incompatibilă, un prefix editat cu thinking păstrat sau un câmp beta trimis fără antetul său asociat. Rezolvă cauza indicată, apoi trimite cererea din nou.

Ar trebui să cache-uiesc fișierele sursă sau un rezumat?

Folosesc această regulă: cache-uiește fișierele sursă când exactitatea codului contează pe mai multe ture. Dacă pașii ulteriori au nevoie doar de arhitectură sau de harta fișierelor, cache-uiește un rezumat. Rezumatul costă mai puțini tokeni, dar poate omite linia aceea de care are nevoie planul final.

Poate Batch API să ruleze acest agent?

Nu de una singură. Batch API trimite cereri Messages individuale; nu rulează această buclă de tool-uri pe client. Aș folosi-o pentru review-uri de repository autonome când progresul live nu e necesar. Rularea buclei complete în batch-uri cere propriul tău cod care să proceseze cererile de tool dintr-un batch înainte de a-l trimite pe următorul.

Subiecte

Învăță AI cu DataCamp!

track

Inginer AI asociat pentru dezvoltatori

26 oră
Învață cum să integrezi AI în aplicații software folosind API-uri și biblioteci open-source. Începe-ți astăzi călătoria spre a deveni Inginer AI!
Vezi detaliiRight Arrow
Începeți Cursul
Vezi mai multRight Arrow