DOCAPI-解體-003
REV2026.04
SUBJECTMESSAGES API
VOLUMEIII
LAYERHTTP · JSON
Kaitai Shinsho · Volume III · the foundation

Claude · API · 解體新書

a ten-chapter dissection of the Messages API · the bedrock beneath all harnesses
POST MESSAGES RESPONSE PARAMS TOOLS STREAMING THINKING CACHING VISION BATCHES
SURGEONCLAUDE
DRAFTED2026.04.08
FORMATSCROLL-HTML
VERIFIEDCONTEXT7
CHAPTERS10 + 序

卷一畫已裝好的代理人(Claude Code),卷二畫裝代理人的工廠(Agent SDK)。卷三這次往最深的地基走 —— Claude Messages API。這是一切之下那個 HTTP 端點:Claude Code 走它、SDK 走它、世界上任何用 Claude 的應用最終都走它。拆到這一層,就等於拆到骨頭。

API 的表面只有一個動詞與一個路徑:POST /v1/messages。但這個扁平的介面背後藏著豐富的結構 — 多模 content blocks、tool 協議、SSE 串流、extended thinking、prompt caching、批次非同步處理。每一項都是可以單獨拆解的小宇宙。

本卷同樣分十回,從最簡單的 curl 一次呼叫開始,到進階的 prompt caching 與批次 API。程式碼同時呈現原始 HTTP / curl、Python SDK、與 TypeScript SDK — 你知道原始協定長什麼樣,就不會被任何一層抽象蒙蔽。

I.

信之所至

POST /v1/messages · the only endpoint that matters
FIG · 01
REQUEST

Claude API 表面上是一個 REST API,但實際上你幾乎只需要記住一條 URL:POST https://api.anthropic.com/v1/messages。一切與模型的對話都走這一條。本章拆解它的最小必要請求 — 哪些 header 非附不可、哪些欄位必填、以及三種呼叫方式(curl / Python / TypeScript)怎麼寫。

HTTP METHOD + URL POST https://api.anthropic.com /v1/messages REQUIRED HEADERS · 三道必附 x-api-key: sk-ant-api03-xxxxxxxxxxxxxxxxxxxx anthropic-version: 2023-06-01 content-type: application/json 選用: anthropic-beta(啟用 beta features)· x-anthropic-priority(service tier) REQUEST BODY · JSON MINIMAL VALID { "model": "claude-opus-4-6", // required · 模型 id "max_tokens": 1024, // required · 最大輸出 token 數 "messages": [ // required · 見第貳回 { "role": "user", "content": "Hello, Claude" } ] } THREE WAYS TO CALL · 三種呼叫姿勢 ▸ curl curl https://api.anthropic.com\ /v1/messages \ -H "x-api-key: $KEY" \ -H "anthropic-version:..."\ -d '{...}' ▸ python · anthropic SDK from anthropic import Anthropic client = Anthropic() r = client.messages.create( model="claude-opus-4-6", max_tokens=1024, ...) ▸ typescript · @anthropic-ai/sdk import Anthropic from "@anthropic-ai/sdk"; const c = new Anthropic(); const r = await c.messages.create({ model, max_tokens, messages })
x-api-key從 Anthropic Console 取得的 API key。格式 sk-ant-api03-...。請視同密碼 — 環境變數 ANTHROPIC_API_KEY 是 SDK 自動讀取的名字。
anthropic-versionAPI 版本標頭。現行穩定值 2023-06-01,新功能需要這個版本以上。SDK 會自動帶。
model目前主力模型:claude-opus-4-6(最強)、claude-sonnet-4-6(平衡)、claude-haiku-4-5(便宜快)。
max_tokens必填 — 而且是「最多可以輸出」的上限,不是目標長度。設太低模型會被截斷;設太高只影響計費上限。
messages最簡情況:一個 {"role": "user", "content": "..."} 物件。複雜情況見下一章。
為何官方 SDKSDK 處理 retry、rate limit、streaming parser、型別推導、錯誤分類。直接 curl 沒有這些 — 適合探索,不適合生產。
II.

對話之骨

messages array & content blocks · the skeleton of conversation
FIG · 02
BLOCKS

