前一輪,Claude 用 high 的 effort 排好了 SQLite 搬到 PostgreSQL 的三個步驟。下一輪你只要它用一句話把計畫講完。這時候把 output_config.effort 從 high 調成 low,Claude 那一端到底有哪些東西跟著動了?

這是官方文件裡的範例情境,問題卻很實際。一句話的摘要不需要深思,繼續用 high 是浪費。可是改頂層參數,文件寫得很直接:頂層 effort 一變,prompt cache 就失效。你前面累積的對話越長,這一下越痛。

9 月 1 日的 release notes 補了第二條路,叫 per-message effort,目前還在 beta。要看懂它為什麼能繞過快取,得先把 effort 本身拆開。

一個旋鈕,管到每一個輸出 token

effort 很像你交代同事做事時順口補的那句「這個仔細弄」或「這個隨便帶過就好」。它影響對方投入多少力氣,可沒規定要做滿幾個小時。官方的原話是:

Effort is a behavioral signal, not a strict token budget.

所以它不是 max_tokens 那種硬上限。等級有五個:low、medium、high、xhigh、max,其中 xhigh 不是每個支援 max 的模型都有。多數模型預設 high,Claude Opus 5.5 預設 medium。把 effort 設成模型的預設值,跟完全不寫這個參數,文件說行為一模一樣。

它管的範圍比很多人以為的大。文件寫的是「所有輸出 token」:一般文字、tool call 跟它的參數,有開 thinking 的話 thinking 也算在內。

Opus 5 有個例外要先講,不然後面會用錯。在 Claude Opus 5 上,文件寫 effort 控制的是 thinking 的量,不是你看得到的回覆長度。調低 effort,回覆不一定變短。你要的如果只是短一點的答案,在 Opus 5 上該動的是 prompt,不是這個旋鈕。

改在頂層,等於換一份樂譜重來

頂層的 effort 寫法很單純,output_config={"effort": "medium"},不需要 beta header,所有支援 effort 的模型都能用。

麻煩在中途改它。文件的說法是頂層 effort 變動會讓 prompt cache 失效,最佳實務是同一個靠快取撐著的對話裡,頂層 effort 從頭到尾不要動。快取為什麼對前綴這麼敏感,我在對話中途換工具那篇拆過,這裡不重講。

拿樂譜來比。一首曲子彈到第四十小節要轉慢,作曲家不會把整份譜重新印一次、在封面改成「慢板」。他在第四十小節上面寫一個速度記號,前面三十九小節一個音符都沒動。

改頂層 effort,就是把封面改掉重印。

夾一則沒有字的 system 訊息

per-message effort 就是那個速度記號。做法是在 messages 裡塞一則 role 為 "system" 的訊息,content 放空陣列,只帶一個 output_config.effort。下面是官方文件的 Python 範例,原封不動:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
client = anthropic.Anthropic()

response = client.beta.messages.create(
model="claude-fable-5-1",
max_tokens=4096,
output_config={"effort": "high"},
messages=[
{
"role": "user",
"content": "Plan a migration from SQLite to PostgreSQL in three short steps.",
},
{
"role": "assistant",
"content": "1. Export the SQLite data. 2. Create the PostgreSQL schema. 3. Import the data and verify row counts.",
},
# Effort-only system message: the new level takes effect from the next user turn.
{"role": "system", "content": [], "output_config": {"effort": "low"}},
{"role": "user", "content": "Summarize the plan in one sentence."},
],
betas=["mid-conversation-output-config-2026-07-01"],
)

for block in response.content:
if block.type == "text":
print(block.text)

頂層還是 high。倒數第二則那個空的 system 訊息把等級換成 low,從下一個 user turn 開始算,一直到後面又有別的訊息改它為止。cURL 版本同一頁也有,header 寫 anthropic-beta: mid-conversation-output-config-2026-07-01。

快取保得住的理由,文件只用一句話交代:

Everything before that message is unchanged, so the cached prefix still matches.

注意主詞是「那則訊息之前的所有東西」。保住的是它前面那一段前綴,不是整條對話不管怎麼改都沒事。而且前提是你本來就有開快取,沒開的話也沒什麼好保的。快取是 opt-in,要在請求裡帶 cache_control 才會啟用,前綴怎麼比對,Prompt Caching 那篇講過。

還有一個細節容易漏看。一般帶文字的 mid-conversation system 訊息有放置規則要守(帶文字的版本,換工具那篇談過),這種只帶 effort 的訊息沒有文字,所以那套規則不適用。它可以放在 messages 的任何位置,包括第一則,或夾在 assistant 回覆跟下一個 user 之間。速度記號本身不是音符,放哪一小節都不會打亂旋律。

