0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

エージェント用途の Claude Fable 5:ツールコール拒否と GLM 5.2 とのコスト比較

0
Last updated at Posted at 2026-07-08

この記事は Synthorai ブログの記事 エージェント用途の Claude Fable 5:ツールコール拒否と GLM 5.2 とのコスト比較 の転載です。原文(多言語対応)はリンク先をご覧ください。

エージェント用途の Claude Fable 5:ツールコール拒否と GLM 5.2 とのコスト比較

我々の評価では、コーディングエージェントの 44 ターン中 11 ターンで Claude Fable 5 がツールコールの途中で拒否を返した。しかも対象は config のデフォルト値を修正するといった、ごくありふれたタスクだ。拒否はツール引数の生成途中で stop_reason: "refusal" として現れるが、途中で切れた引数は依然として有効な JSON としてパースできてしまう。stop reason をチェックせずにツールコールを実行するエージェントループは、書きかけのファイルを平然とディスクに書き込む。Fable 5 をエージェントに組み込むとき、まず対策すべきなのは価格ではなくこの挙動だ。

TL;DR

  • Claude Fable 5 は、ありふれたエージェントタスク(config のデフォルト値修正、会議室の予約)でツールコールの途中で stop_reason: "refusal" を返した。途中で切れた write_file の引数もパースできてしまうため、stop reason をチェックしないループは書きかけのファイルを実行する。
  • Fable 5 の思考は適応的で、オフにするスイッチがない。enableddisabled もどちらも拒否される。制御は output_config.effort で行う。
  • Fable 5 のコスト上乗せはワークロードの形状に依存する。4 ターンのコーディングタスクは $0.045 かかり、glm-5.2 の $0.003 に対して 15 倍だった。一方でウォームなバッチ処理では sonnet-5 の 5 倍にとどまった。
  • Fable 5 は 30 日間のデータ保持を要求する。

以下の内容はすべて 2026-07-05 に Synthorai ゲートウェイ経由で、小さなシナリオハーネスを使って計測した。エージェントワークロードを 5 つの形状(ツールを使うコーディングループ、RAG による質問応答、ツール中心のオーケストレーション、バッチ分類、15 ターンの会話)で用意し、claude-fable-5claude-opus-4-8claude-sonnet-5glm-5.2 に対して実行した。ばらつきが問題になるタスクは 1 つあたり 3 回走らせている。タスクはあえて自明なものにしてある。pass rate は能力を測るベンチマークではなく、正常動作の確認用のゲートだ。コストはゲートウェイが課金した usage.cost の値を使っている。

ツール呼び出しを実行する前に stop_reason を確認する

ドキュメントが警告してくれない類の障害で、状態を壊してしまう。エージェントが app.py を読み、修正を書こうと決めて write_file の呼び出しを吐き始める。ところがファイル内容の途中でストリームが止まる:

{
  "stop_reason": "refusal",
  "content": [{
    "type": "tool_use",
    "name": "write_file",
    "input": {
      "path": "app.py",
      "content": "DEFAULTS = {\n    \"timeout_s\": 30,\n    "
    }
  }]
}

input オブジェクトはパース可能な完全な JSON だ。「途中で止まった」ことを示すものは何もない。ループの契約が「ツール呼び出しを受け取ったら実行する」だと、app.py を 38 文字の断片で上書きしたことになる。その断片は辞書の途中で終わっていて Python としてもうパースできず、次のターンもまた refusal になるので、ワークスペースが壊れたままループが終わる。

このデータから 3 点が言える。

  • ありふれた作業で発生する。 refusal を引き起こしたタスクは、config ルックアップの KeyError の修正、slugify 関数の実装、会議室の予約、請求書ドラフトの作成だった。デュアルユースなものも機密性の高いものもない。
  • ランダムではなく再現する。 あるコーディングタスクは、streaming でも非 streaming でも 3 回全部で refusal を引いた。逆に一度も引かないタスクもあった。条件をまたいで、些細なコーディングのエピソードは Fable 5 では 58〜75% しか通らなかったのに対し、claude-opus-4-8、claude-sonnet-5、glm-5.2 はいずれも 100% だった。しかも失敗はすべて refusal が原因で、コードが間違っていたわけではない。
  • 一度会話に refusal が入るとエピソードは終わり。 その後のターンは空の出力で stop_reason: "refusal" を返した。同じコンテキスト内でリトライしても回復しなかった。

