Chuyển đến nội dung chính

Hướng dẫn Claude Fable 5.1 API: Xây dựng Developer Agent chạy dài bằng Python

Tìm hiểu cách dùng mô hình flagship mới nhất của Anthropic để xây dựng agent Python đọc một kho Flask trước khi lập kế hoạch thay đổi. Thêm cập nhật tiến độ, công cụ tệp chỉ-đọc, và kiểm soát chi phí.
Đã cập nhật 3 thg 9, 2026  · 15 phút đọc

Khám phá với AI

ChatGPTClaudePerplexity

Khi tôi thử một mô hình mới qua cuộc gọi API, phản hồi đầu tiên thường không nói lên nhiều điều. Lần chạy Fable 5.1 đầu tiên trả về cấu trúc hợp lệ và một kế hoạch chung chung. Tôi muốn biết điều gì xảy ra khi cuộc hội thoại dài ra: ứng dụng có giữ nguyên lịch sử, kiểm tra tệp mà không đọc ngoài phạm vi dự án, báo cáo tiến độ và cho biết chi phí đến từ đâu không?

Bài tổng quan Claude Fable 5.1 của chúng tôi đề cập đến lần ra mắt, điểm chuẩn và so sánh mô hình ở phạm vi rộng. Ở đây, chúng ta sẽ bắt đầu với một cuộc gọi Python nhỏ và xây dựng vòng lặp agent xung quanh nó. Agent cuối cùng sẽ nhận yêu cầu tính năng, đọc một dự án Flask, và trả về kế hoạch gắn với các tệp mà nó thực sự đã kiểm tra.

Chúng ta sẽ đề cập cách để:

  • Thực hiện cuộc gọi API Claude Fable 5.1 và đọc các khối nội dung một cách an toàn
  • Thiết lập mức độ suy luận (effort), và thay đổi nó giữa cuộc hội thoại (beta)
  • Giới hạn một hướng dẫn hệ thống cho một lượt duy nhất (beta)
  • Trả về kế hoạch có cấu trúc với Pydantic
  • Thêm công cụ kho mã chỉ-đọc với ranh giới thư mục gốc của dự án
  • Chạy vòng lặp công cụ nhiều lượt
  • Đọc cập nhật tiến độ của agent giữa các lần gọi công cụ (beta)
  • Giữ các khối thinking hợp lệ với lịch sử chỉ-ghi-thêm
  • Bộ nhớ đệm ngữ cảnh lặp lại và ước tính chi phí yêu cầu theo mức giá công bố
  • Xử lý từ chối và cung cấp agent qua FastAPI

Các tính năng beta dùng header có ngày, nên hãy kiểm tra với tài liệu của Anthropic trước khi triển khai.

Chạy Claude Fable 5.1 trong vòng lặp agent tốn bao nhiêu?

Một agent sẽ gửi lại cùng prompt hệ thống, định nghĩa công cụ, và ngữ cảnh kho mã ở mọi lượt, nên mức giá quyết định chi phí của bạn là lần đọc cache, không phải giá đầu vào.

Fable 5.1 có giá $10 mỗi triệu token đầu vào và $50 mỗi triệu token đầu ra, không đổi so với Fable 5. Lần đọc cache có giá $0,25 mỗi triệu, giảm từ $1, và lần ghi cache 5 phút vẫn ở mức $12,50 mỗi triệu. Hướng dẫn Claude Fable 5.1 của chúng tôi có đầy đủ bảng giá và ước tính tiết kiệm của chính Anthropic.

Đọc một tiền tố đã được cache thì rẻ. Ghi thì không, đắt gấp 50 lần đọc, nên vòng lặp chỉ có lợi khi tiền tố được đọc lại nhiều lần. Phần phân tích chi phí bên dưới sẽ cho thấy điều đó trong một lần chạy thực tế, và hạng mục nào chiếm ưu thế.

Giới hạn token đến từ mô hình, không phải ngân sách của bạn. Fable 5.1 cung cấp cửa sổ ngữ cảnh 1M token với tối đa 128K token đầu ra mỗi phản hồi, và max_tokens là giới hạn cứng cho cả thinking và văn bản phản hồi. Ở effort cao bạn cần chừa chỗ cho cả hai, đó là lý do vòng lặp agent dưới đây đặt 16.000 thay vì một con số “đẹp”.

Lưu trữ dữ liệu, hạng ưu tiên và watermark

