
【CCA Foundations対策 / Claude API編 #12】エージェントの設計——ツール抽象化・環境観察・ワークフローとの使い分け
Anthropic Academyの「Claude APIを使用した構築」コースをもとに解説しています。
前回(#11)はワークフロー設計の4パターンを解説した。今回はエージェントに移る。エージェントはワークフローと何が違うのか、どう設計するのか、そしていつ使うべきかを整理する。
この記事でわかること:
- エージェントの定義と、ワークフローとの本質的な違い
- 抽象的なツール設計がなぜエージェントを強力にするか
- 環境観察(Environment Inspection)を設計に組み込む理由
- 長いセッションでの状態永続化とマニフェストによるクラッシュ回復
- ワークフロー vs エージェントの判断軸
エージェントとは
エージェントとは、ゴールとツールのセットを渡して、Claudeに計画を立てさせる仕組みのこと。
ワークフローとの決定的な違いは「処理の流れを誰が決めるか」にある。
| ワークフロー | エージェント | |
|---|---|---|
| 処理の流れ | 開発者が事前に設計する | Claudeが実行時に決める |
| 柔軟性 | 低い(決まったタスクしかこなせない) | 高い(未知のタスクにも対応できる) |
| 信頼性 | 高い | 低め |
| 向いているタスク | 手順が予測できるもの | 何が来るかわからないもの |
ワークフローは「この問題を解くには手順A→B→Cが必要」とわかっているときに使う。エージェントは「どんな問題が来るかわからないが、このツールセットで対応させたい」というときに使う。
抽象的なツールを設計する
エージェント設計の核心は、ツールをどれだけ抽象的に作るかにある。
具体的すぎるツールの問題
「コードをリファクタリングするツール」「依存パッケージをインストールするツール」のように、タスクに特化したツールを作ると、そのツールが想定していないタスクには使えなくなる。開発者が事前に想定した用途だけしかこなせない——それはエージェントではなくワークフローに近い。
Claude Codeの設計例
Claude Codeが持つツールを見ると、抽象的なツール設計の理想形がわかる。
| ツール | できること |
|---|---|
bash |
任意のコマンドを実行 |
read |
任意のファイルを読む |
write |
任意のファイルを作成 |
edit |
任意のファイルを編集 |
glob |
ファイルを検索 |
grep |
ファイルの内容を検索 |
「リファクタリング」専用ツールも「依存関係インストール」専用ツールも存在しない。その代わり、bash・read・editを組み合わせることで、Claudeは開発者が想定していなかったタスクまでこなせる。
設計原則: ツールは「何をするか」ではなく「何ができるか」で定義する。Claude Code がまさにそれを体現している。
組み合わせが生む柔軟性
シンプルな日時ツールの例で考えてみる。
get_current_datetime ← 現在日時を取得
add_duration_to_datetime ← 日時に期間を加算
set_reminder ← リマインダーを設定
この3つのツールがあれば:
- 「今何時?」→
get_current_datetime1回で完了 - 「11日後は何曜日?」→
get_current_datetime→add_duration_to_datetime - 「来週水曜のジムのリマインダーを設定して」→ 3つすべてを使う
さらに「90日保証はいつ切れる?」という問いには、Claudeは追加情報が必要だと判断して「購入日はいつですか?」と聞いてくる。ツールが抽象的なほど、Claudeは創造的な組み合わせを考えられる。
環境観察(Environment Inspection)の設計
エージェントを設計するときに見落とされがちな重要原則がある——Claudeは自分の行動の結果を「見る」手段がなければ、盲目的に動くしかない。
なぜ環境観察が必要か
Claudeがボタンをクリックしたとする。そのクリックが新しいページを開いたのか、メニューが展開されたのか、エラーが出たのか——フィードバックがなければ、Claudeには何が起きたかわからない。
Claude Codeが「コンピューター操作(Computer Use)」を行う際、アクションのたびにスクリーンショットを受け取るのはこのため。「見る」ことなしに次の行動を判断できない。
ファイル操作への応用
同じ原則はファイル操作にも適用できる。Claudeに既存のPythonファイルにルートを追加させたいとする。
悪い設計: ファイルの中身を渡さずに「このファイルに新しいルートを追加して」と指示する
良い設計: まずClaudeにファイルを読ませてから、編集を指示する
現在のコードを理解してからでなければ、安全な変更はできない。読み込みが「環境を観察する」行為にあたる。
動画生成エージェントの例
複雑な動画生成エージェントであれば、こんな環境観察の設計が考えられる。
動画を生成
↓
Whisperで音声から字幕ファイルを生成 → 台詞の配置を検証
↓
FFmpegで動画から定点スクリーンショットを抽出 → 映像を確認
↓
生成物を要件と比較 → 問題があれば修正
エージェントが自分の出力を検証できる設計になっている。これによって「実行した」だけで終わらず、「うまくいったかを確認して、問題があれば直す」という動作ができる。
長いセッションでの状態管理
エージェントが複雑なタスクをこなすとき、処理が数十ステップにわたることがある。そのとき新たな問題が発生する——セッションが途中でクラッシュしたり、コンテキストウィンドウが溢れたりしたとき、最初からやり直しになる問題だ。
Structured State Persistence(状態の永続化)
エージェントの状態を外部に書き出しておく設計。
たとえば100件のドキュメントを順番に処理するエージェントがあるとする。内部の会話履歴だけで状態を持っていると、途中でセッションが切れたときに「どこまで処理したか」がわからなくなる。
状態をファイルや外部ストアに書き出しておけば、再開時に途中から続けられる。
処理するたびに状態ファイルを更新
{
"processed": ["doc_001", "doc_002", ...],
"pending": ["doc_045", "doc_046", ...],
"results": { "doc_001": "...", ... }
}
ポイントは「会話履歴の中だけに状態を持たない」こと。会話履歴はセッションと紐づいており、セッションが切れると失われる。
Crash Recovery Using Manifests(マニフェストによる再開)
マニフェストとは、エージェントが「今何をどこまでやったか」を記録したファイルのこと。クラッシュや中断が起きても、マニフェストを読み込めば処理を再開できる。
manifest.json
{
"task": "リサーチレポートの生成",
"status": "in_progress",
"completed_steps": ["web_search", "source_filtering"],
"next_step": "fact_verification",
"partial_output": "..."
}
エージェントは起動時にマニフェストを確認し、next_step から処理を再開する。最初からやり直す必要がない。
この設計が重要なのは、長時間・多ステップのタスクほどクラッシュのリスクが上がるため。エージェントが強力になるほど、再開可能な設計が前提になる。
ワークフロー vs エージェントの判断軸
エージェントは柔軟性が高い分、タスク成功率はワークフローより低くなる傾向がある。Claudeがどんな手順を踏むか予測できないため、テストも難しい。
基本的な考え方はシンプルだ。
ワークフローで実装できるならワークフローを選ぶ。エージェントは本当に必要なときだけ使う。
| ワークフローを選ぶとき | エージェントを選ぶとき |
|---|---|
| 処理の手順が事前にわかる | どんなタスクが来るか予測できない |
| 信頼性・一貫性が最優先 | 柔軟性が最優先 |
| 出力をEvalで測定したい | 手順が毎回異なってもよい |
| プロダクション環境 | 探索的なユースケース |
ユーザーはたいてい「エージェントを使っているかどうか」ではなく「ちゃんと動くかどうか」を気にしている。信頼性を担保できるならワークフローの方がプロダクション向きだ。
マルチエージェント設計のパターン
coordinator-subagent パターン
複雑なエージェントシステムでは、タスクを指示する「コーディネーター」と、実際に実行する「サブエージェント」に分ける設計が使われる。
コーディネーターはタスクを分解して各サブエージェントに割り振る。サブエージェントは自分に割り当てられたタスクだけを担当する。
混乱しやすい点: サブエージェントは親のコンテキストを自動的に引き継がない。コーディネーターが「ユーザーの要件はAで、制約はBで、前のステップではCが完了した」といった情報を、サブエージェントに明示的に渡す必要がある。「メインエージェントが知っていること」をサブエージェントも当然知っているとは限らない。
📋 試験ガイドより
公式試験ガイドのIn-Scope Topicsに「Subagent context management: Explicit context passing, structured state persistence, crash recovery using manifests」が明記されている。サブエージェントへの明示的なコンテキスト渡しは設計判断のポイントとして扱われており、Preparation Exercisesの演習4でも「each subagent receives its research findings directly in its prompt rather than relying on automatic context inheritance」と具体的に記載されている。
Prompt Chaining vs Dynamic Decomposition
| Prompt Chaining | Dynamic Decomposition | |
|---|---|---|
| タスクの分解 | 開発者が事前に設計 | Claudeが実行時に判断 |
| 制御のしやすさ | 高い | 低い |
| 対応できるタスクの幅 | 狭い | 広い |
Prompt Chaining は前回解説した「直列(チェーニング)ワークフロー」に対応する。Dynamic Decomposition はエージェントがゴールを受け取って自分でサブタスクに分解する動き。
手順が決まっているならChaining、実行時まで手順が不明ならDynamic Decompositionという基本軸で判断する。
よくある誤解まとめ
| 誤解 | 実際 |
|---|---|
| エージェントはワークフローより高性能 | エージェントは柔軟だが成功率はワークフローより低い。ワークフローで実装できるならワークフローを選ぶ |
| 汎用ツールより専用ツールの方がエージェントに向いている | 抽象的な汎用ツールの方が組み合わせで幅広いタスクに対応できる。専用ツールは想定外の用途に使えない |
| サブエージェントは親のコンテキストを引き継ぐ | 引き継がない。コーディネーターが必要な情報を明示的に渡す設計が必要 |
| Claudeは行動の結果を自動的に把握できる | Claudeは行動の結果を「見る」手段がないと盲目的に動くしかない。環境観察の仕組みを設計で担保する必要がある |
| Dynamic Decompositionはいつでも使える | タスクの手順が事前に予測できる場合はPrompt Chainingの方が信頼性が高い |
| 会話履歴に状態を持てば十分 | 会話履歴はセッションと紐づいており中断で失われる。長いタスクは外部ファイルに状態を永続化する |
| クラッシュしたら最初からやり直す | マニフェストで進捗を記録しておけば、途中のステップから再開できる |
設計の判断基準
| 場面 | やりがちな選択 | 正しい選択 | 判断の根拠 |
|---|---|---|---|
| 複雑なタスクを複数エージェントに分担させたい | エージェント間の情報共有はフレームワークに任せる | コーディネーターから各サブエージェントへ必要な情報を明示的に渡す | サブエージェントは親のコンテキストを継承しない。渡さなければ知らないまま実行される |
| エージェントにファイルを編集させたい | ファイルの中身を渡さずに「このファイルに追加して」と指示する | まずファイルを読ませてから編集を指示する | Claudeは現在の状態を観察してからでなければ安全な変更ができない |
| タスクの手順が毎回変わる可能性がある | エージェントに任せてDynamic Decompositionで対応する | 手順が決まっているならPrompt Chainingで実装し、本当に不定な部分だけエージェントにする | ワークフローで対応できる範囲を最大化することで信頼性を確保できる |
| 幅広いタスクに対応できるエージェントを作りたい | タスクごとに専用ツールを作る | 汎用的で組み合わせ可能なツールを設計する | 専用ツールは想定外のタスクに使えない。抽象ツールの組み合わせで想定外のタスクにも対応できる |
| 長時間かかるエージェントタスクの状態を管理したい | 会話履歴の中に状態を持たせておく | 処理の進捗を外部ファイルに書き出して永続化する | 会話履歴はセッション終了で失われる。状態ファイルがあればクラッシュ後も途中から再開できる |
まとめ
- エージェントは「ゴールとツールを渡してClaudeに計画させる」仕組み。柔軟だが成功率はワークフローより低い
- ツールは「何をするか」ではなく「何ができるか」で定義する。抽象的なツールほど組み合わせで幅広いタスクに対応できる
- Claudeは行動の結果を「見る」手段がなければ盲目的に動く。環境観察の仕組みを設計で担保する
- ワークフローで実装できるならワークフローを選ぶ。エージェントは予測不能なタスクが本当に必要なときだけ使う
- coordinator-subagentパターンでは、サブエージェントは親のコンテキストを引き継がない。必要な情報は明示的に渡す
- 長いセッションでは状態をファイルに書き出して永続化する。会話履歴だけに状態を持たない
- マニフェストファイルで「どこまでやったか」を記録しておくとクラッシュ時に途中再開できる
- 手順が決まっているならPrompt Chaining、実行時まで不明ならDynamic Decompositionで設計する
これでシリーズB(Claude API編)のコアコンテンツが完成した。次回はQ4——シリーズB全体の振り返りクイズを予定している。
← #11:ワークフロー設計パターン——並列・直列・評価ループ・ルーティング | Q4:【振り返りクイズ】シリーズB総まとめ →