messages 是一個陣列,依時間順序排列使用者與模型的交替輪次。每個 message 有 role"user""assistant")與 content。content 可以是一個字串(最簡)— 也可以是一個 content block 陣列(多模態、工具、思考)。本章列出所有 content block 型別與它們出現的場合。

messages[] · 交替往返 [0] role: "user" "查一下天氣" ← string content (簡) [1] role: "assistant" content: [ TextBlock, ToolUseBlock ] [2] role: "user" content: [ ToolResultBlock ] ← 工具結果回注 [3] assistant [TextBlock] 最終回答 CONTENT BLOCK CATALOG · 六大區段型別 ① TextBlock 文字區段 { "type": "text", "text": "..." } 雙向都可用 最基本型別 ② ImageBlock 圖像區段 { "type": "image", "source": {base64 | url} } 只在 user 見第玖回 ③ DocumentBlock 文件區段 (PDF) { "type": "document", "source": {...}, "title":... } 只在 user ④ ToolUseBlock 工具請求區段 { "type": "tool_use", "id", "name", "input" } 只在 assistant 見第伍回 ⑤ ToolResultBlock 工具結果回注 { "type": "tool_result", "tool_use_id", "content", "is_error": bool } 只在 user ⑥ ThinkingBlock 延伸思考區段 { "type": "thinking", "thinking": "...", "signature": "..." } ⚠ ALTERNATION RULE · 強制交替 · messages 必須以 user 開頭,且 role 嚴格交替 user → assistant → user → assistant … · 同一個 role 的連續兩則訊息會被 API 拒絕(HTTP 400) · 工具結果不是獨立訊息 — 它是下一則 user message 的 content block,合併帶 tool_result 與正常文字 A · string content (shortcut) {"role": "user", "content": "Hello"} // 等同 [{type:"text", text:"Hello"}] B · array content (full form) {"role": "user", "content": [ {"type":"image", ...}, {"type":"text", "text":"..."}]}
role 二選一目前只有 "user""assistant"。系統指示走另一個頂層參數 system(見第肆回),不放在 messages 裡。
content 雙形式若只有純文字用字串最方便;要混圖片、tool_result、或需要 cache_control 標記,就必須用陣列形式。
assistant 能放的 blocktext · thinking · tool_use。assistant 不能放 image、document、tool_result。
user 能放的 blocktext · image · document · tool_result。user 不能放 thinking、tool_use(這兩個是模型專屬)。
歷史編輯你可以在傳送前任意修改過去的 messages — 這是 replay / branching 的基礎。但要保持 role 交替與 tool_use/tool_result 配對。
連續交替若你想讓 assistant 一次說兩段,請把它們合併為同一個 message 的多個 TextBlock,而不是兩個 assistant message。
III.

回音之型

response envelope · what comes back & why it stopped
FIG · 03
RESPONSE

API 回你的不是一堆字 — 是一個結構化的 JSON envelope。裡面有九個欄位,其中 stop_reason 告訴你為什麼模型停下來、usage 告訴你花了多少 token。讀懂這兩個欄位,你的應用層就知道該繼續、該重試、還是該結算。

▸ HTTP 200 · application/json RESPONSE id : string "msg_01XFD678..." 訊息唯一識別字 type : "message" 固定字串,未來可能擴充 role : "assistant" 固定 assistant(因為是模型的回覆) content : array<ContentBlock> 模型實際產生的內容 — text / thinking / tool_use 的組合 model : string "claude-sonnet-4-6" 實際執行的模型(可能不同於 request 指定的 alias) stop_reason : string | null 為什麼停下來 — 六大可能,見右側 stop_sequence : string | null 若是 stop_sequence 停的,這欄記錄是哪一個 usage : object input_tokens : int · 新輸入 token 數 output_tokens : int · 輸出 token 數 cache_creation_input_tokens : 寫入快取 cache_read_input_tokens : 讀自快取 cache_creation : {ephemeral_5m_, ephemeral_1h_} service_tier : "standard" | "priority" | "batch" inference_geo : "us-west-2" 等 server_tool_use : {web_fetch_requests, ...} container : string | null (code execution container id) total billed input = input_tokens + cache_creation_input_tokens + cache_read_input_tokens stop_reason · 六值辨析 ① "end_turn" 模型自然說完想說的 — 最常見的正常結束 應用層處理:把 content 呈現給使用者 ② "max_tokens" 打到 max_tokens 上限而被截斷 應用層處理:提高 max_tokens 或讓用戶繼續 ③ "stop_sequence" 命中你設定的 stop_sequences 之一 stop_sequence 欄位告訴你是哪一個 ④ "tool_use" 模型想呼叫工具,暫停等你執行 應用層處理:執行工具 → 回傳 tool_result → 再發一次 API ⑤ "pause_turn" 長時 server tool 執行中暫停(如 web_search) 應用層處理:把整份 content 原封丟回繼續呼叫 ⑥ "refusal" 模型拒絕回答(安全策略觸發) 應用層處理:尊重拒絕;不應重試同樣 prompt streaming 模式下,stop_reason 在 message_delta 事件才出現 (message_start 事件的 stop_reason 為 null)
tool_use 迴圈 · 主要 agentic 路徑

