寫第一個 request
messages、system、max_tokens、model 四件事;最常見的兩個新手錯誤怎麼避。
TL;DR
- 一個 request 必填四件事:
model、max_tokens、messages、(可選)system system跟messages是兩個獨立欄位——不要把指示塞進 user messagemax_tokens是上限不是預期長度——Claude 不會努力填到你給的數字
一個情境:兩個新手錯誤
第一次寫 Anthropic API 的時候很容易踩到這兩個雷:
錯誤 1:把指示塞進 user message
# 不要這樣
messages = [{
"role": "user",
"content": "你是一個專業翻譯。把下面句子翻成日文:今天天氣好"
}]
錯誤 2:把 max_tokens 當成「我要 500 字」
# 不要這樣
max_tokens = 500 # 想要 500 字的回答
兩個都會「能跑」,但會讓 prompt engineering 變得困難。第一個讓指示跟 user input 混在一起;第二個讓你以為調這個數字會影響回答長度(其實不會)。
最小可行 request
先裝 SDK:
pip install anthropic
from anthropic import Anthropic
client = Anthropic() # 讀 ANTHROPIC_API_KEY 環境變數
message = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[
{"role": "user", "content": "什麼是量子運算?一句話。"}
]
)
print(message.content[0].text)
對應 cURL(不一定要走 SDK——server 端要極簡部署、或語言沒 SDK 的時候直接 HTTP 也行):
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "What is quantum computing?"}]
}'
四個欄位拆開講
model
寫 model id 字串。抽成 config,不要散落在程式各處。升級新版的時候只改一個地方就好。
messages
是一個 array,每個元素是 {role, content}:
| role | 是誰 |
|---|---|
user | 使用者寫的、或你的 server 注入的內容 |
assistant | model 上一輪的回答(multi-turn 用) |
沒有 system role——system 是分離的欄位,下面講。
max_tokens
上限,不是目標。意思:
- 設
max_tokens=1024,Claude 答 30 token 就夠了,它就停 - 設
max_tokens=1024,Claude 想答 2000 token,它停在 1024,回stop_reason: max_tokens
實務取值:
| 場景 | 建議 |
|---|---|
| 短分類、yes/no、JSON 抽欄位 | 256–512 |
| 一般 chat 回答 | 1024–2048 |
| 長文生成、文章草稿 | 4096–16K |
| 長文 + extended thinking | 32K+(含 thinking budget) |
太低會被截斷;太高雖然只計實際 output token、不會多付錢,但會佔走 extended thinking 的 budget 上限、也讓你 context 預算難規劃。
system
最容易被新手錯放的欄位。它跟 messages 平行:
client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
system="你是一個耐心的數學家教,不要直接給答案,引導學生想。",
messages=[
{"role": "user", "content": "幫我解 5x + 2 = 3"}
]
)
為什麼分開:
- 跨 turn 持久:multi-turn 對話 system 只寫一次,所有 turn 都吃得到
- 不被使用者污染:user message 是 user 寫的,system 是你寫的。分開後 prompt injection 攻擊難一階
- prompt caching 有用:長 system 可以 cache(後面章節會講)
取出回應
response 不是純字串,是物件:
message.content[0].text # 真正的文字
message.stop_reason # "end_turn" | "max_tokens" | "stop_sequence" | "tool_use" 等
message.usage # {input_tokens, output_tokens, ...}
content 是 array 是因為將來 tool use、thinking、image 出現時,會有不同 type 的 block 並列。多數 chat 場景就是 content[0].text。production 寫法:
text = "".join(
block.text for block in message.content if block.type == "text"
)
更安全,不會被 tool_use block 弄爆。
包成 helper
整本系列後面會反覆用到,先包好:
def chat(messages, system=None, **kwargs):
params = {
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"messages": messages,
**kwargs,
}
if system:
params["system"] = system
return client.messages.create(**params)
注意 if system——API 不接受 system=None,要動態組。
接下來
下一篇處理兩個跟「對話流動性」有關的功能:multi-turn 對話(messages 怎麼接續、為什麼歷史每次都要重傳)跟 streaming(讓 user 看到 token 一個個冒出來)。

