Claude Media
Claude Fable 5のsend_to_userツールで非同期タスクの進捗を届ける

Claude Fable 5のsend_to_userツールで非同期タスクの進捗を届ける

Claude Fable 5の非同期エージェントに中間報告を届けるsend_to_userツールの設計を、公式ガイドのJSON定義とシステムプロンプトの書き方から解説します。

Claude Fable 5にsend_to_userツールが必要になる場面

Claude Fable 5は長時間・非同期のタスクに強いモデルですが、ターンを終えるまでユーザーは基本的にモデルの出力を見られません。数十分から数時間かかるエージェントを走らせている途中で、生成済みのコードスニペットや下書きメッセージ、ユーザーが実行中に投げた質問への直接回答をそのまま届けたい場面が出てきます。こうした逐語のまま見せる必要がある内容を、ターンを終えずに表示する仕組みがsend_to_userツールです。

このツールは進捗のナレーション用ではなく、「ユーザーが正確にその文言のまま読む必要があるコンテンツ」専用の窓口です。ツールの入力は表示するメッセージそのもので、Claudeがこのツールを呼んだらUI側で入力をそのまま描画し、ツール結果として簡単な受領確認を返します。ツール入力は要約されずに渡されるため、内容が欠けたり丸められたりせずに届きます。

ツール定義のJSONスキーマ(JSON tool schema)

示されているツール定義は次の通りです。

{
  "name": "send_to_user",
  "description": "Display a message directly to the user. Use this for progress updates, partial results, or content the user must see exactly as written before the task finishes.",
  "input_schema": {
    "type": "object",
    "properties": {
      "message": {
        "type": "string",
        "description": "The content to display to the user."
      }
    },
    "required": ["message"]
  }
}

構造はシンプルです。messageという文字列プロパティ1つだけを持ち、Claudeがこのツールを呼び出すたびに、そのmessageの中身をアプリのUIにそのまま出す実装をハーネス側で書きます。ツール結果は「表示しました」程度の短い確認文で十分です。

このツールを追加する判断基準も明確です。ユーザー体験がタスク完了前の逐語コンテンツ配信や、タスク途中でのユーザーとの直接的なやり取りに依存する場合にだけ足します。定型的な進捗報告しかしないエージェントなら、モデル自身の要約で通常は足ります。

ツール定義だけでは呼ばれない — システムプロンプトでの誘導が必須

ここが実装でつまずきやすい点です。ツールを定義しただけでは、Claude Fable 5はほとんど呼びません。システムプロンプトに明示的な指示がなければ機能しません。

ツールと組み合わせるべき誘導文言として、次の例が挙げられています。

公式ガイドの誘導文言(原文要約)

ツール呼び出しの合間で、ユーザーが逐語で読む必要のあるコンテンツ(部分的な成果物、ユーザーの質問への直接回答)を持っているときは、その内容でsend_to_userツールを呼ぶ。send_to_userはユーザー向けコンテンツにのみ使い、ナレーションや推論の出力には使わない。

この文言のポイントは2つです。1つ目は「ツール呼び出しの合間」というタイミングの明示で、いつ呼べばいいかをClaudeに具体的に伝えています。2つ目は用途の限定で、ナレーションや内部の推論過程をこのツール経由で流さないと明記している点です。ナレーション目的で多用すると、ツールを用意した意味が失われます。

使いどころと使いすぎの境界線

send_to_userを置くべきかどうかの判断は、次の表のように整理できます。

状況send_to_userの要否理由
数時間かかる非同期タスクの途中経過を数値付きで伝えるsend_to_userの要否必要理由数値入りの進捗はモデルの要約に頼ると精度が落ちやすい
タスク実行中にユーザーが投げた質問への直接回答send_to_userの要否必要理由質問への回答は逐語で正確に届く必要がある
生成済みコードスニペットや下書きメッセージの中間共有send_to_userの要否必要理由成果物は要約されると情報が欠ける
定型的な「〜を実行中です」というナレーションsend_to_userの要否不要理由モデル自身の要約で十分機能する
内部の推論過程の逐次表示send_to_userの要否使わない理由ツールの目的外。ナレーションや推論はルート対象外とされている

表からも分かる通り、線引きは「要約されると困る情報かどうか」です。数値や固有名詞を含む進捗、ユーザーへの直接回答、生成済み成果物は要約で劣化しやすいためsend_to_user向きです。逆に「今〜のステップです」という定型ナレーションは、モデルの通常の応答で足ります。

description欄はどこまで詳しく書くべきか

ツール定義のdescriptionをどこまで書き込むかは、送信ツールに限らずカスタムツール全般のベストプラクティスとして別途整理されています。Anthropicのカスタムツール設計ガイドは、ツール性能に最も影響する要素を詳細な説明文だと位置付けています。何をするツールかだけでなく「いつ使うか」「いつ使わないか」まで書き、ツールの説明文はおおむね3〜4文を目安にします。

先に示したsend_to_userのJSON定義はdescriptionが1〜2文とやや簡潔です。公開されている例をそのまま使う分には動きますが、複数のツールを併用するハーネスでは、send_to_userと他のユーザー向け出力手段(通常の応答テキストなど)との使い分けをdescription側にも書き込んでおくと、モデルが呼び出すべき場面をより正確に判断しやすくなります。「進捗のナレーションには使わない」という誘導は、システムプロンプトだけでなくdescription側にも重複させておいて損はありません。たとえば次のように書き足すと、用途の境界がツール定義単体からも読み取れるようになります。

