Tech カテゴリのイメージ

AIエージェントの補償処理とは?途中まで進んだ外部操作を安全に戻す

AIエージェントが一つの依頼で複数の外部サービスを操作すると、途中だけ成功することがある。予定表には会議を作れたが、参加者への案内メールは送れなかった。商品は確保できたが、決済は失敗した。この状態を単なるエラーとして終えると、外部サービスに中途半端な変更が残る。

補償処理とは、すでに完了した操作に対して、業務上の意味を打ち消す別の操作を行い、システムを許容できる状態へ戻す仕組みである。データベースのrollbackと同じではない。外部へ確定した操作は過去から消せないため、会議を削除する、在庫を解放する、返金するなど、新しい操作として埋め合わせる。

一つのトランザクションにできない操作がある

単一データベースの中なら、複数の更新を一つのトランザクションにまとめ、途中で失敗したときに全体を取り消せる。しかし、予定表、メール、決済、顧客管理のような独立したサービスをまたぐと、一つのデータベーストランザクションでは包めない。

例えば、出張手配エージェントが次を順に行うとする。

  1. 航空券を予約する
  2. ホテルを予約する
  3. 予定表へ日程を登録する
  4. 関係者へ確定メールを送る

ホテル予約で失敗しても、航空券予約はすでに相手サービスで確定しているかもしれない。全体を最初からなかったことにはできないため、航空券の取消という補償操作が必要になる。

rollbackではなく業務上の打ち消しである

補償は、必ずしも元の状態を完全に復元しない。航空券を取り消しても手数料が発生し、決済を返金しても売上と返金の二つの履歴が残る。送信済みメールは受信箱から消せず、訂正メールを送るしかない。

そのため、補償処理は技術的な逆操作ではなく、業務ルールで定義する。

  • 仮予約を取り消す
  • 確保した在庫を解放する
  • 請求を返金する
  • 作成した予定を取消済みにする
  • 誤った通知に訂正通知を追加する

MicrosoftのCompensating Transactionパターンも、開始時点のデータへ単純に戻すのではなく、途中で入った他の変更を考慮して、完了済み作業を業務上補償すると説明している。

各道具に補償可能性を持たせる

エージェントへ外部操作を渡すときは、実行関数だけでなく、失敗後に何ができるかを整理する。

  • 自動で元へ戻せる
  • 条件付きで戻せる
  • 代替処理で影響を抑えられる
  • 戻せず、人の判断が必要

予定作成には予定削除を対応させられるが、参加者が予定を別用途へ編集していたら、無条件削除は危険である。請求の返金には期限や金額の制約がある。公開済み投稿や送信済みメールは完全には戻せない。

道具の定義には、補償操作、必要な識別子、期限、費用、承認の要否、元に戻せない条件を記録する。モデルの一般知識から逆操作を推測させない。

元に戻せない操作を最後へ寄せる

Sagaパターンでは、複数サービスの一連の処理を局所的なトランザクションへ分け、失敗時に補償を実行する。ここで重要なのが、戻れる段階と戻れない段階の境界である。

MicrosoftのSaga資料は、補償可能な処理の後にpivot transactionという後戻りできない境界を置き、その後を再試行可能な処理で完了へ進める考え方を示している。

AIエージェントでも、検証、見積もり、仮予約、承認を先に済ませ、取り消しにくい送信、公開、確定決済を最後へ寄せる。途中で失敗しやすい操作を、取り消し不能な操作の後へ置かない。

ただし、最後に置けば安全になるわけではない。実行前に対象と引数を再検証し、必要な人の承認を確定させる。

前へ進む回復と後ろへ戻る回復を選ぶ

失敗したら常に全部取り消すとは限らない。一時的な障害なら、失敗した段階を再試行して前へ進む方がよい。業務条件を満たせない失敗なら、完了済み操作を補償して戻る。

例えば、予定表APIが一時的に混雑しているだけなら、ホテル予約まで取り消さず、予定登録を後で再試行できる。予算超過でホテルを予約できないなら、代替ホテルを提案する方法もある。利用者の目的に照らして、継続、代替、補償のどれを選ぶかを決める。

この判断をモデルへ全面的に任せない。金額、期限、操作種別、承認状態などの規則をポリシーとして持ち、曖昧な場合は人へ確認する。

完了した段階と補償情報を保存する

補償には、何が実際に完了したかという確かな記録が必要である。会話履歴に「予約しました」と書かれているだけでは、外部サービス側の状態を証明できない。

作業全体にworkflow IDを付け、各段階について次を保存する。

  • 操作名と対象
  • 確定した引数
  • 外部サービスの操作ID
  • 開始時刻と完了時刻
  • 成功、失敗、結果不明の状態
  • 補償に必要な値
  • 承認者と承認内容
  • 再試行回数

実行前に予定していた操作と、実際に完了した操作を分ける。結果不明の段階は、補償する前に外部サービスへ照会する。実は成功していた操作を再実行したり、存在しない操作を取り消したりしないためである。

補償処理自体も冪等にする

補償の途中でもタイムアウトや再配信は起きる。同じ返金を二回実行したり、同じ在庫を二度解放したりしないよう、補償操作にも冪等性キーを付ける。

元の操作IDと補償種別から安定したキーを作り、再試行で使い回す。補償の状態もpending、running、succeeded、failed、unknownに分けて保存する。