stop_reason == "tool_use" 是 agent 框架背後最重要的分歧。看到它就表示:把 content 裡的 ToolUseBlock 取出、執行工具、把結果作為 tool_result 放進下一個 user message、再呼叫一次 API。Claude Code 與 Agent SDK 都在幫你跑這個迴圈 — API 層你要自己跑。

quota math · 計費算術

帳單上的輸入 token = input_tokens + cache_creation_input_tokens + cache_read_input_tokens。其中 cache_read 部分單價只要 10%(5m)或 8%(1h),cache_creation 則貴 25%。詳見第捌回。

IV.

諭令微調

system prompt & sampling parameters · the knobs
FIG · 04
PARAMETERS

messages 之外,request body 還有一堆旋鈕可轉 — system 定義模型身分、temperature / top_p / top_k 控制隨機性、stop_sequences 設早停條件、metadata 帶請求辨識資訊。本章把這些全部列出來並給出合理預設。

A · system · 頂層 system prompt(不在 messages 裡) A-1 · string form {"model": "...", "system": "You are a helpful…", "messages": [...]} A-2 · array form (allows cache_control) "system": [ {"type":"text", "text":"你是...", "cache_control":{"type":"ephemeral"}}] SYSTEM PROMPT · 三個用途 ① 角色/人格設定 「你是資深 Python 工程師...」 ② 行為規則 「永遠用 type hints、拒絕寫 eval...」 ③ 固定脈絡(適合快取) 「下列是 API 文件... [50K tokens]」 B · SAMPLING · 隨機性控制 temperature · 0.0 ~ 1.0 溫度 0 0.5 1.0 低 = 穩定複現;高 = 創意發散 預設 1.0;程式任務建議 0.0~0.3 top_p · 0 ~ 1 核採樣閾值 從累積機率 ≤ p 的最小 token 集中採樣 與 temperature 擇一調整 不建議同時改這兩個 預設 1.0(不限制) top_k · positive int 前 K 候選 只從機率最高的 K 個 token 採樣 advanced · 一般不用 對話類幾乎無需調整 預設不設(無限) C · CONTROL · 停機條件與輔助欄位 max_tokens · integer · REQUIRED 最大輸出 token 上限 — 必填 · 達到時 stop_reason = "max_tokens" · 與模型的上下文窗 (200K / 1M) 不同 — max_tokens 是輸出長度 stop_sequences · string[] 自訂停止符 — 最多 4 個 · 打到就停 · 適合結構化輸出(如 "\nObservation:" 結束 ReAct) · 被觸發時 stop_reason = "stop_sequence" metadata · object { "user_id": "uuid-or-hash" } 用於濫用追蹤;勿放個資 — opaque 識別即可 安全審計與 rate limit 分配依此欄 service_tier · (via header) 透過 anthropic-priority header 設定 "standard"(預設) · "priority"(較快但更貴) · "batch"(50% 折扣,非同步) response.usage.service_tier 會告訴你實際用的是哪個 「多數旋鈕預設已經夠好 — 除非你確定,不然別動它們。」
system 為何獨立因為它是「穩定不變」的指示層,與每次 turn 變化的 messages 分離。分開存放讓 prompt caching 可以只快取 system 而不動歷史。
temperature vs top_p兩者都影響採樣隨機性,但機制不同。官方建議只改其中一個。溫度較直觀,大多數情境用它就夠。
max_tokens 小技巧設成「你預期最長答案的 1.5 倍」。設太大浪費也沒壞處(只計算實際輸出),設太小會被截斷。
stop_sequences 限制最多 4 個字串。字串要夠獨特 — 太短的字串(如 ".")會過早觸發。
metadata.user_id 用途若你的產品有多使用者,請為每個使用者產生穩定的 opaque 識別(不是真實 email/姓名)填入。Anthropic 以此為單位做濫用檢測與速率限制。
service_tier batch走 batch tier 要改用 /v1/messages/batches 端點,不是在 header 切換。見第拾回。
V.