Một vài chi tiết truy cập quan trọng trước khi viết mã. Có hai điều có thể chặn thẳng yêu cầu của bạn:

  • Fable 5.1 yêu cầu lưu trữ dữ liệu 30 ngày và không khả dụng với chế độ không lưu dữ liệu, trừ khi Anthropic cấp quyền. Yêu cầu từ workspace không tương thích sẽ trả về 400 invalid_request_error mà không có gợi ý nào khác.

  • Mô hình không được hỗ trợ trên Priority Tier. Fable 5 thì có, nên điều này dễ gây nhầm lẫn khi di chuyển.

  • Đầu ra văn bản Fable 5.1 có watermark văn bản của Anthropic. Điều này không làm tăng token và không cần thay đổi yêu cầu.

Dùng Claude Fable 5.1 qua API để xây dựng agent cho nhà phát triển nhận biết kho mã

Quy trình của chúng ta có hai giai đoạn:

  1. Một vòng lặp kiểm tra có giới hạn đọc các tệp dự án được phép.
  2. Một yêu cầu cuối dùng đầu ra có cấu trúc biến ngữ cảnh đó thành một kế hoạch. 

Dự án mẫu là một Flask JSON API nhỏ để lưu và tìm kiếm bookmark, với app factory, ba blueprint, một module cấu hình, models, và bộ pytest. Tôi dùng hạn chế tốc độ (rate limiting) làm nhiệm vụ xuyên suốt vì agent phải kiểm tra phần cấu hình app, routes, config, và tests trước khi có thể xác định tệp và bài test cần thiết. Mã hoàn chỉnh và dự án mẫu có trong kho GitHub.

Sơ đồ một yêu cầu tính năng đi qua agent Claude Fable 5.1, danh sách cho phép đường dẫn, và dự án mẫu trước khi trả về một kế hoạch có cấu trúc

Yêu cầu chỉ chạm đến tệp thông qua một ranh giới. Ảnh: Tác giả.

Agent chỉ có thể dùng ba công cụ: list_project_files, read_project_file, và get_project_metadata. Claude không bao giờ truy cập hệ thống tệp trực tiếp. Nó yêu cầu một đường dẫn, và mã của bạn quyết định đường dẫn đó có được phép hay không.

Thiết lập Claude Fable 5.1 API trong Python

Bắt đầu với môi trường Python riêng và giữ API key trên máy chủ.

Yêu cầu tiên quyết

Bạn cần Python 3.10 trở lên và một Anthropic API key có quyền truy cập claude-fable-5-1

Để tạo API key, đăng nhập vào Claude Console, mở trang API keys, nhấp Create key, rồi sao chép khóa. Tốt nhất là đặt tên giúp bạn nhớ mục đích sử dụng, chọn ngày hết hạn và lưu trữ khóa an toàn.

Cài SDK và thêm API key

Tạo môi trường ảo và cài đặt các gói:

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

Giữ cố định phiên bản SDK vì các tính năng beta thay đổi thường xuyên. Cập nhật tiến độ cần ít nhất 1.1.0, và ví dụ dùng 1.3.0.

Đặt key vào .env filethêm .env vào .gitignore trước commit đầu tiên. Nó phải nằm trên máy chủ do bạn kiểm soát, không bao giờ ở trình duyệt hay kho công khai. Lộ key có thể cho phép sử dụng API trái phép và phát sinh chi phí ở đầu vào, đầu ra, và thao tác cache.

ANTHROPIC_API_KEY=sk-ant-your-key-here

Với thiết lập đó, client sẽ tự tìm key.

Thực hiện cuộc gọi API Claude Fable 5.1 đầu tiên trong Python

Gửi yêu cầu API nhỏ nhất có thể trước khi xây dựng thêm.

Gửi yêu cầu API đầu tiên

Khởi tạo client, gửi một tin nhắn người dùng, và in metadata phản hồi:

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 hiển thị phản hồi API Claude Fable 5.1 với ID mô hình, lý do dừng, số lượng token, và ID yêu cầu

Cuộc gọi đầu trả về văn bản kèm metadata. Ảnh: Tác giả.

Lệnh next(...) chọn khối văn bản đầu tiên. Adaptive thinking luôn bật và không thể tắt, nên phản hồi có thể bắt đầu với khối thinking; gửi thinking: {"type": "disabled"} sẽ trả 400 thay vì tắt. Khi khối thinking đứng trước, response.content[0].text sẽ ném ngoại lệ.

Giải pháp là lọc theo loại khối thay vì giả định vị trí cố định. Cũng hãy ghi log response._request_id vì hỗ trợ Anthropic dùng nó để truy vết yêu cầu.

