Step Functionsは最も過小評価されているエージェントオーケストレーター
多くのエージェントワークフローは制御フローの判断にモデルを必要としない。Step Functionsは決定論的なオーケストレーション、リトライ、人間の承認ステートを提供する。

世間でエージェントと呼ばれているものの多くは、途中に1つか2つのモデル呼び出しを挟んだ固定シーケンスに過ぎない。制御フローは事前にわかっているのに、チームはそれをモデルに委ねてしまい、その後何週間もかけて非決定論的なループをまともに動かそうとする。作業の形がわかっているなら、オーケストレーターは決定論的であるべきで、AWS Step Functionsはその仕事において手作りのエージェントループよりも適している。リトライ、タイムアウト、エラーハンドリング、並列処理、人間による承認をすでに解決済みであり、それらはまさにエージェントフレームワークが再実装を求めてくるものだ。
内面化する価値のある捉え直し方はこうだ。モデルには判断をさせ、配管はさせない。抽出、分類、ドラフト作成のように本当に判断を要するステップにモデルを使い、何を、どの順番で実行するか、あるステップが失敗したらどうなるかは、ステートマシンに決めさせる。ステップ3がステップ2の後に続くことを知るのにLLMは必要ない。
決定論的なオーケストレーションは制約ではなく機能である
自前で作ったエージェントループは、制御フローをモデルに任せる。どのツールを呼ぶか決め、結果を読み、次のツールを決め、終わったと思うまでそれを繰り返す。これは、作成時点で経路が本当にわからない場合には正しい設計だ。しかし経路がホワイトボードに描けるようなワークフローである場合は誤った設計になる。実行のたびに異なる経路をたどりうるし、リトライはその場しのぎになり、途中での失敗は再構築しなければならない状態を残してしまうからだ。
Step Functionsはこれを逆転させる。ステートと遷移を宣言する。判断を要する各ステートはBedrockを(直接、またはLambda経由で)呼び出し、判断を要さない各ステートは単なるロジックになる。実行は再現可能で、すべての遷移がログに記録され、実行履歴は組み込みの監査証跡になる。形の決まったワークフローには、決定論こそがまさに求めるものだ。
自分で書く必要のないリトライとエラーハンドリング
エージェントの信頼性作業のうち地味な部分の大半は、リトライポリシーだ。モデル呼び出しがスロットリングされ、ツールがタイムアウトし、下流のAPIが一時的な500エラーを返す。手作りのループでは、バックオフ、ジッター、エラーごとのハンドリングを手で書くことになり、たいてい微妙に間違える。
Step Functionsはこれを宣言的にする。各ステートは自分自身のリトライとキャッチの振る舞いを持つ。
"InvokeModel": {
"Type": "Task",
"Resource": "arn:aws:states:::bedrock:invokeModel",
"Retry": [{
"ErrorEquals": ["Bedrock.ThrottlingException"],
"IntervalSeconds": 2,
"BackoffRate": 2.0,
"MaxAttempts": 5
}],
"Catch": [{
"ErrorEquals": ["States.ALL"],
"Next": "HandleFailure"
}]
}
スロットリングには指数バックオフがかかり、それ以外はすべて自分が制御する失敗ステートへとルーティングされる。リトライコードもなく、失われた例外もなく、その振る舞いはループの中に埋もれるのではなく定義の中に可視化されている。
人間参加型はファーストクラスのステートである
手作りのエージェントが最も苦しむのは、人間のために一時停止する場面だ。お金を使ったり、メールを送ったり、本番環境を変更したりできるエージェントは、停止して承認を待つべきであり、それを長時間稼働するプロセスの中で行うということは、人が数時間から数日かけて応答するあいだ、どこかにステートを保持し続けることを意味する。
Step Functionsにはこれがコールバックパターンとして組み込まれている。.waitForTaskTokenで開始されたタスクは実行を一時停止し、トークンを発行し、誰かがそのトークンとともにSendTaskSuccessまたはSendTaskFailureを呼ぶまで何もしない。ワークフローは、プロセスを稼働させ続けることなく、承認にかかるだけの時間だけ一時停止し続けられ、中断した場所から正確に再開できる。キューやステートストア、再開機構を自分で構築することなく、永続的で監査可能な人間ゲートが手に入る。
それでも本物のエージェントループが必要な場合
これはエージェントループそのものへの反論ではない。エージェントループが働きに見合う場所で使うべきだという主張だ。経路が本当にオープンエンドである場合、つまりモデルが実行時に多数のツールのうちどれをどの順番で使うかを判断しなければならず、固定されたグラフでは捉えきれない場合には、モデル駆動のループに手を伸ばすべきだ。オープンエンドな調査、自由形式のデバッグ、そして次のステップが前のステップの結果に列挙できない形で依存するタスクこそが、エージェントループの本来の居場所だ。
罠は、分岐が1つしかない5ステップのパイプラインにそのパターンを使うことだ。フローチャートが描けるなら、フローチャートをコード化すればいい。非決定論的なループは、本当に非決定論的な作業のために取っておくこと。
結論
本番のエージェント作業のかなりの部分は、エージェントの衣装をまとった決定論的なオーケストレーションだ。そうした作業には、Step Functionsがリトライ、エラールーティング、並列処理、そして本来なら自前で構築し保守しなければならない永続的な人間承認ステートを提供してくれ、加えて実行履歴が監査ログを兼ねる。判断を要する呼び出しはモデルにさせ、制御フローはステートマシンに所有させる。最も信頼できるエージェントは、しばしばモデルが最も判断をしないエージェントだ。
次に読む
- Bedrock Agents vs Rolling Your Own Loop、オーケストレーションにおける構築か管理サービス利用かのもう一方の判断について。
- Agent Memory Is a Database Problem, Not a Prompt Problem、ワークフローがステップ間で持ち運ぶステートを実際にどこに置くべきかについて。
高リスク操作への承認ゲートを含む、同じパターンのインフラおよびプラットフォーム側の読み物は、クラウドのフィールドノートがercan.cloudにあり、ハブはercanermis.comにある。
Ercan の他のサイト
同じ著者、別の領域のサイトが2つ。