このレッスンのロックを解除するには、まず「レッスン2:構造化プロンプトによるモデル出力の制御」を完了してください。前のレッスンに戻る

シングルプロンプトからエージェントワークフローへ

単一のプロンプトはモデルに一つのことを尋ね、一つの答えを得るだけです。エージェントワークフローは複雑な目標を複数のステップに分解します:エージェントが計画を立て、ツールを呼び出し、結果を読み取り、次のアクションを決定し、タスクが完了するまでループします。Webアプリ开发では、AI機能がデータを取得し、変換し、検証し、ユーザーに応答する ― これらすべてを人間が一つ一つ手書きすることなく実現できます。

このシフトは「聞いて答える」から「判断して行動する」への転換です。慎重に作り込んだ単一プロンプトの代わりに、思考→行動→観察→繰り返しのループを設計します。

エージェントワークフローのコア構成要素

どれほど複雑なエージェントワークフローも、すべて同じ4つのピースから構築されています。

第一に、エージェントの役割、利用可能なツール、そして停止ルールを定義するシステムプロンプト。第二に、エージェントが呼び出せるツールのリスト ― `fetch_user_data`、`send_email`、`query_database` などの関数。第三に、ステップ間で情報を引き継ぎ、エージェントが既に学んだことを忘れないようにするメモリまたは状態オブジェクト。第四に、エージェントの出力が完了を示すまで入力としてフィードバックする制御ループです。

TypeScriptでループの最小限のパターンを示します:

typescript
async function runAgent(goal: string) {
let state = { goal, steps: [], done: false };
while (!state.done) {
const decision = await llm.decide(state);
if (decision.action === "finish") {
state.done = true;
} else {
const result = await callTool(decision.action, decision.input);
state.steps.push({ decision, result });
}
}
return state.steps;
}

エージェントは`state`を確認し、次に何をすべきかを判断し、ワークフローがツールを実行し、その結果が次のラウンドのために`state`に戻されます。

🖥️ [画像挿入のヒント:エージェントループを示すフローチャート ― エージェントが判断し、ツールが実行し、結果がエージェント状態にフィードバックされ、完了までループする様子]

状態管理と停止条件

状態は、エージェントが「金魚」になるのを防ぐものです。各ターンでエージェントが確認すべき情報は:元の目標、過去のアクションとその結果の履歴、そして制約条件(「5ステップ以上かけない」「APIがエラーを返したら停止」など)です。

停止条件は開始条件と同じくらい重要です。これらがないと、エージェントは永遠にループしたり、API予算を食い潰したりする可能性があります。一般的なパターンには:エージェントが特別な`finish`アクションを発行する、ステップ上限に達する、エラーが発生してワークフローが中断する、または検証チェックで目標達成を確認する ― があります。自然的な停止シグナルがあっても、安全策としてステップ上限のようなハードリミットを必ず設定してください。

チェーン呼び出しと並列呼び出し

すべてのマルチステップタスクにループが必要なわけではありません。時にはチェーンで十分です:呼び出しAの出力が呼び出しBの入力になり、間に意思決定はありません。この方が高速で、安く、予測可能です。

次のステップが前のステップの結果に依存する場合にのみループを使用してください。ユーザーレビューを要約し、それを翻訳し、メール送信する場合 ― それはチェーンです。3つのデータベースを検索して結果をマージする場合 ― それは並列処理です。データベースを検索し、結果が空かどうかを確認し、別のソースを検索するかどうかを判断する場合 ― それはループです。

線形チェーン(A → B → C)と決定分岐付きループを並べた比較図

実践例:サポートチケットエージェント

incomingサポートチケットを処理するワークフローを想像してください。エージェントはチケットを読み、分類し、ユーザーアカウントを確認し、返信を作成するか人間にエスカレーションします。

typescript
async function handleTicket(ticketId: string) {
const ticket = await fetchTicket(ticketId);
const classification = await llm.classify(ticket.body);
if (classification.category === "billing") {
const account = await fetchAccount(ticket.userId);
const draft = await llm.draftReply(ticket, account);
await sendReply(ticket.userId, draft);
return { status: "replied", draft };
}
await escalateToHuman(ticketId, classification);
return { status: "escalated" };
}

これはチェーン(分類してから下書き作成)と分岐判断を組み合わせたものです。エージェントは自由に「考えている」わけではなく、特定の意思決定ポイントでLLMを使用するスクリプトに従っています。通常、本番運用ではこれが適切なバランスです:決定論的なフロー、賢い呼び出し。

よくある間違いとその回避方法

最初からエージェントに 너무多くの自由を与えること。既知の意思決定ポイントでLLMを呼び出す固定フローから始めましょう。動的な動作が本当に必要な場合にのみ、自由形式のループを追加してください。

状態のログ取得を忘れること。すべてのステップ、すべてのツール呼び出し、すべての結果をログに記録してください。夜中の2時に何かが壊れたとき、ログがエージェントの「思考」を確認する唯一の方法です。

再試行やフォールバックロジックがないこと。ツールは失敗します。APIはタイムアウトします。バックオフ付き再試行を実装し、「チケットを人間に送信する」のような単純なものでも、常にフォールバックパスを用意してください。

状態を無制限に成長させること。各ターンでエージェントは全履歴を確認します。20ステップ後、その履歴は巨大で高コストになります。会話が長くなったら、古いステップを要約またはトリミングしましょう。

まとめ

エージェントワークフローはループです:モデルが判断し、ツールが実行し、結果が状態を更新し、停止条件が発火するまでサイクルが繰り返されます。状態はステップ間でコンテキストを引き継ぎ、自然的な停止シグナルとハードリミットの両方が必要です。予測可能なパイプラインにはまずチェーンから始め、次のステップが本当に前の結果に依存するときにのみ、完全なエージェントループを採用してください。すべてをログに記録し、失敗時には再試行し、状態の成長に合わせてトリミングしましょう。

レッスンの練習

レッスンのチェックポイント

学んだ内容を復習し、回答へのフィードバックを受けましょう。

0/1
回答済み · 0/1