Đây là yêu cầu dùng trong các ví dụ lập kế hoạch và effort. Nó yêu cầu agent kiểm tra nhiều tệp:

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

Giữ nguyên văn bản đó khi so sánh mức effort và số token. Kết quả khi đó phản ánh thiết lập API chứ không phải prompt khác.

Thiết lập mức effort với output_config

Thiết lập effort thông qua output_config. Nó nhận low, medium, high, xhigh, và max. Mặc định API là high.

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

Effort có thể ảnh hưởng sử dụng token, hành vi công cụ, và độ trễ. Tôi chạy cùng yêu cầu ba lần ở mỗi trong bốn mức effort; bảng cho thấy giá trị trung bình:

Effort

Giây

Thinking tokens

Tổng token đầu ra

Chi phí

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

Token thinking đã được tính trong tổng token đầu ra, nên đừng cộng hai cột. Trong các lần này, low, medium, và high gần như tương đương về độ trễ và chi phí.

xhigh mất thời gian gấp hai rưỡi, tạo ra số token đầu ra gần gấp chín lần, và tốn chi phí gấp tám lần. 

Kết luận: Bắt đầu ở high, hạ xuống medium cho các bước thường lệ, và chỉ tăng khi kiểm thử của bạn cho thấy cải thiện có ý nghĩa. Ở low effort, mô hình có thể trả lời theo trí nhớ thay vì gọi công cụ truy xuất. Nếu một lượt cần dữ liệu mới, hãy nói rõ hoặc nâng mức.

Giới hạn phạm vi agent bằng system prompt

