Sổ tay kỹ thuật

Prompt caching với Claude API

how-to#claude-api#python#agents· cập nhật 2026-11-06

Dùng khi agent gửi lặp lại system prompt, tool hoặc tài liệu dài (runbook, config mẫu) và muốn giảm chi phí, độ trễ bằng cache_control.

Sửa trang này
Mục lục

Tóm tắt: Đặt cache_control: {"type": "ephemeral"} lên block cuối cùng của phần prefix không đổi. Thứ tự prefix luôn là tools → system → messages. Lần gọi đầu, phần đó được ghi vào cache (usage.cache_creation_input_tokens). Các lần sau, trong thời gian TTL (mặc định 5 phút, mỗi lần hit lại được làm mới), prefix giống hệt sẽ đọc từ cache (usage.cache_read_input_tokens) với giá rẻ hơn nhiều. Vòng tool use cơ bản xem Claude API tool use.

Luồng hoạt động

flowchart LR A["Request: tools + system + messages"] --> B{"Prefix đến breakpoint đã có trong cache?"} B -->|"có"| C["cache_read_input_tokens (rẻ)"] B -->|"không"| D["cache_creation_input_tokens (ghi cache)"] C --> E["Phần sau breakpoint: input_tokens"] D --> E E --> F[Model sinh output]

Cache khớp theo prefix chính xác. Chỉ cần đổi một ký tự trong tools hoặc system thì mọi breakpoint phía sau đều bị miss.

Cấu hình

Cache system prompt + tài liệu dài

cached_agent.py
from pathlib import Path
 
import anthropic
 
client = anthropic.Anthropic()
RUNBOOK = Path("runbook-bgp.md").read_text()   # tài liệu dài, ít đổi
 
SYSTEM = [
    {"type": "text", "text": "Bạn là trợ lý NOC. Trả lời ngắn, dẫn mục runbook."},
    {
        "type": "text",
        "text": RUNBOOK,
        "cache_control": {"type": "ephemeral"},   # breakpoint: cache tools + toàn bộ system
    },
]
 
 
def ask(question: str) -> str:
    resp = client.messages.create(
        model="claude-sonnet-5-5",
        max_tokens=1024,
        system=SYSTEM,
        messages=[{"role": "user", "content": question}],
    )
    u = resp.usage
    print(f"write={u.cache_creation_input_tokens} read={u.cache_read_input_tokens} "
          f"uncached={u.input_tokens} out={u.output_tokens}")
    return resp.content[0].text
 
 
ask("Peer BGP flap liên tục thì kiểm tra gì trước?")   # lần 1: write > 0
ask("Khi nào được clear bgp soft?")                    # lần 2: read > 0

Cache hội thoại nhiều lượt (agent loop)

Đặt breakpoint ở block cuối của message mới nhất. Ở lượt sau, toàn bộ lịch sử trước đó sẽ là cache hit. Cách gọn nhất là dùng tham số top-level cache_control (có trong SDK Python hiện hành, đã kiểm tra với anthropic 0.109). SDK sẽ tự gắn breakpoint vào block cuối có thể cache của request:

resp = client.messages.create(model="claude-sonnet-5-5", max_tokens=2048,
                              cache_control={"type": "ephemeral"},
                              system=SYSTEM, tools=TOOLS, messages=messages)

Với SDK cũ hơn, tự gắn bằng hàm:

def with_cache_on_last(messages):
    """Gắn cache_control vào block cuối của message cuối, không sửa list gốc."""
    msgs = [dict(m) for m in messages]
    last = msgs[-1]
    content = last["content"]
    if isinstance(content, str):
        content = [{"type": "text", "text": content}]
    content = [dict(b) if isinstance(b, dict) else b.model_dump(exclude_none=True) for b in content]
    content[-1]["cache_control"] = {"type": "ephemeral"}
    last["content"] = content
    return msgs
 
resp = client.messages.create(model="claude-sonnet-5-5", max_tokens=2048,
                              system=SYSTEM, tools=TOOLS,
                              messages=with_cache_on_last(messages))

Tham số và giới hạn

Mục Giá trị
Kiểu cache {"type": "ephemeral"}
TTL Mặc định 5 phút. Muốn 1 giờ thì dùng {"type": "ephemeral", "ttl": "1h"}
Số breakpoint tối đa 4 trong một request
Chỗ đặt được Tool definition, block system, block trong messages (text, image, tool_use, tool_result)
Độ dài tối thiểu Prefix ngắn hơn ngưỡng của model (cỡ một đến vài nghìn token) sẽ không được cache và không báo lỗi
Giá (tương đối với input thường) Ghi cache 5 phút ~1.25x, ghi 1 giờ ~2x, đọc cache ~0.1x
Phạm vi cache Theo organization/workspace, không chia sẻ giữa các tổ chức

Kiểm tra giá và ngưỡng chính xác cho từng model trên trang pricing trước khi tính chi phí.

Đọc usage

Trường Ý nghĩa
cache_creation_input_tokens Token vừa được ghi vào cache (tính giá ghi)
cache_read_input_tokens Token đọc từ cache (tính giá đọc)
input_tokens Token sau breakpoint cuối, không cache
cache_creation.ephemeral_5m_input_tokens / ephemeral_1h_input_tokens Lượng token ghi, tách theo TTL

Tổng input của request = input_tokens + cache_creation_input_tokens + cache_read_input_tokens.

Lỗi thường gặp

Triệu chứng Nguyên nhân Cách xử lý
Cả write và read đều bằng 0 Prefix ngắn hơn ngưỡng tối thiểu Chỉ cache phần dài (runbook, tool list lớn)
Lần nào cũng write, không bao giờ read Prefix thay đổi mỗi lần: timestamp, UUID, thứ tự tool ngẫu nhiên, json.dumps không sort_keys Đưa phần động ra sau breakpoint, giữ tools/system cố định
Read giảm sau vài phút không dùng Hết TTL 5 phút Dùng "ttl": "1h" cho tác vụ thưa, chấp nhận giá ghi cao hơn
400 khi thêm breakpoint Quá 4 cache_control trong một request Gom lại: tools/system dùng 1 breakpoint, hội thoại dùng 1
Cache miss sau khi thêm hoặc bớt tool Tools nằm đầu prefix nên mọi phần sau bị miss Cố định danh sách tool trong một phiên
Request song song đều write Cache chỉ sẵn sàng sau khi response đầu tiên bắt đầu trả về Gửi 1 request "làm nóng" trước rồi mới fan-out

Tham khảo