Program
Saat saya mencoba model baru melalui panggilan API, respons pertama biasanya tidak banyak memberi tahu. Run Fable 5.1 pertama saya mengembalikan struktur yang valid dan rencana generik. Saya ingin tahu apa yang terjadi setelah percakapan memanjang: bisakah aplikasi menjaga riwayatnya tetap utuh, memeriksa file tanpa membaca di luar proyek, melaporkan progres, dan menunjukkan asal biaya?
Ulasan Claude Fable 5.1 kami membahas peluncuran, benchmark, dan perbandingan model yang lebih luas. Di sini, kita mulai dari panggilan Python kecil lalu membangun agent loop di sekelilingnya. Agen final menerima permintaan fitur, membaca proyek Flask, dan mengembalikan rencana yang terkait dengan file yang benar-benar diperiksanya.
Kita akan membahas cara:
- Melakukan panggilan API Claude Fable 5.1 dan membaca blok konten dengan aman
- Menetapkan reasoning effort, serta mengubahnya di tengah percakapan (beta)
- Membatasi instruksi sistem ke satu giliran (beta)
- Mengembalikan rencana terstruktur dengan Pydantic
- Menambahkan tool repositori read-only dengan batas root proyek
- Menjalankan loop alat multi-turn
- Membaca pembaruan progres agen di antara panggilan alat (beta)
- Menjaga blok thinking tetap valid dengan riwayat append-only
- Meng-cache konteks berulang dan memperkirakan biaya permintaan sesuai tarif yang dipublikasikan
- Menangani penolakan dan mengekspos agen melalui FastAPI
Fitur beta menggunakan header bertanggal, jadi cocokkan dengan dokumentasi Anthropic sebelum Anda merilisnya.
Berapa Biaya Menjalankan Claude Fable 5.1 dalam Agent Loop?
Agen mengirim ulang prompt sistem, definisi alat, dan konteks repositori yang sama pada setiap giliran, jadi tarif yang menentukan tagihan Anda adalah cache read, bukan tarif input.
Fable 5.1 berharga $10 per sejuta token input dan $50 per sejuta token output, tidak berubah dari Fable 5. Cache read berharga $0,25 per juta, turun dari $1, dan cache write lima menit tetap $12,50 per juta. Panduan Claude Fable 5.1 kami memiliki tabel tarif lengkap dan estimasi penghematan dari Anthropic.
Membaca prefiks yang di-cache itu murah. Menulisnya tidak, yakni 50 kali tarif baca, jadi loop baru menguntungkan saat prefiks dibaca ulang beberapa kali. Rincian biaya nanti menunjukkan hasil run nyata, dan kategori mana yang sebenarnya mendominasi.
Batas token berasal dari model, bukan anggaran Anda. Fable 5.1 memberi Anda context window 1 juta token dengan hingga 128K token keluaran per respons, dan max_tokens adalah batas keras untuk thinking dan teks respons bersama-sama. Pada effort tinggi Anda butuh ruang untuk keduanya, itulah mengapa agent loop di bawah menetapkan 16.000, bukan angka yang lebih rapi.
Retensi data, tingkatan prioritas, dan watermark
Beberapa detail akses penting sebelum Anda menulis kode. Dua di antaranya akan langsung menghentikan permintaan Anda:
-
Fable 5.1 memerlukan retensi data 30 hari dan tidak tersedia di bawah retensi nol kecuali Anthropic mengotorisasi akses. Permintaan dari workspace yang tidak kompatibel mengembalikan 400
invalid_request_errortanpa petunjuk lain. -
Model tidak didukung pada Priority Tier. Fable 5 didukung, sehingga ini sering menjebak saat migrasi.
-
Keluaran teks Fable 5.1 membawa watermark teks Anthropic. Ini tidak menambah token dan tidak memerlukan perubahan permintaan.
Gunakan Claude Fable 5.1 via API untuk Membangun Agen Pengembang yang Paham Repositori
Alur kerja kami memiliki dua tahap:
- Loop inspeksi berbatas membaca file proyek yang diizinkan.
- Permintaan akhir menggunakan structured outputs mengubah konteks tersebut menjadi rencana.
Proyek contoh adalah API JSON Flask kecil untuk menyimpan dan mencari bookmark, dengan app factory, tiga blueprint, modul konfigurasi, model, dan suite pytest. Saya menggunakan rate limiting sebagai tugas berjalan karena agen harus memeriksa setup app, rute, konfigurasi, dan pengujian sebelum dapat mengidentifikasi file dan tes yang diperlukan. Kode lengkap dan proyek contoh tersedia di repositori GitHub.

