Claude の Extended Thinking は、複雑な問題に対して Claude が「声に出して考える」ように深い推論を行う機能です。数学の難問、複雑な法的分析、多段階の戦略立案など、通常のモードでは見落としがちなステップを丁寧に踏んで回答を組み立ててくれます。
ところが、この Extended Thinking を使い始めた多くの方が「思考が途中で止まる」「タイムアウトエラーが返ってくる」「思考がループしているように見える」という問題に直面しています。せっかくの高度な機能なのに、うまく使いこなせないのは非常にもったいないことです。
私自身、個人開発で運用しているアプリのサポート文面の下書きや、問い合わせ分類の判断ロジックに Extended Thinking を組み込んでいます。導入したばかりの頃は、夜間バッチがタイムアウトで半分ほど落ちていて、朝のログを開くたびに胃が締めつけられるような思いをしました。原因はどれも派手なものではなく、設定の小さな取り違えでした。同じところでつまずく方が一人でも減るように、その時に手を動かして確かめたことを順に書いていきます。
Extended Thinking の仕組みを理解する
トラブルを解決する前に、まず Extended Thinking がどのように動作するかを理解しておきましょう。
Claude の Extended Thinking は、通常の回答生成の前に「thinking」ブロックを生成します。このブロック内で Claude は仮説の検証、反論の検討、複数のアプローチの比較などを行います。この思考プロセスはトークンとして生成されるため、利用者は budget_tokens というパラメータで最大思考トークン数を指定します。
重要な制約
Extended Thinking は Claude Sonnet 4.6、Claude Opus 4.6 などの上位モデルでのみ利用可能です(2026年4月時点)。Claude Haiku では対応していません。また、Extended Thinking を有効にすると通常よりも大幅にコストが増加します。budget_tokens に設定した上限まで思考トークンが消費される可能性があることを前提に設計してください。
問題パターン別トラブルシューティング
パターン1:タイムアウトエラーが返ってくる
最もよくある問題です。API から timeout や request_timeout というエラーが返ってきます。
原因
デフォルトのAPI タイムアウト時間(多くの場合600秒)を超えるような複雑な思考が発生した場合、処理が打ち切られます。budget_tokens を非常に大きな値(たとえば100,000以上)に設定した場合、思考時間がタイムアウトに達するリスクが高まります。
解決策1:ストリーミングを使用する
タイムアウト問題の最も効果的な解決策はストリーミングの活用です。非ストリーミングモードでは最初のトークンが返ってくるまでの時間が長く、タイムアウトが発生しやすくなります。
import anthropic
client = anthropic.Anthropic()
# ❌ タイムアウトリスクが高い(非ストリーミング)
# response = client.messages.create(
# model="claude-sonnet-4-6",
# max_tokens=16000,
# thinking={
# "type": "enabled",
# "budget_tokens": 10000
# },
# messages=[...]
# )
# ✅ ストリーミングでタイムアウトを回避
with client.messages.stream(
model="claude-sonnet-4-6",
max_tokens=16000,
thinking={
"type": "enabled",
"budget_tokens": 10000
},
messages=[
{"role": "user", "content": "複雑な質問をここに書く"}
]
) as stream:
for event in stream:
# イベントタイプに応じて処理
if hasattr(event, 'type'):
if event.type == 'content_block_delta':
pass # テキストデルタの処理解決策2:budget_tokens を段階的に調整する
思考に必要なトークン数は問題の複雑さによって大きく異なります。まず小さな値(5,000〜10,000)から始めて、回答品質を見ながら少しずつ増やしていくアプローチが堅実です。
# 問題の複雑さに応じたbudget_tokens の目安
BUDGET_PRESETS = {
"simple": 5_000, # 単純な数学・論理問題
"moderate": 10_000, # 複数ステップの推論
"complex": 20_000, # 複雑な分析・設計タスク
"extreme": 50_000, # 非常に難しい研究・哲学的問題
}パターン2:思考が返ってくるが最終回答がない・空になる
thinking ブロックは取得できるが、その後の text ブロックが空か、期待と大きく異なる場合があります。
原因
max_tokens が不足しています。Extended Thinking では、budget_tokens(思考用)と最終回答のトークン数の両方が max_tokens の範囲内に収まる必要があります。
解決策
# ❌ 問題のある設定例
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=5000, # 思考に5000使い切ったら回答できない!
thinking={
"type": "enabled",
"budget_tokens": 5000 # max_tokens と同じ値は危険
},
...
)
# ✅ 正しい設定例
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=20000, # 思考トークン + 最終回答分を確保
thinking={
"type": "enabled",
"budget_tokens": 15000 # max_tokens より小さく設定
},
...
)設計の原則:max_tokens は budget_tokens の1.3〜2倍を確保してください。最終回答には5,000〜10,000トークンが目安です。
パターン3:思考がループしている・同じ内容を繰り返す
thinking ブロックを見ると、Claude が同じ検討を何度も繰り返しているように見えることがあります。これは計算コストの無駄遣いになります。
原因 プロンプトが曖昧すぎる、または矛盾した制約が与えられている場合に、Claude が答えを一つに絞れず思考を循環させることがあります。
解決策:プロンプトに構造と制約を与える
# ❌ 曖昧なプロンプト
messages = [
{"role": "user", "content": "このビジネスプランを評価してください"}
]
# ✅ 構造化されたプロンプト
messages = [
{
"role": "user",
"content": """
以下のビジネスプランを評価してください。
【評価の観点】
1. 市場規模の妥当性(日本市場、数値根拠を中心に)
2. 競合優位性(既存3社との比較)
3. 財務的実現可能性(3年間のキャッシュフロー観点から)
【制約】
- 評価は各観点100〜200字でまとめること
- 「可能性がある」等の曖昧な表現を避け、根拠を示すこと
- 総合評価は5段階で最後に示すこと
【ビジネスプラン】
{business_plan}
"""
}
]パターン4:コストが想定より大幅に高くなる
Extended Thinking は通常モードよりコストが高く、意図せず大量のトークンを消費することがあります。
原因の特定
# 使用トークン数を必ず記録する
response = client.messages.create(...)
thinking_tokens = sum(
len(block.thinking) if hasattr(block, 'thinking') else 0
for block in response.content
if block.type == 'thinking'
)
answer_tokens = response.usage.output_tokens - thinking_tokens
print(f"思考トークン: {thinking_tokens:,}")
print(f"回答トークン: {answer_tokens:,}")
print(f"合計コスト概算: ${(response.usage.input_tokens * 3 + response.usage.output_tokens * 15) / 1_000_000:.4f}")コスト最適化の設計パターン
パターンA:必要な場合だけExtended Thinkingを使う
すべてのリクエストにExtended Thinkingを適用するのではなく、問題の複雑さに応じて切り替える設計にしましょう。
def ask_claude(question: str, complexity: str = "auto") -> str:
"""
複雑さに応じてExtended Thinkingを動的に切り替える
"""
use_thinking = complexity == "high" or (
complexity == "auto" and _is_complex_question(question)
)
kwargs = {
"model": "claude-sonnet-4-6",
"max_tokens": 8000,
"messages": [{"role": "user", "content": question}]
}
if use_thinking:
kwargs["thinking"] = {"type": "enabled", "budget_tokens": 10000}
kwargs["max_tokens"] = 20000
return client.messages.create(**kwargs)
def _is_complex_question(question: str) -> bool:
"""簡易的な複雑さ判定"""
complexity_keywords = ["証明", "最適化", "なぜ", "比較", "設計", "分析"]
return any(kw in question for kw in complexity_keywords)パターンB:キャッシュを活用してコストを削減する
同じシステムプロンプトを使い回す場合はPrompt Cachingを組み合わせると効果的です。長いシステムプロンプトを cache_control でキャッシュし、Extended Thinking との組み合わせでコストを大幅に抑えられます。
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=20000,
thinking={"type": "enabled", "budget_tokens": 15000},
system=[
{
"type": "text",
"text": "長い専門的なシステムプロンプト...",
"cache_control": {"type": "ephemeral"} # キャッシュ有効化
}
],
messages=[{"role": "user", "content": question}]
)