トリガーはタスクの内容ではなく、データはその点をはっきり示している。毎回 refuse したタスクは、config 辞書内の KeyError を直す 9 行の修正で、認証情報もエクスプロイトもなかった。一方、バッチシナリオはクリプトマイニングや流出した Stripe キー、フィッシングページに関するサポートチケットを一度も refuse せずに分類したし、RAG シナリオも AES-256-GCM の秘密情報や侵害対応手順で埋まったドキュメントを問題なく回答した。refusal はすべて、マルチターンでツールを実行する 2 つのシナリオで起きた。単発の 3 シナリオは、もっと重い内容を扱っても一度も refuse しなかった。パターンは言葉ではなくエージェントループの形にある。つまり入力をサニタイズしても防げない。

修正はツール実行ステップの前に 1 行入れるだけだ。

if response.stop_reason == "refusal":
    # do NOT execute tool calls from this turn: arguments may be truncated
    raise AgentInterrupted("model refused; restart episode or escalate")

Anthropic はこの仕組みを文書化している。出力が返る前に発火した refusal は空の content 配列を返し、課金されない。ストリームの途中で発火した refusal は既にストリームされた分の出力に課金され、部分的な出力は破棄するよう案内されている。レスポンスには stop_details オブジェクトも付き、カテゴリ(cyberbio など、あるいは null)が入るので、分類器によるブロックと通常の拒否を区別できる。ドキュメントが明示していないのは、上で遭遇したツール利用との相互作用だ。refusal は引数生成の途中で発火し得るし、部分的な引数は完全なものと見分けがつかない。

公式の回復パスもある。Claude API では beta の fallbacks パラメータ(betas: ["server-side-fallback-2026-06-01"]fallbacks: [{"model": "claude-opus-4-8"}])を使うと、拒否されたリクエストを同じ呼び出しの中でフォールバックモデルで再実行できる。拒否自体は、出力前に発火していれば課金されない。これは Amazon Bedrock、Vertex AI、Microsoft Foundry では使えず、そちらでは SDK がクライアント側のフォールバックミドルウェアを提供している。どのパスを使うにせよ、上のガードが先だ。stop reason が refusal のターンからツール呼び出しを絶対に実行しないこと。

5 種類のエージェント構成のコスト

完了 1 単位(タスク、クエリ、アイテム、会話)あたりのコスト中央値。同じプロンプト、同じ日に計測した。

シナリオ fable-5 opus-4-8 sonnet-5 glm-5.2
コーディングループ(タスクあたり、4 ターン中央値) $0.045 $0.012 $0.0059 $0.0031
RAG 回答(クエリあたり) $0.024 $0.0075 $0.0036 $0.0031
ツールオーケストレーション(タスクあたり) $0.048 $0.011 $0.0045 $0.0027
バッチ分類(アイテムあたり、warm) $0.0024 $0.0012 $0.00046 $0.00057
15 ターンの会話(全体) $0.94 $0.34 $0.26 $0.083

この表は個々のセルよりも、次の 2 つの読み方が重要だ。

  • 最安のモデルは構成によって変わる。 ループと長い会話では glm-5.2 が勝つが、バッチ分類では claude-sonnet-5 がこのなかで最安になり、glm-5.2 を下回る。理由は、scaffold プロンプトが warm になれば cache-read の割合が 97% に達し、導入価格がそこに乗るからだ。
  • Fable 5 の割高さも構成依存だ。 コーディングループでは glm-5.2 の 15 倍、会話では 11 倍だが、warm なバッチアイテムではキャッシュがプロンプトの大半を吸収するため、sonnet-5 の 5 倍にとどまる。

コスト全体の話は、まずこれらの数字をどう抑えるか、そして次にそれらを静かに押し戻す 2 つの要因についてだ。

エージェントの請求額を抑える