Permintaan menjangkau file melalui satu batas. Gambar oleh Penulis.
Agen hanya dapat menggunakan tiga alat: list_project_files, read_project_file, dan get_project_metadata. Claude tidak pernah mengakses filesystem secara langsung. Ia meminta sebuah path, dan kode Anda yang memutuskan apakah path itu diizinkan.
Menyiapkan API Claude Fable 5.1 di Python
Mulailah dengan lingkungan Python terpisah dan simpan kunci API di server.
Prasyarat
Anda memerlukan Python 3.10 atau lebih baru dan kunci API Anthropic dengan akses ke claude-fable-5-1.
Untuk membuat kunci API, masuk ke Claude Console, buka halaman API keys, klik Create key, lalu salin kuncinya. Praktik terbaik adalah memberinya nama yang membantu Anda mengingat tujuannya, memilih tanggal kedaluwarsa, dan menyimpan kuncinya dengan aman.
Instal SDK dan tambahkan kunci API
Buat virtual environment dan instal paket-paketnya:
python -m venv .venv
source .venv/bin/activate # macOS atau Linux
.venv\Scripts\Activate.ps1 # Windows PowerShell
pip install anthropic==1.3.0 pydantic fastapi uvicorn python-dotenv
Pertahankan versi SDK tetap dipatok karena fitur beta sering berubah. Pembaruan progres membutuhkan setidaknya 1.1.0, dan contoh menggunakan 1.3.0.
Tempatkan kunci di .env file dan tambahkan .env ke .gitignore sebelum commit pertama Anda. Kunci harus berada di server yang Anda kendalikan, bukan di browser atau repositori yang dapat diakses. Mengeksposnya dapat memungkinkan penggunaan API tanpa izin dan penagihan pada operasi input, output, dan cache.
ANTHROPIC_API_KEY=sk-ant-your-key-here
Dengan itu, klien akan menemukan kuncinya sendiri.
Lakukan Panggilan API Claude Fable 5.1 Pertama Anda di Python
Kirim permintaan API sekecil mungkin sebelum membangun apa pun di atasnya.
Kirim permintaan API pertama
Inisialisasi klien, kirim satu pesan pengguna, dan cetak metadata respons:
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}")