這篇我只讀了文件,沒有實際呼叫 API,上面的範例沒有跑過,快取實際有沒有命中、usage 數字長怎樣,我都沒看過。功能還在 beta,header 帶的 2026-07-01 日期代表它還可能變動。

支援的模型:release notes 與 effort 文件頁的模型清單不一致,以下照 effort 頁、基準日 2026-10-06,列的是 Claude Fable 5.1、Claude Mythos 5.1、Claude Opus 5.5、Claude Opus 5、Claude Sonnet 5.5。9 月 1 日的 release notes 只寫了 Fable 5.1、Mythos 5.1、Opus 5 三個。Google Cloud 從 9 月 3 日起也提供,同一個 beta header,release notes 列的模型是 Fable 5.1、Mythos 5.1、Opus 5。

讓我意外的是另一半理由

讀到這裡,我原本以為 per-message effort 只是一個省錢技巧:同樣是換 effort,一個要重付快取,一個不用。

文件裡針對 Claude Fable 5.1 的那段建議,講的卻不只是錢。它建議優先用這種夾訊息的寫法,不要在請求之間改頂層值,理由有兩個。第一個是頂層改動會讓快取重來,這個前面講過。第二個是模型比較不會穩定遵循頂層的改動,因為它先前的回覆是在舊等級下寫的,而它傾向跟那些回覆保持一致。

這句話的分量比第一個理由重。

前一個理由是帳單問題。你算得出來,也可以決定忍。後一個是效果問題:你付了重算的錢,換來的可能是一個沒有好好換檔的模型。接下來這句是我自己的白話延伸,文件沒這樣寫:對話越長,它前面用 high 寫出來的回覆就越多,等於有一整疊「這段對話裡我都是這樣寫的」的範本擺在它眼前,而你只在最上面改了一個參數。

兩個理由疊在一起,結論就變成:在 Fable 5.1 上中途改頂層 effort,有可能錢多付了、等級卻沒換乾淨。

文件沒有解釋為什麼夾在中間的寫法比較不會被前文拖著走,我也不打算替它補一套說法。能確定的範圍就是文件寫的這些:這條建議是針對 Fable 5.1 寫的,其他模型文件沒有同樣的表述,我不會把它推到整份清單上。

我的做法是這樣。模型在支援清單上的話,對話中途要換 effort 一律用夾訊息,頂層 effort 在對話開頭定好就不再動。會讓我改變做法的條件有兩個:模型不在清單上,那就只能改頂層、接受快取重來;或者你用的是 Sonnet 5.5 又開了 between_tools 的 thinking,這個組合根本不能中途換,下一節會講。

如果你根本沒開快取,「保住快取」這個理由就不成立了。但在 Fable 5.1 上,一致性那個理由還在,我照樣會用夾訊息。

文件明寫會撞牆的幾條路

下面這幾條我自己沒撞過,是文件寫明會失敗的地方,列出來省得你親自去試。

最容易撞的是名字很像的模型。Claude Fable 5(不是 5.1)不支援 per-message effort,送出去會回 400,錯誤訊息是:

1
output_config.effort requires a model that supports per-turn effort; this model does not

看到這行不用去查 header 有沒有帶錯。先確認 model ID 是不是 claude-fable-5-1,而不是少了 -1 的那個。

Sonnet 5.5 搭配 thinking: {"type": "between_tools"}。這個組合下 effort 不能中途改,夾一則等級不同的訊息進去就是 400。真的要逐輪變動,文件說要改用 adaptive thinking。

還有一個比較像手滑:adaptive 是 thinking 的模式,不是 effort 的值。文件特別提醒不要把它當成 effort 填,effort 的值就是前面那五個等級。

這個記號不只寫在 API 裡

回到樂譜。速度記號這招能成立,靠的是兩件事:前面的小節不用重來,而且記號就寫在變化發生的那一格,不是印在封面上讓演奏的人自己去對。

前半句是快取,文件寫得明明白白。後半句是我拿來解釋 Fable 5.1 那條建議的比喻,文件只說夾訊息的寫法比較穩,沒說為什麼,所以這半句算我的推論。

不過我會把這個習慣帶到 API 以外的地方。長對話裡想換風格,不管是叫它簡短一點還是換個語氣,前面那一長串舊回覆一直都在,它們本身就是範本。這同樣是我讀完文件後的推論,沒有查證,你可以自己留意看看。對話真的長到該清掉舊內容,那是另一套工具的事,context editing 與 memory tool那篇寫過。

下次想在對話中途換檔,問自己一句就好:這個記號,我是要寫在第四十小節上,還是要把封面撕掉重印?

原文來源:Effort - Claude API Docs(取得日 2026-10-06)、Claude Platform release notes(2026-09-01、2026-09-03 條目)