器械交響

tool use protocol · request tools · parse tool_use · return tool_result
FIG · 05
TOOL CYCLE

Tool use 是 API 層最精巧的協議。你宣告工具、模型決定用哪個、你執行它、把結果回傳 — 這個循環在 API 層全都要你親手跑。三個步驟:宣告tools 欄位)、接收ToolUseBlock)、回注ToolResultBlock 放進下一個 user message)。

① DECLARE · 宣告 tools 欄位(request body 頂層) request body "tools": [{ "name": "get_weather", "description": "Get current weather for a city", "input_schema": {"type":"object", "properties":{"city":{"type":"string"}}, "required":["city"]} }], "tool_choice": {"type": "auto"} // or "any" / {"type":"tool","name":"..."} ② CYCLE · 四步迴圈 STEP A · POST 你發起請求 messages + tools (上方宣告) client → API STEP B · RESPONSE 模型想用工具 stop_reason = "tool_use" content 含 ToolUseBlock {id, name, input} API → client STEP C · EXECUTE 你執行工具 get_weather(city="Tokyo") → "25°C, 晴" client side STEP D · RESEND 再送一次 原 messages + assistant 那則 + new user with tool_result loop until stop_reason != "tool_use" ③ BLOCK SHAPES · 兩個 block 的配對 ASSISTANT message content[n] · ToolUseBlock { "type": "tool_use", "id": "toolu_01A09q90qw9w", "name": "get_weather", "input": {"city": "Tokyo"} } // 模型產生;你不可改 NEXT USER message content[n] · ToolResultBlock { "type": "tool_result", "tool_use_id": "toolu_01A09q...", "content": "25°C, clear sky", "is_error": false } // 你產生;tool_use_id 必須對應
tool_choice · 強制模式

"auto"(預設)讓模型決定要不要用工具;"any" 強制它必須用某個工具(任意哪個都可以);{"type":"tool","name":"..."} 強制用特定工具。最後一種搭配單一工具可以做「強制結構化輸出」— 把 input_schema 當作你想要的 JSON 形狀。

parallel tool use · 同時多個

一個 assistant message 裡可以有多個 ToolUseBlock — 模型打算「同時呼叫這幾個」。你應該全部執行完,把全部的 ToolResultBlock 一次塞進下一則 user message 的 content 陣列,順序與 id 對應即可。

VI.

流之八事

SSE Streaming · eight event types & delta assembly
FIG · 06
STREAM EVENTS

把 request body 加上 "stream": true,API 就改用 Server-Sent Events 格式回你 — 不再是一個大 JSON,而是一連串小事件。總共八種事件型別,按序出現。本章畫出它們的時間序與組裝邏輯:客戶端如何從一堆 delta 重建完整訊息。