Panggilan pertama mengembalikan teks plus metadata. Gambar oleh Penulis.
Panggilan next(...) memilih blok teks pertama. Adaptive thinking selalu aktif dan tidak bisa dimatikan, jadi respons dapat dimulai dengan blok thinking; mengirim thinking: {"type": "disabled"} mengembalikan 400 alih-alih mematikannya. Ketika blok thinking datang lebih dulu, response.content[0].text akan memicu exception.
Solusinya adalah memfilter berdasarkan tipe blok alih-alih mengasumsikan posisi tetap. Catat juga response._request_id karena dukungan Anthropic menggunakannya untuk melacak permintaan.
Berikut permintaan yang digunakan pada contoh perencanaan dan effort. Ini mengharuskan agen memeriksa beberapa file:
feature_request = (
"Add rate limiting to the public API endpoints so one client cannot exhaust "
"the search endpoint or brute force the token endpoint."
)
Biarkan teks itu tidak berubah saat membandingkan level effort dan jumlah token. Hasilnya kemudian menjelaskan pengaturan API, bukan prompt yang berbeda.
Atur reasoning effort dengan output_config
Tetapkan reasoning effort melalui output_config. Ini menerima low, medium, high, xhigh, dan max. Default API adalah high.
response = client.messages.create(
model=MODEL,
max_tokens=8192,
output_config={"effort": "high"},
messages=[{"role": "user", "content": feature_request}],
)
Effort dapat memengaruhi penggunaan token, perilaku alat, dan latensi. Saya menjalankan permintaan fitur yang sama tiga kali pada masing-masing dari empat level effort; tabel menunjukkan rata-ratanya:
|
Effort |
Detik |
Token thinking |
Total token output |
Biaya |
|---|---|---|---|---|
|
|
7,7 |
111 |
173 |
$0,0093 |
|
|
8,1 |
129 |
186 |
$0,0099 |
|
|
7,9 |
136 |
199 |
$0,0106 |
|
|
20,0 |
151 |
1.764 |
$0,0888 |
Token thinking sudah termasuk dalam total token output, jadi jangan menjumlahkan dua kolom itu. Pada run ini, low, medium, dan high tetap berdekatan dalam hal latensi dan biaya.
xhigh memakan waktu dua setengah kali lebih lama, menghasilkan hampir sembilan kali token output, dan berbiaya delapan kali lipat.
Intinya: Mulai dari high, turunkan ke medium untuk langkah rutin, dan gunakan level lebih tinggi hanya ketika pengujian Anda sendiri menunjukkan peningkatan terukur. Pada effort low model bisa menjawab dari ingatan alih-alih memanggil alat retrieval. Jika sebuah giliran butuh informasi segar, katakan atau naikkan level.
Batasi cakupan agen dengan system prompt
System prompt mendefinisikan perilaku agen:
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."""
Panduan prompting Anthropic mencatat bahwa model bisa memperluas tugas atau berhenti terlalu cepat. Prompt ini memintanya tetap pada lingkup dan menutup dengan panduan konkret. Skema akan menangani format output nanti.
Kembalikan Rencana Terstruktur Dengan Pydantic
Definisikan rencana dengan Pydantic agar aplikasi Anda dapat memvalidasinya dan meneruskannya ke kode lain:
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() mengonversi model Pydantic menjadi skema JSON, mengirimkannya, memvalidasi balasan, dan mengembalikan objek bertipe pada parsed_output. Structured outputs tersedia secara umum, jadi tidak perlu header beta. Periksa stop_reason terlebih dahulu karena penolakan, dibahas nanti, melewati skema dan tidak menyisakan apa pun untuk diurai.
Hasil generik dari pendahuluan tadi melakukan satu hal dengan benar: tidak menyebut file yang tidak dapat dilihatnya. Skema memvalidasi struktur, bukan landasan faktual.
Claude Fable 5.1 vs. Fable 5: Perubahan Migrasi API
Sebelum menambahkan alat, perhatikan pembatasan forced-tool, kompatibilitas blok thinking, dan riwayat append-only.
-
Fable 5.1 menolak pemilihan alat paksa. Bagian tool-loop di bawah ini menunjukkan error dan konfigurasi
autoyang digunakan sebagai gantinya. -
Blok thinking kompatibel hanya searah. Fable 5.1 dapat membaca blok dari model Claude sebelumnya, tetapi tidak ada model sebelumnya yang dapat membaca blok miliknya.
Saat router atau fallback memindahkan percakapan ke model yang lebih lama, API menghapus blok yang tidak kompatibel sebelum model target melihatnya. Riwayat yang tersisa tetap ada, tetapi model lama harus merencanakan tanpa blok tersebut.
Mengedit giliran sebelumnya membuat blok thinking setelahnya menjadi tidak valid. Ini bisa merusak pemangkasan riwayat dan ringkasan sisi klien.
Panduan migrasi membahas set perubahan lengkap.
Tambahkan Alat Repositori Read-Only
Sekarang berikan model konteks repositori melalui alat read-only.
Definisikan alat read-only
Lapisan alat memiliki dua bagian: fungsi Python yang menegakkan aturan akses dan skema yang dapat dipanggil Claude.
Batasi path ke root proyek
Read-only tidak sama dengan aman. Model bisa meminta ../../.env semudah config.py, jadi guard harus ada di kode Anda, bukan di 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
Tolak path absolut dan komponen symlink, lalu resolve path dan konfirmasi bahwa ia tetap berada di bawah root proyek. Meminta ../.env mengembalikan "path is outside the project root." Error alat yang dikembalikan memungkinkan agen melanjutkan dengan file yang diizinkan.
Definisikan skema alat yang ketat
Kelas pembaca mengontrol apa yang boleh dibuka Python. Claude juga memerlukan skema JSON yang menjelaskan tiga aksi yang dapat dimintanya:
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 memeriksa argumen saat model memilih alat. Ini tidak memaksa pemanggilan alat, yang penting untuk Fable 5.1.
Jalankan loop alat multi-turn
Mulai dengan loop dasar: kirim alat, periksa stop_reason, jalankan yang diminta, tambahkan hasilnya, dan ulangi.
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 membatasi permintaan model, bukan pengeluaran, jadi terapkan batas biaya terpisah jika diperlukan. Loop menangani refusal, max_tokens, dan tool_use secara langsung; alasan berhenti lainnya mengakhiri tahap inspeksi. Field is_error memberi tahu model bahwa sebuah path ditolak, sehingga dapat memilih aksi lain.
Mengapa pemaksaan pilihan alat mengembalikan 400
Di Fable 5, Anda bisa memaksa panggilan pertama dengan tool_choice: {"type": "any"}. Fable 5.1 mengembalikan error ini sebelum permintaan dijalankan:
tool_choice: type "tool" and "any" are not supported for this model.
Panggilan paksa akan melewati thinking yang selalu aktif. Biarkan tool_choice pada auto, gunakan skema ketat yang didefinisikan di atas, dan sebutkan alat di prompt ketika suatu langkah membutuhkannya.
Fable 5.1 kadang mengeluarkan satu panggilan alat per giliran, sementara Fable 5 membundel beberapa. Itu menambah round-trip. Tambahkan baris ini ke prompt: “Minta file independen dalam giliran yang sama alih-alih satu per giliran.” Contoh run membundel sembilan permintaan file independen, meskipun jumlahnya bervariasi.
Streaming Respons dan Pembaruan Progres Claude Fable 5.1
Streaming teks mengeluarkan konten respons saat dibuat; pembaruan progres mencakup jeda di antara panggilan alat.
Streaming respons teks
Proyek penuh menggunakan context_system() untuk menggabungkan SYSTEM_PROMPT dengan ringkasan proyek sebelum memulai stream:
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() memberi Anda pesan yang telah dirakit dengan usage dan alasan berhenti setelah stream selesai. Potongan streaming tidak dijamin berisi JSON lengkap, jadi tunggu pesan final sebelum mengurai.
Tampilkan progres di antara panggilan alat
Streaming teks tidak mencakup jeda selama panggilan alat. Fable 5.1 dapat menulis pembaruan progres singkat sebelum panggilan alat. Di bawah default thinking.display yaitu "omitted", blok thinking khusus progres kosong, meskipun model masih dapat menghasilkan teks pengantar biasa.
Dengan display: "updates" dan header beta thinking-display-updates-2026-08-18 , dokumentasi API mendefinisikan pembaruan progres yang dapat dibaca sebagai blok thinking yang tidak kosong saat penalaran tetap tersembunyi. Pada run langsung untuk proyek ini, field thinking tetap kosong dan status yang dapat dibaca datang sebagai blok text tepat sebelum tool_use. Karena itu, helper memeriksa kedua tipe blok, dan loop memanggilnya hanya pada giliran yang berakhir dengan 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
Pesan progres menjelaskan file yang direncanakan model untuk dibaca: "Saya akan membaca wiring app, config, extensions, rute publik dan auth, serta tes yang ada, karena di sanalah rate limiting akan di-hook in." Tampilkan pesan tersebut dan abaikan blok kosong.

Agen membaca file sambil melaporkan progres. Gambar oleh Penulis.
Fable 5.1 menulis lebih sedikit pesan ini dibanding Fable 5, terutama pada effort lebih tinggi. Jika antarmuka Anda memerlukan pembaruan reguler, mintalah kalimat pembuka, pesan progres, dan rekap penutup.
Ubah Effort Claude Fable 5.1 di Tengah Percakapan
Fitur berikut sangat menarik. Seperti kita tahu, agen repositori tidak memerlukan kedalaman penalaran yang sama pada setiap giliran.
Ubah effort antar giliran
Dalam agent loop, turunkan effort untuk giliran retrieval rutin dan naikkan kembali untuk giliran perencanaan akhir.
Dengan header beta mid-conversation-output-config-2026-07-01 Anda dapat menambahkan pesan sistem yang hanya mengubah level effort:
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,
)
Level baru berlaku mulai giliran pengguna berikutnya, bukan di tengah giliran saat ini, dan tidak membatalkan cache prompt. Mengubah output_config.effort tingkat atas di antara permintaan memang membatalkannya.
Agen mempertahankan pengaturan tingkat atas pada high, menambahkan direktif per-pesan medium sebelum retrieval rutin, dan menambahkan direktif high sebelum rencana akhir. Uji berpasangan menggunakan 18 token output pada effort lebih rendah versus 76 pada pengaturan sebelumnya. Anggap itu contoh, bukan penghematan yang diharapkan.
Terapkan instruksi sistem untuk satu giliran
Gunakan instruksi berskala giliran untuk memblokir pembacaan file tambahan selama perencanaan akhir.
Atur clear_at: "next_user_message" pada pesan sistem dengan header beta mid-conversation-system-clear-at-2026-08-21 . API memperlakukan teksnya sebagai instruksi sistem untuk giliran saat ini, lalu berhenti merendernya setelah pesan pengguna berikutnya. Pesan tetap di messages, sehingga riwayat sebelumnya tidak berubah, cache tetap cocok, dan pesan yang dihapus tidak menimbulkan biaya token 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"} menjaga permintaan akhir tidak memanggil alat lain. Instruksi berskala giliran membatasi rencana pada file yang sudah diperiksa agen. Jangan menambahkan pengingat lalu menghapusnya pada permintaan berikutnya. Pengeditan itu membuat blok thinking selanjutnya tidak valid.
Perbaiki Error 400 Thinking-Block Claude Fable 5.1
Error The block is bound to a different conversation berarti riwayat sebelum blok thinking berubah. Setiap blok thinking Fable 5.1 terikat pada prompt sistem, definisi alat, dan pesan yang tepat sebelumnya.
Hasilnya bergantung pada kapan akun Anda dibuat.
-
Akun yang dibuat pada atau setelah 31 Agustus 2026 mendapatkan 400 yang menyatakan blok terikat pada percakapan berbeda.
-
Untuk akun yang dibuat lebih awal, API mencatat ketidaksesuaian namun hanya bertindak saat permintaan menetapkan
thinking.block_binding.prefix_mismatch_behavior.
Anda dapat mendeteksinya dengan header beta thinking-binding-controls-2026-08-01, thinking.block_binding.prefix_mismatch_behavior disetel ke "drop_block", dan array input_transformations. Riwayat yang diedit muncul sebagai reason: "prefix_binding_mismatch". Jalankan pemeriksaan ini sekali terhadap integrasi Anda.
Operasi berikut memicu ketidaksesuaian:
-
Mengedit, mengurutkan ulang, atau menghapus giliran sebelumnya sambil mempertahankan yang sesudahnya
-
Menyuntikkan teks per-permintaan ke giliran lebih awal dan menghapusnya di permintaan berikutnya
-
Mengubah konten atau urutan prompt
systemtingkat atas atau arraytoolsdi tengah percakapan -
Menyajikan byte berbeda dari URL gambar atau dokumen pada permintaan selanjutnya
Masing-masing memiliki pengganti yang menjaga binding tetap utuh:
-
Tambahkan instruksi dengan pesan sistem di tengah percakapan alih-alih mengedit
system. -
Ubah alat dengan perubahan alat di tengah percakapan alih-alih mengubah array tingkat atas.
-
Pangkas riwayat dengan context editing atau compaction sisi server yang tidak dihitung sebagai pengeditan.
-
Teruskan blok thinking kembali tanpa perubahan.
Memindahkan penanda cache_control dan mengubah effort tingkat permintaan sama-sama aman dan tidak membuat binding blok thinking tidak valid. Namun, mengubah effort tingkat atas memulai ulang caching prompt, jadi gunakan effort per-pesan ketika prefiks yang di-cache harus tetap sama.
Prompt Caching dan Biaya API Claude Fable 5.1
Run berikut memisahkan biaya input segar, cache write, cache read, dan output.
Tambahkan prompt caching otomatis
Prompt caching mengurangi biaya konteks yang berulang di berbagai giliran. Riwayat yang bertambah mengubah posisi breakpoint, jadi caching otomatis lebih cocok di sini.
Field cache_control tingkat atas memindahkan breakpoint ke blok terbaru yang dapat di-cache pada setiap permintaan:
response = client.beta.messages.create(
model=MODEL,
cache_control={"type": "ephemeral"},
system=system,
tools=TOOLS,
messages=messages,
# Other request fields...
)
Prefiks yang dapat di-cache dengan panjang kurang dari 512 token tidak di-cache pada Fable 5.1, bahkan jika ditandai dengan cache_control. API memprosesnya secara normal dan mengembalikan nol untuk kedua penghitung cache. Menulis prefiks 583 token berbiaya $0,0073; membacanya pada giliran berikutnya berbiaya $0,00015. Giliran kedua masih harus menulis bagiannya yang baru ke cache, jadi cache hit tidak menghapus semua biaya input.
Perkirakan biaya API yang sadar cache
response.usage melaporkan input segar, pembuatan cache, pembacaan cache, dan output secara terpisah. Harga keempat penghitung secara mandiri; menjumlahkan hanya input dan output menyembunyikan biaya cache write dan melebihkan harga cache hit.
Berikut rincian biaya dari satu run penuh yang membaca 12 file dalam tiga giliran dan menghasilkan rencana akhir:
|
Item baris |
Token |
Perkiraan biaya |
Porsi |
|---|---|---|---|
|
Output |
5.713 |
$0,2857 |
59,4% |
|
Cache write |
15.426 |
$0,1928 |
40,1% |
|
Input segar |
50 |
$0,0005 |
0,1% |
|
Cache read |
6.549 |
$0,0016 |
0,3% |
|
Total |
27.738 |
$0,4806 |
100% |
Cache read menyumbang sebagian kecil dari kurang dari setengah persen estimasi ini. Pada tarif lama Fable 5, run ini akan berbiaya sekitar $0,4855 alih-alih $0,4806. Penghematan meningkat ketika setiap giliran menggunakan kembali konteks jauh lebih banyak.
Pada run ini, output menghasilkan hampir 60% estimasi, dan cache write sekitar 40%. Pada tarif lima menit yang digunakan di sini, satu token cache write berharga 50 kali token cache read. Cache write satu jam berharga 80 kali lipat.
Tangani Penolakan dan Fallback Claude Fable 5.1
Penolakan dan permintaan gagal memerlukan perilaku aplikasi yang berbeda.
Deteksi penolakan sebelum mengurai output
Penolakan sebelum output datang sebagai HTTP 200 dengan stop_reason: "refusal", konten kosong, dan stop_details. Kategorinya bisa null. Penolakan kemudian dalam stream bisa mengikuti output parsial, yang sebaiknya dibuang oleh aplikasi. try/except di sekitar panggilan tidak akan menangkap keduanya.
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})."
Tangani sebagai status aplikasi. Jika permintaan yang diizinkan tidak jelas, tulis ulang dengan lebih presisi. Jangan membangun logika retry yang tujuannya mengakali classifier.

Penolakan datang sebagai HTTP 200. Gambar oleh Penulis.
Konfigurasi fallback sisi server
Fallback sisi server dapat mencoba ulang permintaan yang ditolak pada model lain, menggunakan fallbacks: "default" dengan header beta server-side-fallback-2026-07-01 . Target yang diizinkan untuk Fable 5.1 adalah Opus 4.8 dan Opus 5.
Fallback default hanya berjalan ketika kategori penolakan memiliki target yang direkomendasikan. Penolakan reasoning_extraction yang diuji tidak memicu fallback; periksa usage.iterations alih-alih mengasumsikan setiap penolakan akan mencoba ulang. Seperti disebutkan sebelumnya, berpindah ke model yang lebih lama juga menghapus blok thinking Fable 5.1.
Layani Agen Claude Fable 5.1 Dengan FastAPI
Agen lokal kini dapat melayani alur kerja yang sama melalui HTTP API.
Buat endpoint plan
Jika Anda hanya butuh skrip lokal, lewati bagian ini. Untuk layanan web gunakan FastAPI dengan AsyncAnthropic. Buat satu klien untuk proses dalam lifespan handler. Impor skema dan prompt dari modul agen yang ada.
@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))
Perhatikan pemanggil mengirim nama proyek, bukan path. resolve_project() memetakannya ke salah satu dari sejumlah kecil root yang diizinkan, sehingga permintaan tidak dapat meminta server membaca sembarang lokasi. Layanan ini memetakan penolakan ke 422 sebagai pilihan aplikasi. API Claude sendiri mengembalikannya sebagai HTTP 200.
Jalankan dengan uvicorn app:app --reload. Dokumentasi interaktif tersedia di http://localhost:8000/docs.
Endpoint mengembalikan rencana dengan perkiraan biaya. Video oleh Penulis.
Endpoint /plan/stream menjalankan inspeksi dalam tugas latar belakang, menempatkan event progres dan alat pada asyncio.Queue, dan memancarkannya melalui StreamingResponse. Saat stream ditutup, generator membatalkan tugas latar belakang. Antarmuka Streamlit di repositori merender stream event yang sama.
Streamlit menampilkan progres live agen. Video oleh Penulis.
Daftar Periksa Deployment Agen Claude Fable 5.1
Batas dan pemeriksaan yang dibangun sebelumnya tetap menjadi bagian dari layanan. Sebelum deployment, tambahkan komponen operasional yang tidak terlihat dalam run lokal.
-
Tinjau dua retry default SDK untuk respons 429 dan 5xx, lalu setel
max_retriesdan timeout agar sesuai dengan anggaran latensi layanan -
Tetapkan timeout permintaan dan konfirmasi bahwa pembatalan tugas SSE yang ada menghentikan pekerjaan yang tertunda saat klien terputus
-
Log ID model, versi SDK, ID permintaan, alasan berhenti, dan empat kategori token untuk setiap run
-
Buat alert pada kenaikan cache write, token output, penolakan, dan run yang mencapai batas giliran
-
Konfirmasikan bahwa pengaturan retensi akun cocok dengan persyaratan model
-
Pin SDK dan periksa ulang header beta sebelum setiap rilis
Kapan Menggunakan Claude Fable 5.1 Alih-alih Opus 5 atau Sonnet 5
- Anthropic merekomendasikan Opus 5 sebagai default yang masuk akal.
- Uji Fable 5.1 ketika Opus 5 kurang memadai untuk analisis repositori panjang, debugging sulit, atau tugas agen dengan konteks besar.
- Untuk pekerjaan repositori dan tugas sehari-hari, bandingkan Sonnet 5 dan Opus 5 pada kualitas, latensi, dan biaya.
- Untuk klasifikasi, ekstraksi, jawaban singkat, dan permintaan yang lebih sederhana, Sonnet 5 adalah default yang baik; untuk tugas paling mudah, Haiku 4.5 mungkin juga cukup kuat.
Jangan memilih Fable 5.1 hanya karena lebih baru. Satu permintaan tetap bisa menggunakan effort dan structured outputs; streaming juga berfungsi. Ia tidak mendapatkan manfaat dari loop atau caching prefiks berulang yang digunakan di sini.
Penutup
Rencana generik dari panggilan pertama saya baru menjadi berguna setelah agen membaca repositori. Dalam run yang selesai, ia memeriksa 12 file dalam tiga giliran, sementara output dan cache write menyumbang 99,5% dari perkiraan biaya. Saya akan mempertahankan batas path dan riwayat append-only, lalu menguji apakah effort lebih rendah mengurangi biaya tanpa membuat model melewatkan alat repositori.
Jika satu respons dapat menjawab tugas, cukup gunakan structured outputs. Gunakan tool loop ketika jawaban harus bergantung pada file repositori atau melaporkan progres di antara panggilan.
Untuk detail pemilihan model, saya merekomendasikan mengikuti kursus Introduction to Claude Models kami. Untuk prompting dan alur kerja agen, lihat kursus Software Development with Cursor kami.
FAQs
Bisakah Claude Fable 5.1 membaca gambar sekaligus kode?
Ya. Model ini menerima input gambar dan dapat membaca bagan serta PDF. Saya tidak memasukkan vision dalam contoh utama karena rencana repositori tidak membutuhkannya. Jika saya memperluas agen ini untuk merencanakan perubahan UI, saya akan mengirim tangkapan layar saat ini bersama permintaan fitur. Turunkan resolusinya terlebih dahulu jika detail visual kecil tidak memengaruhi tugas.
Mengapa agen saya menjadi lebih lambat setelah beralih dari Fable 5?
Periksa hasil alat sebelum menyalahkan model. Jika instruksi batching dari sebelumnya sudah ada, bandingkan jumlah dan ukurannya. Reader saat ini membatasi setiap file pada 40.000 byte. Jika masih terlalu besar, tambahkan argumen rentang baris atau pencarian agar alat dapat mengembalikan hanya bagian yang relevan.
Mengapa Claude Fable 5.1 mengembalikan 400 invalid_request_error?
Jangan langsung melakukan retry. invalid_request_error biasanya menunjuk ke bentuk permintaan atau pengaturan akun yang harus diubah. Dalam proyek ini, penyebab yang mungkin adalah tool_choice paksa, pengaturan retensi yang tidak kompatibel, prefiks yang diedit dengan thinking yang dipertahankan, atau field beta yang dikirim tanpa header yang sesuai. Perbaiki penyebab yang disebutkan, lalu kirim ulang permintaan.
Haruskah saya meng-cache file sumber atau ringkasan?
Saya menggunakan aturan ini: cache file sumber saat kode persisnya penting di beberapa giliran. Jika langkah selanjutnya hanya membutuhkan arsitektur atau peta file, cache ringkasannya. Ringkasan berbiaya token lebih sedikit, tetapi bisa menghilangkan satu baris yang dibutuhkan rencana akhir.
Bisakah Batch API menjalankan agen ini?
Tidak sendirian. Batch API mengirim permintaan Messages individual; ia tidak menjalankan loop alat di sisi klien ini. Saya akan menggunakannya untuk ulasan repositori yang berdiri sendiri ketika progres live tidak diperlukan. Menjalankan loop penuh dalam batch memerlukan kode Anda sendiri untuk memproses permintaan alat satu batch sebelum mengirimkan batch berikutnya.
Saya seorang data engineer dan pembangun komunitas yang bekerja lintas pipeline data, cloud, dan perkakas AI sambil menulis tutorial praktis dan berdampak tinggi untuk DataCamp dan pengembang yang sedang berkembang.