キャッシュが最大のレバーであり、Fable 5 でもその仕様は変わっていない。エージェントのデータがその価値を示している。cache_control マーカーを外すと、同じコーディングタスクのコストは 2.0 倍、warm なバッチアイテムは 6.8 倍になった。opus-4-8 で同じ ablation を行うと、それぞれ 3.8 倍と 6.9 倍だった。ループにおいて、sliding-marker パターンは最適化ではない。請求額が現実的なものになるか、ならないかの分かれ目だ。

2 つ目のレバーはプロンプトの順序で、試したすべてのモデルで効果があった。安定したルールをクエリごとのコンテキストの後ろではなく前に置くと、4 モデルすべてで RAG クエリが 26〜37% 安くなった。Claude 系では、順序を誤ると呼び出しごとに 1.25 倍の cache-write プレミアムまで支払うことになる。仕組みは LangChain caching の記事にあり、ここでの数字はそれが Fable 5 でもそのまま当てはまることを裏づけているにすぎない。

Fable 5 は独自のレバーも 2 つ加えている。1 つ目は、キャッシュ対象となる下限が 2,048 token に下がったこと。Opus 4.8 の 4,096 の半分だ。これは些細な話に聞こえるが、エージェントの節約がどこから生まれるかを思い出せば意味がわかる。繰り返し使われる scaffold(system プロンプト、ツール定義、sliding な会話のプレフィックス)がキャッシュされる対象であり、それも下限を超えたときだけだ。ターンごとのプレフィックスが 2,048〜4,096 token に収まるツール中心のエージェントは、Opus 4.8 ではキャッシュがまったく効かなかったが、Fable 5 では効き始める。フルプライスのプレフィックスが、以降のすべてのターンでおよそ価格の 10% の cache read に変わる。逆方向にも働く。旧来の 4,096 の下限を超えるために水増ししていたプレフィックスは、いまや無駄な重りを抱えているかもしれない。Fable 5 では割引が早く始まるので、思い込みではなく、実際のレスポンスから cache_read_input_tokens を読むこと。

2 つ目は task budgets(beta、ヘッダー task-budgets-2026-03-13)で、この比較が繰り返し浮き彫りにしてきた問題そのものに対処する。Fable 5 のループは請求額をあっという間に積み上げるが、max_tokens では役に立たない。これはモデルからは見えないレスポンスごとのハードな上限なので、モデルは無制限の余地があるかのように計画を立て、思考の途中で打ち切られる。task budget はこれとは違う。ループに token の上限(最小 20,000)を与えると、モデルはそれを残りカウントダウンとして把握し、それに合わせてペース配分し、切り捨てられるのではなくきれいに締めくくる。カウント対象は、モデルが生成したものと、そのターンで読み込んだツールの結果であって、毎回のリクエストで再送信する全履歴ではない。コーディングループのターンコストが glm-5.2 の 15 倍になるモデルにとって、モデル自身が守るように調整する budget は、後付けできる最も安上がりなガードレールだ。

ドキュメントが警告してくれないコストの落とし穴が 2 つ

主要なレバーを設定し終えても、ドキュメントには書かれていない方向で請求額を動かす、もう少し細かい要素が 2 つ残っていた。

「low」設定は安くならなかった。 Fable 5 の思考の深さは output_config.effort で制御する。直感的には low が一番安いと思うだろう。実際は違った。effort: "low" を指定してコーディングループを回すと 1 タスクあたり $0.0478 かかり、デフォルトの $0.0451 より高い。しかも output token は減るどころか増えた。同じ傾向は GLM 5.2 でも見られ、こちらでも effort の名前は token 数と対応していない。どちらのモデルラインでも、「low」が「少ない」を意味すると決めつける前に、自分のワークロードでこのつまみを実測すること。数値が読みにくい理由の一つは、adaptive thinking が output token に占める割合が同じモデル・同じ日でもコーディングループでは 2%、RAG の回答では 30%、バッチ分類では 52% と振れることだ。output token の予算はモデル単位ではなく、ワークロードの形状ごとに見積もる。