System prompt xác định hành vi của 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."""

Tài liệu hướng dẫn nhắc prompt của Anthropic lưu ý mô hình có thể mở rộng nhiệm vụ hoặc dừng quá sớm. Prompt yêu cầu bám sát phạm vi và kết thúc với hướng dẫn cụ thể. Một schema sẽ xử lý định dạng đầu ra sau đó.

Trả về kế hoạch có cấu trúc với Pydantic

Định nghĩa kế hoạch bằng Pydantic để ứng dụng của bạn xác thực và chuyển tiếp cho mã khác:

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() chuyển mô hình Pydantic thành JSON schema, gửi đi, xác thực phản hồi, và trả về đối tượng có kiểu trong parsed_output. Structured outputs khả dụng chung, nên không có header beta. Kiểm tra stop_reason trước vì trường hợp từ chối, được đề cập sau, sẽ bỏ qua schema và bạn không có gì để parse.

Kết quả chung chung lúc đầu có một điểm đúng: nó không nêu các tệp mà nó không thể thấy. Schema xác thực cấu trúc, không xác thực căn cứ thực tế.

Claude Fable 5.1 so với Fable 5: Thay đổi khi di chuyển API

Trước khi thêm công cụ, tính đến ràng buộc ép-dùng-công-cụ, tương thích khối thinking, và lịch sử chỉ-ghi-thêm.

  • Fable 5.1 từ chối ép chọn công cụ. Phần vòng lặp công cụ bên dưới cho thấy lỗi và cấu hình auto được dùng thay thế.

  • Khối thinking chỉ tương thích một chiều. Fable 5.1 đọc được các khối từ các mô hình Claude trước đó, nhưng không mô hình cũ nào đọc được khối của nó. 

Khi một router hoặc fallback chuyển cuộc hội thoại sang mô hình cũ hơn, API sẽ loại bỏ các khối không tương thích trước khi mô hình đích thấy chúng. Phần lịch sử còn lại giữ nguyên, nhưng mô hình cũ phải lập kế hoạch mà không có các khối đó.

Chỉnh sửa các lượt trước sẽ làm mất hiệu lực các khối thinking sau đó. Điều này có thể làm hỏng cắt tỉa lịch sử và tóm tắt phía client.

Hướng dẫn di chuyển bao quát đầy đủ các thay đổi.

Thêm công cụ kho mã chỉ-đọc

Giờ hãy cung cấp ngữ cảnh kho mã cho mô hình qua các công cụ chỉ-đọc.

Định nghĩa công cụ chỉ-đọc

Lớp công cụ có hai phần: các hàm Python thực thi quy tắc truy cập và các schema mà Claude có thể gọi.

Giới hạn đường dẫn trong thư mục gốc dự án

Chỉ-đọc không đồng nghĩa với an toàn. Mô hình có thể yêu cầu ../../.env dễ như config.py, nên hàng rào phải nằm trong mã của bạn chứ không phải trong 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

Từ chối đường dẫn tuyệt đối và các thành phần symlink, sau đó resolve đường dẫn và xác nhận nó vẫn nằm dưới thư mục gốc dự án. Yêu cầu ../.env sẽ trả “path is outside the project root.” Lỗi công cụ trả về cho phép agent tiếp tục với các tệp được phép.

Định nghĩa schema công cụ nghiêm ngặt

Lớp đọc kiểm soát những gì Python được mở. Claude cũng cần các JSON schema mô tả ba hành động mà nó có thể yêu cầu:

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 kiểm tra tham số khi mô hình chọn công cụ. Nó không ép phải gọi công cụ, điều này quan trọng với Fable 5.1.

Chạy vòng lặp công cụ nhiều lượt

Bắt đầu với vòng lặp cơ bản: gửi công cụ, kiểm tra stop_reason, chạy điều được yêu cầu, nối kết quả, và lặp lại.

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 giới hạn số lượt yêu cầu của mô hình, không phải chi tiêu, nên nếu cần hãy áp thêm giới hạn chi phí. Vòng lặp xử lý trực tiếp refusal, max_tokens, và tool_use ; các lý do dừng khác sẽ kết thúc giai đoạn kiểm tra. Trường is_error cho mô hình biết rằng một đường dẫn đã bị từ chối, để nó có thể chọn hành động khác.

Vì sao ép chọn công cụ trả về 400

Trên Fable 5, bạn có thể ép cuộc gọi đầu với tool_choice: {"type": "any"}. Fable 5.1 trả lỗi này trước khi yêu cầu thực thi:

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

Các cuộc gọi ép buộc sẽ bỏ qua thinking luôn bật. Giữ tool_choice auto, dùng các schema nghiêm ngặt đã định nghĩa, và nêu tên công cụ trong prompt khi một bước cần đến nó.

Fable 5.1 đôi khi gọi một công cụ mỗi lượt, trong khi Fable 5 gom nhiều cái. Điều đó tăng số vòng trao đổi. Thêm dòng này vào prompt: “Hãy yêu cầu các tệp độc lập trong cùng một lượt thay vì từng lượt một.” Một lần chạy mẫu đã gộp chín yêu cầu tệp độc lập, dù số lượng có thể thay đổi.

Stream phản hồi và cập nhật tiến độ của Claude Fable 5.1

Stream văn bản phát nội dung phản hồi khi nó được sinh ra; cập nhật tiến độ bao quát các khoảng tạm dừng giữa các lần gọi công cụ.

Stream phản hồi văn bản

Dự án đầy đủ dùng context_system() để kết hợp SYSTEM_PROMPT với tóm tắt dự án trước khi bắt đầu 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() cho bạn thông điệp đã lắp ráp với usage và lý do dừng khi stream kết thúc. Các mảnh stream không đảm bảo chứa JSON hoàn chỉnh, nên hãy đợi thông điệp cuối trước khi parse.

Hiển thị tiến độ giữa các lần gọi công cụ

Stream văn bản không bao quát độ trễ trong khi gọi công cụ. Fable 5.1 có thể ghi ngắn gọn cập nhật tiến độ trước khi gọi công cụ. Ở mặc định thinking.display "omitted", các khối thinking dành cho tiến độ sẽ rỗng, dù mô hình vẫn có thể sinh một câu dẫn văn bản bình thường.

Với display: "updates" và header beta thinking-display-updates-2026-08-18 , tài liệu API định nghĩa một cập nhật tiến độ có thể đọc là một khối thinking không rỗng trong khi lý luận vẫn ẩn. Trong các lần chạy thực tế cho dự án này, trường thinking vẫn rỗng và trạng thái có thể đọc đến dưới dạng khối text ngay trước tool_use. Do đó helper sẽ kiểm cả hai loại khối, và vòng lặp chỉ gọi nó ở các lượt kết thúc bằng 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

Các thông điệp tiến độ mô tả các tệp mô hình dự định đọc: "Tôi sẽ đọc phần wiring của app, config, extensions, các route public và auth, và các bài test hiện có, vì đó là nơi rate limiting sẽ gắn vào." Hiển thị các thông điệp này và bỏ qua khối rỗng.

Terminal hiển thị vòng lặp agent Claude Fable 5.1 với số token theo lượt, thông điệp tiến độ, và các lần đọc tệp gộp

Agent đọc tệp trong khi báo cáo tiến độ. Ảnh: Tác giả.

Fable 5.1 ghi ít thông điệp loại này hơn Fable 5, đặc biệt ở effort cao. Nếu giao diện của bạn cần cập nhật thường xuyên, hãy yêu cầu dòng mở đầu, thông điệp tiến độ, và tóm tắt kết thúc.

Thay đổi effort của Claude Fable 5.1 giữa cuộc hội thoại

Tính năng tiếp theo khá thú vị. Như chúng ta biết, agent cho kho mã không cần cùng độ sâu suy luận ở mọi lượt.

Thay đổi effort giữa các lượt

Trong vòng lặp agent, hạ effort cho các lượt truy xuất thường lệ và nâng lại cho lượt lập kế hoạch cuối.

Với header beta mid-conversation-output-config-2026-07-01 , bạn có thể nối một thông điệp hệ thống chỉ thay đổi mức 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,
)

Mức mới áp dụng từ lượt người dùng kế tiếp, không phải giữa lượt hiện tại, và không làm mất hiệu lực cache của prompt. Thay đổi output_config.effort ở cấp yêu cầu giữa các lần gọi thì có làm mất hiệu lực.

Agent giữ thiết lập cấp cao là high, thêm chỉ thị medium trước các lượt truy xuất thường lệ, và thêm high trước kế hoạch cuối. Một kiểm thử cặp dùng 18 token đầu ra ở effort thấp so với 76 ở thiết lập trước. Xem kết quả đó như ví dụ, không phải mức giảm kỳ vọng.

Áp dụng hướng dẫn hệ thống cho một lượt

Dùng hướng dẫn phạm vi-lượt để chặn đọc thêm tệp trong giai đoạn lập kế hoạch cuối.

Đặt clear_at: "next_user_message" trên thông điệp hệ thống với header beta mid-conversation-system-clear-at-2026-08-21 . API coi văn bản của nó là hướng dẫn hệ thống cho lượt hiện tại, rồi ngừng render sau thông điệp người dùng kế tiếp. Nó vẫn nằm trong messages, nên lịch sử trước đó không đổi, cache vẫn khớp, và thông điệp đã clear không tốn token đầu vào.

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"} giữ yêu cầu cuối không gọi thêm công cụ. Chỉ thị phạm vi-lượt giới hạn kế hoạch vào các tệp agent đã kiểm tra. Đừng thêm lời nhắc và xóa nó ở yêu cầu sau. Sửa đổi đó sẽ làm mất hiệu lực các khối thinking tiếp theo.

Sửa lỗi 400 liên quan khối thinking của Claude Fable 5.1

Lỗi The block is bound to a different conversation nghĩa là lịch sử trước một khối thinking đã thay đổi. Mỗi khối thinking của Fable 5.1 gắn với chính xác system prompt, định nghĩa công cụ, và các thông điệp đi trước nó.

Kết quả phụ thuộc vào thời điểm tài khoản của bạn được tạo. 

  • Tài khoản tạo từ ngày 31/08/2026 trở đi sẽ nhận 400 báo rằng khối gắn với cuộc hội thoại khác. 

  • Với tài khoản cũ hơn, API ghi nhận sự không khớp nhưng chỉ hành động khi yêu cầu đặt thinking.block_binding.prefix_mismatch_behavior

Bạn có thể phát hiện điều này với header beta thinking-binding-controls-2026-08-01, đặt thinking.block_binding.prefix_mismatch_behavior thành "drop_block", và mảng input_transformations. Lịch sử đã chỉnh sửa xuất hiện là reason: "prefix_binding_mismatch". Chạy kiểm tra này một lần với tích hợp của bạn.

Các thao tác sau sẽ gây không khớp:

  • Chỉnh sửa, sắp xếp lại, hoặc xóa một lượt trước đó trong khi giữ các lượt sau

  • Chèn văn bản theo-yêu-cầu vào lượt trước rồi loại bỏ ở yêu cầu tiếp theo

  • Thay đổi nội dung hoặc thứ tự system cấp cao hoặc mảng tools giữa cuộc hội thoại

  • Phục vụ các byte khác nhau từ URL hình ảnh hoặc tài liệu ở yêu cầu sau

Mỗi trường hợp đều có cách thay thế để giữ ràng buộc:

  • Thêm hướng dẫn bằng thông điệp hệ thống giữa cuộc hội thoại thay vì chỉnh sửa system

  • Thay đổi công cụ bằng thay đổi công cụ giữa cuộc hội thoại thay vì chỉnh mảng cấp cao. 

  • Cắt tỉa lịch sử bằng chỉnh sửa ngữ cảnh hoặc nén phía máy chủ, các thao tác này không tính là chỉnh sửa. 

  •  Trả lại các khối thinking không thay đổi.

Di chuyển các marker cache_control và thay đổi effort ở cấp yêu cầu đều an toàn và không làm mất ràng buộc khối thinking. Tuy nhiên, thay đổi effort cấp cao sẽ khởi động lại bộ nhớ đệm prompt, nên hãy dùng effort theo-thông-điệp khi muốn giữ nguyên tiền tố được cache.

Bộ nhớ đệm prompt và chi phí Claude Fable 5.1 API

Lần chạy sau sẽ tách riêng chi phí đầu vào mới, ghi cache, đọc cache, và đầu ra.

Thêm bộ nhớ đệm prompt tự động

Bộ nhớ đệm prompt giảm chi phí của ngữ cảnh lặp lại qua các lượt. Lịch sử tăng dần làm thay đổi điểm gãy phù hợp, nên bộ nhớ đệm tự động phù hợp hơn ở đây.

Trường cache_control cấp cao di chuyển điểm gãy đến khối có thể cache mới nhất ở mỗi yêu cầu:

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

Tiền tố có thể cache ngắn hơn 512 token sẽ không được cache trên Fable 5.1, ngay cả khi gắn cache_control. API xử lý bình thường và trả về 0 cho cả hai bộ đếm cache. Ghi tiền tố 583 token tốn $0,0073; đọc nó ở lượt kế tiếp tốn $0,00015. Lượt thứ hai vẫn phải ghi phần mới của nó vào cache, nên cache hit không xóa bỏ toàn bộ chi phí đầu vào.

Ước tính chi phí API có tính cache

response.usage báo cáo riêng đầu vào mới, tạo cache, đọc cache, và đầu ra. Hãy tính giá bốn bộ đếm này độc lập; chỉ cộng đầu vào và đầu ra sẽ che mất chi phí ghi cache và thổi phồng giá của cache hit.

Đây là phân tích chi phí từ một lần chạy đầy đủ đọc 12 tệp qua ba lượt và sinh một kế hoạch cuối:

Hạng mục

Token

Chi phí ước tính

Tỷ trọng

Đầu ra

5.713

$0.2857

59,4%

Ghi cache

15.426

$0.1928

40,1%

Đầu vào mới

50

$0.0005

0,1%

Đọc cache

6.549

$0.0016

0,3%

Tổng

27.738

$0.4806

100%

Đọc cache chỉ chiếm một phần nhỏ dưới nửa phần trăm của ước tính này. Ở mức giá cũ của Fable 5, lần chạy sẽ tốn khoảng $0,4855 thay vì $0,4806. Tiết kiệm sẽ tăng khi mỗi lượt tái sử dụng nhiều ngữ cảnh hơn.

Trong lần này, đầu ra chiếm gần 60% ước tính, và ghi cache chiếm khoảng 40%. Với mức giá 5 phút dùng ở đây, mỗi token ghi cache đắt gấp 50 lần token đọc cache. Ghi cache 1 giờ đắt gấp 80 lần.

Xử lý từ chối và fallback của Claude Fable 5.1

Một lần từ chối và một yêu cầu thất bại cần hành vi ứng dụng khác nhau.

Phát hiện từ chối trước khi parse đầu ra

Một lần từ chối trước khi có đầu ra sẽ đến với HTTP 200 cùng stop_reason: "refusal", nội dung rỗng, và stop_details. Danh mục có thể null. Một lần từ chối muộn trong stream có thể đến sau đầu ra một phần, ứng dụng nên loại bỏ phần đó. Một khối try/except xung quanh cuộc gọi sẽ không bắt được cả hai trường hợp.

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

Hãy xử lý nó như một trạng thái ứng dụng. Nếu yêu cầu được phép nhưng chưa rõ, hãy viết lại chính xác hơn. Đừng xây logic thử lại nhằm lách bộ phân loại.

Từ chối đến với HTTP 200. Ảnh: Tác giả.

Cấu hình fallback phía máy chủ

Fallback phía máy chủ có thể thử lại yêu cầu bị từ chối trên mô hình khác, dùng fallbacks: "default" với header beta server-side-fallback-2026-07-01 . Mục tiêu cho phép với Fable 5.1 là Opus 4.8 và Opus 5

Fallback mặc định chỉ chạy khi danh mục từ chối có mục tiêu khuyến nghị. Một lần từ chối reasoning_extraction đã kiểm thử không kích hoạt fallback; hãy kiểm usage.iterations thay vì giả định mọi từ chối đều thử lại. Như đã đề cập, chuyển sang mô hình cũ hơn cũng làm rơi các khối thinking Fable 5.1.

Cung cấp agent Claude Fable 5.1 với FastAPI

Agent cục bộ giờ có thể cung cấp cùng quy trình qua HTTP API.

Tạo endpoint kế hoạch

Nếu bạn chỉ cần script cục bộ, hãy bỏ qua phần này. Với dịch vụ webe, dùng FastAPI với AsyncAnthropic. Tạo một client cho tiến trình trong lifespan handler. Import schema và prompt từ module agent sẵn có.

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

Lưu ý phía gọi gửi tên dự án, không phải đường dẫn. resolve_project() ánh xạ nó tới một tập nhỏ thư mục gốc được phép, nên yêu cầu không thể bắt máy chủ đọc bừa. Dịch vụ này ánh xạ từ chối sang 422 như một lựa chọn ứng dụng. Bản thân Claude API trả chúng là HTTP 200.

Chạy với uvicorn app:app --reload. Tài liệu tương tác có tại http://localhost:8000/docs.

Endpoint trả về kế hoạch với chi phí ước tính. Video: Tác giả.

Endpoint /plan/stream chạy giai đoạn kiểm tra trong một tác vụ nền, đặt sự kiện tiến độ và công cụ vào asyncio.Queue, và phát chúng qua StreamingResponse. Khi stream đóng, generator hủy tác vụ nền. Giao diện Streamlit trong kho cũng render cùng luồng sự kiện.

Streamlit hiển thị tiến độ trực tiếp của agent. Video: Tác giả.

Checklist triển khai agent Claude Fable 5.1

Các giới hạn và kiểm tra đã xây dựng trước đó vẫn là một phần của dịch vụ. Trước khi triển khai, hãy thêm các phần vận hành không nhìn thấy trong lần chạy cục bộ.

  • Rà soát mặc định SDK có hai lần retry cho phản hồi 429 và 5xx, rồi đặt max_retries và timeout phù hợp ngân sách độ trễ của dịch vụ

  • Đặt timeout yêu cầu và xác nhận rằng hủy nhiệm vụ SSE hiện có dừng công việc còn lại khi client ngắt kết nối

  • Ghi log ID mô hình, phiên bản SDK, ID yêu cầu, lý do dừng, và bốn nhóm token cho mỗi lần chạy

  • Cảnh báo khi ghi cache tăng, token đầu ra tăng, số lần từ chối tăng, và các lần chạy chạm trần lượt

  • Xác nhận thiết lập lưu trữ của tài khoản khớp yêu cầu của mô hình

  • Pin phiên bản SDK và kiểm tra lại các header beta trước mỗi lần phát hành

Khi nào nên dùng Claude Fable 5.1 thay vì Opus 5 hoặc Sonnet 5

  • Anthropic khuyến nghị Opus 5 là mặc định hợp lý.
  • Kiểm thử Fable 5.1 khi Opus 5 thiếu ở phân tích kho mã dài, gỡ lỗi khó, hoặc các tác vụ agentic với ngữ cảnh lớn.
  • Với công việc kho mã và tác vụ hằng ngày, so sánh Sonnet 5 và Opus 5 về chất lượng, độ trễ, và chi phí.
  • Với phân loại, trích xuất, trả lời ngắn, và yêu cầu đơn giản, Sonnet 5 là mặc định tốt; với tác vụ dễ hơn nữa, Haiku 4.5 cũng có thể đủ mạnh.

Đừng chọn Fable 5.1 chỉ vì nó mới hơn. Một yêu cầu đơn lẻ vẫn có thể dùng effort và structured outputs; streaming cũng hoạt động. Nó không hưởng lợi từ vòng lặp hay bộ nhớ đệm tiền tố lặp lại như ở đây.

Lời kết

Kế hoạch chung chung từ cuộc gọi đầu tiên chỉ trở nên hữu ích sau khi agent đọc kho mã. Trong lần chạy hoàn chỉnh, nó kiểm tra 12 tệp qua ba lượt, trong khi đầu ra và ghi cache chiếm 99,5% chi phí ước tính. Tôi sẽ giữ ranh giới đường dẫn và lịch sử chỉ-ghi-thêm, rồi kiểm tra liệu effort thấp hơn có giảm chi phí mà không khiến mô hình bỏ qua công cụ kho mã hay không.

Nếu một phản hồi có thể trả lời nhiệm vụ, hãy dừng ở structured outputs. Dùng vòng lặp công cụ khi câu trả lời phải phụ thuộc vào tệp trong kho hoặc cần báo cáo tiến độ giữa các lần gọi.

Về chi tiết chọn mô hình, tôi khuyến nghị khóa Giới thiệu về các mô hình Claude của chúng tôi. Với nhắc prompt và quy trình agent, xem khóa Phát triển phần mềm với Cursor.

Câu hỏi thường gặp

Claude Fable 5.1 có đọc được hình ảnh cũng như mã không?

Có. Nó nhận đầu vào hình ảnh và có thể đọc biểu đồ và PDF. Tôi bỏ phần thị giác khỏi ví dụ chính vì kế hoạch kho mã không cần đến nó. Nếu mở rộng agent này để lập kế hoạch thay đổi UI, tôi sẽ gửi ảnh chụp màn hình hiện tại kèm yêu cầu tính năng. Hãy giảm kích thước trước nếu chi tiết hình ảnh nhỏ không ảnh hưởng nhiệm vụ.

Vì sao agent của tôi chậm hơn sau khi chuyển từ Fable 5?

Hãy kiểm tra kết quả công cụ trước khi đổ lỗi cho mô hình. Nếu chỉ dẫn gộp lô từ trước đã có, hãy so sánh cả số lượng và kích thước. Trình đọc hiện tại giới hạn mỗi tệp ở 40.000 byte. Nếu vẫn quá lớn, hãy thêm tham số phạm vi dòng hoặc tìm kiếm để công cụ chỉ trả về phần liên quan.

Vì sao Claude Fable 5.1 trả về 400 invalid_request_error?

Đừng thử lại ngay. invalid_request_error thường chỉ ra hình dạng yêu cầu hoặc thiết lập tài khoản cần thay đổi. Trong dự án này, các nguyên nhân có khả năng là ép tool_choice, thiết lập lưu trữ không tương thích, tiền tố đã chỉnh nhưng giữ thinking, hoặc gửi trường beta mà không có header tương ứng. Sửa nguyên nhân nêu ra, rồi gửi lại yêu cầu.

Tôi nên cache mã nguồn hay bản tóm tắt?

Tôi dùng quy tắc này: cache mã nguồn khi đoạn mã chính xác quan trọng qua nhiều lượt. Nếu các bước sau chỉ cần kiến trúc hoặc bản đồ tệp, hãy cache bản tóm tắt. Bản tóm tắt tốn ít token hơn, nhưng có thể bỏ sót dòng duy nhất mà kế hoạch cuối cần.

Batch API có thể chạy agent này không?

Không tự thân. Batch API gửi các yêu cầu Messages riêng lẻ; nó không chạy vòng lặp công cụ phía client này. Tôi sẽ dùng nó cho các lần rà soát kho mã tự chứa khi không cần tiến độ trực tiếp. Chạy toàn bộ vòng lặp theo lô đòi hỏi mã của bạn xử lý yêu cầu công cụ của một lô trước khi gửi lô kế tiếp.


Khalid Abdelaty's photo
Author
Khalid Abdelaty
LinkedIn

Tôi là một kỹ sư dữ liệu và người xây dựng cộng đồng, làm việc với pipeline dữ liệu, đám mây và công cụ AI, đồng thời viết các hướng dẫn thực hành, tác động cao cho DataCamp và các nhà phát triển mới nổi.

Chủ đề

Học AI cùng DataCamp!

Tracks

Kỹ sư Trợ lý Trí tuệ Nhân tạo (AI) cho Lập trình viên

26 giờ
Học cách tích hợp trí tuệ nhân tạo (AI) vào các ứng dụng phần mềm thông qua việc sử dụng các giao diện lập trình ứng dụng (API) và các thư viện mã nguồn mở. Hãy bắt đầu hành trình trở thành Kỹ sư Trí tuệ Nhân tạo ngay hôm nay!
Xem chi tiếtRight Arrow
Bắt Đầu Khóa Học
Xem thêmRight Arrow
Có liên quan

blogs

Claude Opus 4.6: Tính năng, Điểm chuẩn, Bài kiểm tra thực hành và hơn thế nữa

Mô hình mới nhất của Anthropic dẫn đầu ở mã hóa tác tử và lập luận phức tạp. Thêm vào đó, nó có cửa sổ ngữ cảnh 1M.
Matt Crabtree's photo

Matt Crabtree

10 phút

Xem ThêmXem Thêm