補償が失敗したときに最初から全段階を繰り返すのではなく、保存済み状態から未完了の補償だけを再開する。Microsoftの資料も、補償トランザクションは失敗し得るため進捗を記録し、各段階を冪等な命令として設計するよう求めている。

必ず逆順とは限らない

一般には、後で実行した操作から逆順に補償すると依存関係を保ちやすい。しかし、業務上の優先度によって順番は変わる。

決済と在庫が残っている場合、返金を先にするのか、在庫を先に解放するのかは事業ルールで決める。互いに独立した補償なら並列化できる。機密情報の公開停止のように影響が大きい操作は、元の順序に関係なく最優先にする。

補償順序をモデルに都度考えさせるのではなく、依存関係と優先順位をワークフロー定義に持たせる。

同時変更を上書きしない

元の操作後に、別の利用者や処理が同じ資源を変更している場合がある。予定作成後に参加者が説明を編集したのに、補償が作成前の状態を丸ごと上書きすると、その編集まで消してしまう。

更新時のバージョン、ETag、更新時刻などを保存し、補償前に現在状態を読み直す。想定した版から変わっていたら自動補償を止め、差分を示して人へ判断を求める。

短時間の業務なら処理中フラグや期限付きロックを使える場合もある。ただし、長時間のエージェント処理で広いロックを保持すると、他の利用者を止めてしまう。競合を前提に、対象を限定した補償を設計する。

補償できない操作には事前の境界を置く

外部公開、法的な確定、物理配送、送信済み通知など、元に戻せない操作もある。このような道具に架空のundoを用意してはいけない。

補償不能な操作では、実行前に次を行う。

  • 必要な前段階がすべて完了したか確認する
  • 対象と引数を固定する
  • 権限と承認を再確認する
  • 重複防止の操作IDを付ける
  • 失敗時の訂正や人への引き継ぎを決める

取り消せない操作を複数まとめて自動実行せず、一つずつ確定結果を確認する。利用者へは、実行後に戻せないことを承認前に示す。

補償は新たな副作用として承認する

補償は安全な後片付けとは限らない。予約取消には手数料がかかり、返金は会計処理を発生させ、訂正メールは新たな情報を外部へ送る。

元の操作を承認したからといって、任意の補償まで包括的に許可されたとは限らない。一定金額以下の返金や仮予約の解放は事前ルールで自動化し、それを超える操作は、影響と確定引数を示して承認を求める。

補償の承認待ちでも状態を失わないようにする。承認が期限切れになった場合は自動実行せず、担当者へ通知する。

オーケストレーションで全体を追跡する

Sagaには、各サービスがイベントを見て次へ進むchoreographyと、中央の制御役が段階を管理するorchestrationがある。

単純な流れではイベント連携でもよいが、段階が増えると、どこまで完了し、どの補償が必要かを追いにくくなる。複数の道具を選び直しながら動くAIエージェントでは、アプリケーション側のオーケストレーターが状態、認可、承認、再試行、補償を管理する方が境界を明確にしやすい。

モデルは次の操作を提案できるが、完了記録と補償の実行順序を保持する唯一の台帳にはしない。モデルの再実行や会話の要約で状態が変わっても、ワークフロー記録は変わらないようにする。

最終状態を利用者へ具体的に示す

「処理に失敗しました」だけでは、何が残っているか分からない。最終結果には、成功した操作、補償済みの操作、未解決の操作、利用者が行う必要のある作業を分けて表示する。

例えば、航空券は取消済み、ホテルは未予約、予定表の仮予定は削除済み、取消手数料は確認待ち、と示す。補償が完了しても、元の依頼が成功したわけではないため、completedとcompensatedを別の状態にする。

監査ログでは、元の操作と補償操作を同じworkflow IDで結び付ける。誰が何を承認し、どの外部IDへ操作し、最終的にどの状態へ到達したかを追跡できるようにする。

失敗の組み合わせを試験する

正常に全段階が完了する試験だけでは、補償処理の不具合は見つからない。各段階の直前と直後で失敗を起こし、期待する補償が選ばれるか確認する。

  • 最初の操作が失敗し、補償が不要な場合
  • 二段階目で失敗し、一段階目だけを補償する場合
  • 外部操作は成功したが応答が失われた場合
  • 補償中にタイムアウトし、同じキーで再開する場合
  • 補償前に別の利用者が対象を変更した場合
  • 補償不能な操作の直前で停止する場合
  • 承認が拒否または期限切れになる場合
  • 自動補償が失敗し、人へ引き継ぐ場合

各試験で、外部サービスの実状態、内部のワークフロー状態、利用者への表示、監査ログが一致していることを見る。

まとめ

AIエージェントの補償処理は、途中まで完了した外部操作を、業務上の別の操作で打ち消して許容できる状態へ戻す仕組みである。単純なrollbackではなく、取消、解放、返金、訂正といった領域ごとのルールになる。

各段階の完了と外部IDを保存し、継続するか補償するかをポリシーで判断する。補償自体も冪等にし、競合と失敗から再開できるようにする。戻せない操作は最後へ寄せ、事前検証と承認を強くする。モデルは操作を提案しても、進捗と回復を管理する責任はアプリケーション側に置く。

参考資料

生成AI・機械学習講座の一覧へ