EVENT TIMELINE · 依序到達 t₀ · request sent t_end · stream closed EVENT message_start envelope open EVENT content_block_start block[0] opens DELTAS ×N content_block_delta text chunks EVENT content_block_stop block[0] closes LOOP … more blocks … thinking / tool_use EVENT message_delta stop_reason arrives EVENT message_stop stream end ASYNCHRONOUS · 可能隨時出現 ping keep-alive(忽略即可) error streaming 中的例外 DELTA TYPES · content_block_delta.delta 的 5 種子型別 ① text_delta {type, text} 文字段增量 對應 TextBlock ② input_json_delta {type, partial_json} 工具 input 增量 對應 ToolUseBlock ③ thinking_delta {type, thinking} 思考文字增量 對應 ThinkingBlock ④ signature_delta {type, signature} 思考簽章增量 用於 replay 驗證 ⑤ citations_delta {type, citations} 引用增量 搜尋結果引用 CLIENT ASSEMBLY · 客戶端組裝演算法 message = event.message # from message_start for event in stream: if event.type == "content_block_start": message.content[event.index] = event.content_block elif event.type == "content_block_delta": message.content[event.index].apply(event.delta) # 累加 elif event.type == "message_delta": message.stop_reason = event.delta.stop_reason # 最終原因 「SDK 會幫你組裝 — 自己 parse SSE 只在你用非官方 HTTP client 時需要。」
事件順序保證message_start 必為第一則、message_stop 必為最後一則;中間 content_block_* 依 block index 分群串列。同一 block 的 delta 順序保持、index 不會交錯。
ping 的存在意義SSE 長連線可能被中間 proxy 關閉。API 每 10~15 秒發一個 ping 事件維持連線。你的 parser 直接忽略它。
error 處理streaming 中若發生 internal error 或 overloaded,會收到 error 事件含 error.type 與 error.message。這時應該中止串流並顯示錯誤。
input_json_delta工具的 input 是結構化的 JSON,流式傳輸時會被切成「partial JSON 字串」片段。需要累加字串後再一次 parse 成 object。
signature_deltaextended thinking 會產生一段簽章(見第柒回)。這段簽章也是分片傳送,用 signature_delta 累加得到最終值。
SDK 抽象Python / TS SDK 的 messages.stream() 幫你把這八種事件組裝成增量物件並提供高階 iterator。直接用 SDK 通常不需要知道這層細節 — 但知道它幫你解決除錯問題。
VII.

靜思一界

Extended Thinking · budget_tokens & thinking blocks
FIG · 07
THINKING

Extended thinking 讓模型在「回答前」先做一段結構化思考 — 這些思考以 ThinkingBlock 的形式出現在 content 陣列裡。你可以在 request 設定 thinking.budget_tokens 控制允許的思考量。這一層是透明的:你看得見思考過程,但在多輪對話中把 ThinkingBlock 原封保留回傳,模型可以「繼續原本的思考線索」。