"description": "Display a message directly to the user, verbatim, without ending your turn. Use this for a partial deliverable, a progress update with concrete numbers, or a direct answer to a question the user asked mid-task. Do not use this for routine narration of what you are about to do next; the model's normal response text already covers that."

呼び出し結果(tool result)の設計も軽視しない

カスタムツール全般のベストプラクティスは、ツールの応答は高シグナルな情報だけを返すよう設計することも求めています。内部的な参照IDのような不透明な値ではなく、次の判断に必要な最小限のフィールドに絞るという指針です。send_to_userのツール結果を「表示しました」という短い受領確認にとどめるのも、この指針と整合しています。表示内容そのものはUI側の責務であり、モデルに返す結果を膨らませてもツール呼び出しの精度は上がりません。ツール結果を必要以上に詳しくしてコンテキストを消費するのは、長時間の非同期タスクほど避けたい設計です。

同じベストプラクティスには、関連する操作は別々のツールに分けず1つのツールに統合するという指針もあります。send_to_userは入力がmessage1つだけの単機能ツールで、この指針とは逆の方向に見えるかもしれません。ただしこの統合指針が対象にしているのはcreate_prmerge_prのように性質の異なる複数操作で、公式ガイドがsend_to_userのような単機能ツールを名指しで対比しているわけではありません。「ユーザーへの逐語表示」という単一の役割しか持たないsend_to_userは、この指針の射程外と読めます。むしろ用途を1つに絞っているからこそ、システムプロンプト側で「いつ呼ぶか」を具体的に書きやすくなっています。

推論の逐語表示ではなくsend_to_userを使う

send_to_userが特に効くもう一つの場面が、推論過程をユーザーに見せたい場合です。Claudeに内部の推論をそのまま応答としてエコーさせる・書き起こさせる・説明させるような指示は、システムプロンプトやハーネスの指示に含めないよう注意が必要です。こうした指示はClaude Fable 5ではreasoning_extractionという拒否カテゴリを引き起こすことがあり、結果としてClaude Opus 4.8へのフォールバックが増える原因になります。

推論の可視性がアプリの要件として必要な場合、代替策は2段構えです。1つは構造化されたthinkingブロックをAPI経由でそのまま読み取ること、もう1つが本記事のsend_to_userツールで長時間実行中の進捗を表に出すことです。つまりsend_to_userは、進捗報告の手段であると同時に、モデルに推論の書き起こしを強制せずに済ませるための回避策としても位置付けられています。

進捗報告の中身を裏付けと結びつける

send_to_userで届ける進捗報告は、内容が正確であることが前提になります。長時間の自律実行中には虚偽の進捗報告(実際には終わっていない作業を完了したと申告する等)が起きることがあり、報告の前に各主張をそのセッション内のツール実行結果と突き合わせ、裏付けを取ります。テストが失敗していればその出力とともに失敗と報告し、未検証の項目は未検証だと明示させる、という運用です。send_to_userで数値入りの進捗を届ける設計を組むなら、このグラウンディングの指示を同じシステムプロンプト内に含めておくと、届く内容の信頼性が上がります。

タスク完了後の最終まとめも同じ配慮が要る

send_to_userはタスク完了前の中間報告用ですが、隣接する項目は、長時間・非同期のセッションを経たあとの最終まとめメッセージにも注意を向けます。多数のツール呼び出しを重ねた拡張セッションでは、Claude Fable 5は矢印つなぎの省略表記や、ユーザーが見ていない内部の思考への言及、過度に専門的な言い回しを含んだ、追いにくい文章を書くことがあります。

ユーザーが夜間や長時間、会話を見ずに過ごしたあとの最終メッセージは、ユーザーにとってそのタスクの内容を初めて目にする瞬間です。この最終メッセージは「作業中の思考の続き」としてではなく、読み手にとって仕切り直しの文章として書きます。作業中に使っていた省略表現や自分で作った略語はいったん置いて、完全な文で結果から書き始め、ファイル名やコミット、フラグのような識別子にはそれぞれ平易な説明を添える書き方です。

この配慮はsend_to_userで送る内容そのものにも当てはまります。作業途中の省略表現のままmessageに詰め込むと、逐語で表示される分だけ読みにくさがそのままユーザーに届きます。中間報告であっても、ユーザーがその文脈を初めて読む前提で完結した文章にしておくのが安全です。

非同期エージェント設計の他の要素との関係

send_to_userは単体の小さな機能ですが、Claude Fable 5を非同期・長時間タスクに使うときの設計全体の中に位置付けると効果が読み取りやすくなります。並列sub-agentへの委譲を積極的に行い、長時間実行では検証を別のsub-agentに切り出す、という設計も合わせて効いてきます。send_to_userはこうした裏側の並列処理や自己検証をユーザーからは隠したまま、届けるべき情報だけを表に出す役割を担います。

Claude Agent SDKでカスタムツールを定義する具体的な手順はAgent SDKカスタムツールの作り方にまとめています。sub-agentへの委譲を制御する仕組みはAgent SDKのサブエージェント上限を参照してください。

まとめ

Claude Fable 5で非同期の長時間タスクを組むなら、send_to_userツールはユーザーが逐語で読む必要のあるコンテンツを届ける専用の窓口として用意します。ツール定義自体はmessage1プロパティのシンプルなJSON schemaで済みますが、システムプロンプトで呼び出しタイミングと用途を明示しないと、Claude Fable 5はこのツールをほとんど呼び出しません。ナレーションや推論の垂れ流しには使わず、進捗の数値・直接回答・生成済み成果物のような「要約すると劣化する情報」に限定して呼ばせる設計にします。

この記事を共有:XはてブLinkedIn