reasoning_content を絶対に再送しない。 OpenAI 互換モデルでは、reasoning フィールドは会話履歴ではない。DeepSeek の API はこれを除去することを要求する。GLM 5.2 では再送しても構文上は通るが、課金される。メッセージ履歴に戻し続けた結果、GLM ループのコストが約 28% 膨らみ、除去してようやく収まった。Anthropic 自身の thinking ブロックは事情が違う。同じモデルでは thinking ブロックを変更せずに再送しなければならないが、Fable 5 の thinking ブロックが別のモデルに回された場合(例えば Opus へのフォールバック時)は、プロンプトから自動的に削除され課金もされないので、除去する必要はない。

リクエスト面の変更点

Fable 5 はリクエスト面の大部分を Opus 4.7/4.8 と Sonnet 5 と共有している。ドキュメントによると、廃止されたのは以下のとおり。

  • thinking: {type: "enabled", budget_tokens: N} は 400 を返す。token 予算付きの extended thinking(Claude 3.7 Sonnet から 4.5 系まで使われてきた仕組み)は、4.7 以降のラインで廃止され、adaptive thinking に置き換えられた。
  • thinking: {type: "disabled"} は 400 を返す。これは Fable 5 に固有の挙動だ。Opus 4.7/4.8 と Sonnet 5 では thinking をオフにできるが、Fable 5 ではできない。
  • temperaturetop_ptop_k はデフォルト以外の値を指定すると拒否される。
  • assistant メッセージの prefill(末尾の assistant ターン)は 400 を返す。

移植したリクエストで最もよく引っかかるのは、temperature/top_p/top_k の拒否と prefill の廃止だ。thinking と保持まわりの変更については、上記と保持に関する記事で扱っている。

まとめ

エージェントに組み込んだ Fable 5 は、予算の問題である前にエンジニアリングの問題だ。tool call を実行する前に stop_reason: "refusal" を処理すること。さもないと、config の修正程度の退屈なタスクでも、write が途中で切れて状態を壊す。次にコストは自分で形作るものとして扱う。キャッシュが最大のレバーで、対象となる下限は今や 2,048 token なのでプレフィックスを再確認すること。タスク予算を設けておけば、この比較で 1 ターンあたり最も高い請求をループが積み上げるのを防げる。そして effort: "low" は名前が示すような割引ではない。予算はワークロードの形状ごとに立てること。同じモデルでも、コーディングループでは glm-5.2 の 15 倍、ウォームなバッチ処理では sonnet-5 の 5 倍かかる。ここで言いたいのは使え・使うなという話ではない。デフォルトは中立ではなく、請求も失敗モードもエージェントの形状次第で変わるということだ。

FAQ

Fable 5 はツールコールを頻繁に拒否しますか?
特定のタスクに集中していました。ある config 修正タスクは毎回拒否され、他のタスクは一度も拒否しませんでした。同じタスクは streaming と非 streaming の両方で再現します。つまり、リトライで回避できるまれな一時的エラーではありません。ワークロードによって発生率は変わりますが、エンジニアリング上の答えはどちらでも同じです。ツールコールを実行する前に stop_reason を確認してください。

Fable 5 の thinking はオフにできますか?
できません。thinking.type.disabledenabled もどちらも拒否されます。thinking はデフォルトで adaptive であり、制御できるのは output_config.effort だけです。今回のループでは、low effort にしてもコストは下がりませんでした。

Fable 5 が安く済むケースはありますか?
このセットの中ではありません。最も割増が小さいのは、warm cache を多用するバッチ処理で、sonnet-5 の約 5 倍です。ここでは warm cache がプロンプトの大部分を吸収します。ループと長い会話では、今回計測した中で最もコストの高いモデルでした。


検証:全数値は 2026-07-05 に https://synthorai.io/ に対して計測(Claude 系は Anthropic ネイティブの /v1/messages、glm-5.2 は /v1/chat/completions)。5 種類のシナリオ形状にわたり 505 エピソード、1,022 コール、ばらつきが問題になるタスクは 3 回ずつ実行。コストはゲートウェイが報告する usage.cost で、中央値を表示。タスクは意図的にシンプルにしているため、pass rate は健全性チェックであって能力ベンチマークではありません。計測していない能力についての主張は公開しません。拒否の挙動は streaming と非 streaming の両モードで再現しました。数値はプロンプト、リージョン、負荷によって変わります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?