Skip to main content
エージェントが複数のツールを使うとき、モデルを呼び出す前に使用量を確認し、各ステップの応答を記録したい場合があります。Laravel AI SDKのミドルウェアは、エージェント全体を一度だけ包むものではなく、生成の各ステップで実行されます。このページではLaravel 13の公式ドキュメントと laravel/ai の v1.3.0 の実装をもとに、AI SDKの基本操作より一歩踏み込んで実行順と停止条件を整理します。

ミドルウェアが実行される単位

エージェントがモデルの応答を受け取り、ツールを実行して再びモデルを呼ぶ場合は、次のモデル呼び出しが別のステップになります。各ステップの直前に、HasMiddleware::middleware() で返したミドルウェアを宣言順に通します。 ミドルウェアの handle(PendingStep $step, Closure $next) に渡される PendingStep には、実行済みステップの配列 steps、その累積使用量 usage、現在のゼロ始まりのステップ番号 number が含まれます。初回の usage はまだ今回のモデル呼び出しの使用量を含みません。 $next($step) の結果に付けた then() は、モデルが応答した後、ツール呼び出しが実行される前に動きます。ツール実行後にだけ呼ばれるフックではありません。また、この時点の usage は以前に完了したステップの合計であり、進行中のリクエストのトークン数を予測しません。

ステップごとの処理を登録する

ステップ番号と、それまでに使った入力トークン数だけをログに残す例です。プロンプト本文やモデルの出力をログへ無条件に保存しないようにします。
エージェントで HasMiddleware を実装し、middleware() からインスタンスを返します。
middleware() の並び順では、Stop を先に置きます。上限を超えて次のステップを開始しない場合、後続の LogAgentSteps はそのステップで実行されません。順序を逆にすると、ログの「開始」だけが記録され、「モデルが応答した」は記録されないことがあります。$next($step) の結果を handle() から返し、then() のコールバックではレスポンスを返す必要はありません。

Stopは次のモデル呼び出しを止める

Stop::when(...) は条件がtrueになったとき、Stop::unless(...) は条件がfalseになったときに、そのステップの前で処理を終了します。上の例は完了済みステップの累積入力トークンが50,000以上になったら次の呼び出しを行いません。1回のモデル呼び出しが閾値を超える前に強制停止するハードリミットではありません。
Stop は進行中のプロバイダーへのリクエストを中断しません。使用量の上限を厳密に保証する必要があるなら、次のステップの判定だけに依存せず、モデルやプロバイダー側の制限も検討してください。
独自条件で停止したいミドルウェアは Laravel\Ai\Gateway\StepResult::stop() を返すこともできます。handle() からは $next($step) の結果、StepResponse、または StepResult::stop() を返します。無関係な型を返すと例外になります。

実行順を検証する

モデル応答とツール実行を混同しないよう、少なくとも次のケースを確認します。
  • 1ステップだけの生成では、開始ログとモデル応答ログが1回ずつ出る。
  • ツールに続く追加ステップでは、番号が0から増え、後続ステップの usage に前のステップの使用量が含まれる。
  • 最初から停止条件が成立する場合、モデル呼び出しと LogAgentSteps のログが発生しない。
  • 途中で条件に達する場合、それまでのステップは残り、次のステップのモデル呼び出しは発生しない。
通常の経路と停止する経路を分け、各ステップの実行回数を確認します。then() に副作用が必要な場合も、モデル応答を得る前に失敗・停止した経路では呼ばれない前提で設計してください。

参照した一次情報

最終更新日 2026年10月21日