REQUEST · enable thinking { "model": "claude-opus-4-6", "thinking": { "type": "enabled", "budget_tokens": 16000 }, "messages": [...]} thinking 設定細節 budget_tokens · 思考階段的最大 token 數 ≥ 1024 · 不等於最終輸出 — 輸出另外算 · 越高越深思,但越貴越慢 一般用 4K~16K 之間 推理密集任務可到 32K RESPONSE · content[] content[0] · ThinkingBlock { "type": "thinking", "thinking": "Let me analyze...", "signature": "EqoBCkg..." content[1] · TextBlock { "type": "text", "text": "The answer is..." } content[N] · RedactedThinkingBlock 若思考內容觸發安全過濾, 會以加密形式保留: {"type": "redacted_thinking", "data": "..."} ⚠ PRESERVATION RULE · 思考保留規則 · 多輪對話中,若你要讓 API 繼續同一條思考脈絡 —— ThinkingBlock 必須原封不動保留在 assistant message 裡重新傳回 · 簽章(signature)是用來驗證這段思考確實出自模型 — 你不可以修改 thinking.text 後仍保留簽章 INTERLEAVING WITH TOOLS · 與工具交錯 ThinkingBlock "考慮是否查天氣" ToolUseBlock get_weather("Tokyo") ToolResultBlock "25°C" ThinkingBlock "綜合判斷..." TextBlock 最終回覆 think → act → observe → think → speak — extended thinking 讓模型能像人一樣穿插思考與行動
cost · 計費方式

thinking tokens 計入 output_tokens(以輸出費率計費)。budget_tokens 是上限,不是預算消耗總量 — 模型可能用得比上限少。但若撞上限,就直接結束思考強制輸出,效果可能不如給它更多空間。

when to use · 使用時機

複雜推理、多步驟計畫、數學證明、代碼複雜 refactoring —— 給它思考空間會顯著提升品質。但一般對話、簡單問答、已經結構化好的任務 —— 開 thinking 只是增加成本與延遲。

VIII.

憶之快徑

Prompt Caching · cache_control & the fast path to cheap tokens
FIG · 08
CACHE

有些 prompt 的前段很長且很固定 — 例如放了 50K tokens 的 API 文件當 system prompt。每次都重送是浪費。Prompt caching 讓你標記「這段請快取」— 下次請求若開頭一致,就按 10% 的折扣價從快取讀(cache_read)而不是重新處理。本章拆解它的協議、TTL 選項、與計費模型。

① FIRST REQUEST · cache creation request body · system 欄位標記快取 "system": [ {"type":"text", "text":"<50K tokens of API docs>", "cache_control": {"type": "ephemeral", "ttl": "5m"}} ] response.usage · 首次寫入快取 cache_creation_input_tokens: 50000 · cache_read_input_tokens: 0 · input_tokens: <prompt 其餘部分> cache_creation 按 125% 單價計 — 第一次較貴 ② NEXT REQUEST(5 分鐘內)· cache read response.usage · 命中快取 cache_creation_input_tokens: 0 · cache_read_input_tokens: 50000 · input_tokens: <新加的部分> cache_read 按 10% 單價計 — 最高可省 90% TTL OPTIONS · 兩個保存期限 "ttl": "5m" · 預設 · 5 分鐘內有命中會重置倒數 · cache_creation 單價: 1.25 × base · cache_read 單價: 0.10 × base 適合:對話期間反覆用到同一份 context "ttl": "1h" · 長效快取 · 1 小時保存期 · cache_creation 單價: 2.00 × base · cache_read 單價: 0.08 × base 適合:間隔較久但反覆命中的大型 prompt BREAKPOINTS · 最多 4 個快取切點 你可以在 prompt 裡放 多達 4 個 cache_control 標記,每個標記前面的所有內容是一個「快取段」 system prompt 基礎 [BP1] API 文件 [BP2] 使用者歷史 [BP3] 當前 turn [BP4] new input 命中條件:新 request 的前綴必須與某個 breakpoint 之前的內容「bytewise 完全一致」才會命中
cache 命中條件 · 完全一致

命中邏輯是逐 byte 比對 — 即使多一個空格、system prompt 改一個字,都會讓整段 cache 失效重建。設計 cacheable prefix 時要確保「變動部分一律放在 breakpoint 之後」,不要混在穩定內容裡。

cost math · 一個實例

50K tokens 的 system prompt,用 5m cache:第一次 50000 × 1.25 = 62500 tokens 計費;之後每次 50000 × 0.10 = 5000 tokens。若 30 分鐘內被命中 10 次 — 省下 (500000 × 0.9 − 12500) ≈ 437500 tokens 的費用。context 越大越划算。

IX.

多模之眼

Vision & Documents · image and document content blocks
FIG · 09
MULTIMODAL

Claude 可以看圖、讀 PDF、分析文件 — 都透過 content block 系統實現。ImageBlock 接受 base64 或 URL 來源、DocumentBlock 吃 PDF、SearchResultBlock 用於 RAG 管線。本章列出所有 source 型別與尺寸限制,並附實際 request 範例。

A · ImageBlock · 兩種來源 A-1 · base64 source { "type": "image", "source": { "type": "base64", "media_type": "image/png", "data": "iVBORw0KGgoAAAANS..." } } A-2 · url source { "type": "image", "source": { "type": "url", "url": "https://example.com/img.png" } } // API 會主動抓取該 URL 的內容 IMAGE FORMATS · 支援格式與限制 · media_type: image/jpeg · image/png · image/gif · image/webp · 單圖上限 5 MB · 單則 message 最多 20 張 · 最大解析度會被自動縮小至 ~1568 × 1568 · 每張圖約 ~1600 tokens(取決於尺寸) B · DocumentBlock · PDF 與長文件 PDF via base64 { "type": "document", "source": { "type": "base64", "media_type": "application/pdf", "data": "<base64 PDF bytes>" }, "title": "API Spec v2.pdf", "citations": {"enabled": true} DOCUMENT CAPABILITIES · media_type application/pdf · text/plain · text/html · 上限 PDF 最多 100 頁;單檔最大 32 MB · citations 啟用後,回答會自動帶頁碼引用 · 頁數計算 每頁 ≈ 1500~3000 tokens(依內容) 「圖與文件都是 content block — 你可以在一個 user message 裡混合文字、圖、PDF 與問題。」
base64 vs urlbase64 適合私有圖、url 適合公開圖與節省頻寬。URL 來源會由 API 端主動抓取 — 須確保該 URL 可公開存取且回應迅速。
media_type 必填base64 來源必須標明 media_type。若格式不符會拒絕(HTTP 400)。
token 成本圖片與 PDF 都會轉成 tokens 計費。粗估:一張 1024×1024 圖 ≈ 1500 tokens、一頁 PDF ≈ 2000 tokens。長 PDF 很貴 — 考慮搭配 prompt caching。
多圖策略單則 message 最多 20 張圖。若你有更多,分批成多輪對話,或先做檢索只選最相關的幾張。
vision 擅長什麼讀圖表、OCR、描述場景、從截圖抓 UI 元素、看圖解題。不擅長:極高精度的計數、細粒度定位座標。
citations 用法開啟後 assistant 的 TextBlock 會附 citations 陣列,每個項目含 document_index 與 page_number — 讓你在前端渲染「來源第 N 頁」。
X.

批次與檔案

Message Batches & Files API · async at 50% discount
FIG · 10
ASYNC APIs

若你能接受「幾分鐘到 24 小時內完成」而不是即時,可以走 Message Batches API — 價格打五折。一次提交最多 100,000 筆請求,API 會排進低優先佇列慢慢跑,跑完後把結果以 JSONL 提供下載。搭配 Files API 可讓你把大型附件(PDF、長文件)預先上傳、反覆引用而不必每次重傳。本章拆解這兩個端點的生命週期。

A · BATCHES LIFECYCLE · 批次生命週期 ① CREATE POST 批次 /v1/messages/batches requests: [ {custom_id, params} × N ② PROCESSING 排程中 processing_status: "in_progress" (低優先佇列) ③ POLL 輪詢狀態 GET /v1/messages/ batches/{id} "ended" = 完成 ④ DOWNLOAD 取結果 results_url JSONL 逐行 每行一個請求結果 BATCHES 特性 · 50% 折扣 — 所有 token(含快取)按一半計價 · 最多 100,000 請求/批次 · 批次總大小 ≤ 256 MB · 完成時限 24 小時 · 超過會回傳 expired 狀態(未處理的部分不計費) B · FILES API · 可重用的附件儲存 ① UPLOAD 上傳檔案 POST /v1/files (multipart form) → file_id ② REFERENCE in content 在 message 裡引用 {"type":"document", "source":{"type":"file", "file_id":"file_xxx"}} ③ REUSE 反覆引用 同一個 file_id 可 在多個 request 使用 不必重複上傳 DELETE 用完 自行刪除 釋出配額 WHEN TO USE WHICH · 選型決策表 即時對話 → 一般 POST /v1/messages · standard tier 不急的大量分析 → Batches API · 50% 折扣,容忍 24h 延遲 反覆查同一份 PDF → Files API 上傳一次,多個 request 用 file_id 引用 超長固定 context → Prompt caching(見第捌回)· 即時但省 90% 延遲極敏感 → priority service tier(via header)· 較貴但較快 「即時、便宜、預上傳 — API 給你三種互補的速率層。」
Batches custom_id每個批次請求必須帶 custom_id — 這是你自己給的識別字,用於把結果對應回原始請求。它會出現在結果檔的每一行。
Batches 可混模型同一個批次內可以混用不同 model、不同參數 — 每個請求都是獨立的 Message 參數。
Files 格式目前支援 PDF 與純文字。上傳後用 file_id 當作 document source 引用,效果與直接內嵌 base64 相同 — 差別在於省頻寬與方便重用。
Files 配額每個 workspace 有儲存配額上限。長期不用的檔案記得 DELETE 釋出空間。
組合技Batches + Files 一起用最划算:檔案上傳一次,把 10000 個分析任務打包成一個 batch,享 50% 折扣同時不重複傳檔。
不相容事項Batches 內的請求不支援 streaming(本來就不需要)。Extended thinking、tool use、vision 都支援。