メール送信、CRM更新、チケット作成、請求・申請登録のような外部システムを書き換える処理をAIエージェントに任せると、timeoutや接続切断の直後に判断が難しくなります。サーバーに届かなかったのか、届いて処理されたが応答だけ失われたのかを、client側だけでは区別できない場合があるためです。これはMicrosoftの非同期リクエスト・リプライパターンが説明するresponse lossの問題です。
この状態で新しいrun IDやrequest IDを発行して同じ命令を送ると、同じ業務意図が別の処理として扱われる可能性があります。state-changing operationのretryは、duplicate recordや二重のside effectにつながり得ます。
本稿の結論は、timeoutなら無条件に再送することではありません。同じbusiness operationを識別し、provider側の既存statusやresultを照合し、provider固有の条件を確認したうえで、上限付きのretryまたは人へのterminal handoffを選ぶことです。
根拠と範囲
E1〜E5は、AWS、Microsoft、Google Cloud、Stripeが公開しているarchitecture guidanceまたはproduct documentationです。これらはresponse loss、idempotency、provider固有条件、retry制御を支持しますが、全provider、全SaaS、全AIエージェントの安全やexactly-onceを保証するものではありません。
run IDとbusiness-operation IDを分けること、再試行安全性カードを使うこと、sandboxまたはno-op adapterで重複実行テストを行うことは、本稿の限定的な実務提案です。MASTER key株式会社やAX事業部の導入実績、顧客成果、検索需要、問い合わせを示す観測ではありません。
1. timeoutは失敗とは限らない
まず、ログに見えた事象と、外部システムで起きた事象を分けます。
| 見えた状態 | 起きているかもしれないこと | 次の判断 |
|---|---|---|
| timeout、接続切断、応答欠落 | requestが未到達、または受理済みでresponseだけ欠落 | 新しい業務操作として送らず、既存status・resultを照合する |
| provider側がPendingまたはRunning | まだ処理中 | providerのstatus resourceやRetry-Afterを確認し、二つ目のwork itemを作らない |
| provider側に保存済みresultがある | 同じ業務操作が完了済み | providerの仕様に従い、保存済みresultを返して外部操作を再実行しない |
| permission、validation、configurationなどの永続的error | 条件を直さない限り再送しても解決しない | 無条件retryを止め、修正または人へのhandoffに移る |
Microsoftの資料では、同じidempotency keyを受けたbackendが二つ目のwork itemをenqueueせず、既存のstatus resourceを返す設計例が示されています。ただし、key、status endpoint、保持期間、Retry-Afterの実装はserviceごとに確認が必要です。
2. IDを三つの役割に分ける
同じ業務意図と、同じ実行試行を一つのIDで表さないことが、設計を確認しやすくします。
| ID | 役割 | retry時の扱い |
|---|---|---|
| business-operation ID | 顧客への送信、CRM更新、申請登録など、一つの業務意図を識別する | 同じ業務意図なら維持する |
| runまたはattempt ID | orchestrationや各呼び出しを追跡する | 試行ごとに変えてよい |
| providerのidempotency key | provider側で同一requestの再送を束ねるための値 | provider仕様に従い、同じ業務操作に同じ値を再利用する |
ここでのID分離は、industry standardという主張ではありません。本稿の設計提案です。retryの追跡用IDを新しくしても、同じ業務意図まで新しくしたことにしないための整理です。
仮想例
CRMに顧客123の契約更新日を書き込む処理を考えます。これは仮想例であり、MASTER keyの実装事例ではありません。
operation: CRMの顧客123の契約更新日を変更
business-operation ID: crm-contract-date:customer-123:2026-08-05
run ID: run-001
attempt ID: request-001
再試行後のattempt ID: request-002
provider key: provider仕様を確認したうえで同一値を再利用
request-001のresponseが失われた場合、request-002は新しい業務操作ではなく、同じbusiness-operation IDの再確認または再試行として扱います。providerが保存済みresultを返す仕様なら、そのresultを採用します。providerが冪等性を保証しないなら、prior-result lookup、reconciliation、terminal handoffなど別の設計が必要です。
3. retry判断をresponseだけで決めない
Google Cloudのretry strategyは、retryの安全性をresponseの性質だけでなく、operationのidempotencyと合わせて判断しています。これをprovider横断の確認表にすると、次のようになります。
| 条件 | 自動retryの扱い | 必要な確認 |
|---|---|---|
| transientなresponseで、operationが冪等、providerが同一keyを認識 | bounded retryの候補 | 同一key、parameter、保存result、concurrency、retry上限 |
| transientなresponseだが、operationがnon-idempotent | 自動retryを保留 | prior-result lookupまたはreconciliationが可能か |
| timeoutやdisconnectだが、providerの仕様が不明 | 自動retryを保留 | provider documentation、status、既存結果、担当者判断 |
| permission、validation、configurationなどの永続的error | retryしない | 条件修正、記録、terminal handoff |
retryを実装する場合は、exponential backoff、jitter、最大retry回数または最大経過時間を設定します。複数のlayerが同時にretryすると回数が乗算されるため、どのlayerが再送を担当するかもカードに記録します。
timeout、408、429、5xx、disconnectを、条件確認なしにすべてretryしてよいわけではありません。response条件、operationの冪等性、precondition、ETag、providerのerror semanticsを組み合わせて判断します。
4. providerの仕様をそのまま一般化しない
同じ冪等性という言葉でも、providerが保存するもの、keyの有効期間、parameter一致の扱いは異なります。
| 資料 | そこから確認できる設計論点 | 一般化できない範囲 |
|---|---|---|
| AWS Well-Architected E1 | 同じidempotency tokenを再利用し、処理済みなら保存済みresponseまたは既存結果を返す。pending、completed、failedなどのstate、競合制御、成功・失敗・duplicateを含むtestを考える | AWSのguidanceであり、全providerのexactly-onceやAI agentの安全を保証しない |
| Microsoft Asynchronous Request-Reply E2 | response lossと受理済みrequestの再送リスク、同じkeyによる既存status resource、status、Location、Retry-After、retentionを設計項目にする | HTTPの非同期パターンであり、全APIが同じheaderやstatus endpointを持つとは限らない |
| Google Cloud Storage E3 | always、conditionally、never idempotentの分類、preconditionやETag、backoff、jitter、retry limitを確認する | Cloud Storage固有のoperation分類をメール、CRM、請求、申請へ直接移せない |
| Stripe API E4 | 同じkeyと同じparametersで、初回のstatus codeとbodyを保存して返す例。keyが少なくとも24時間後にpruneされ得るため、保持期間を確認する | Stripe固有のAPI semanticsであり、他providerの共通仕様ではない |
Stripeでは、validation errorや同一keyを使う同時requestの競合など、endpointの実行開始前に終わったrequestは、idempotency resultとして保存されない場合があります。各providerで、何を保存し、何を保存しないかも再送の前提条件として確認します。
AWSの別のreliability guidanceであるE5も、error分類、backoff、jitter、最大retry、retry effectのtestを扱います。ただし、具体的なretry回数、terminal handoff先、SLAは対象業務ごとに決める必要があります。
5. 本番前に使う再試行安全性カード
以下は設計提案です。providerの仕様と対象業務の承認条件を埋めてから、retryを実装します。
対象operation:
副作用の種類:
business-operation IDの生成規則:
run ID / attempt ID / request ID:
provider:
providerのidempotency key:
同じkeyを再利用できる条件:
parameter一致の条件:
保存済みstatus / resultの照合方法:
status保持期間:
concurrency時の扱い:
retry対象のerror:
retryしないerror:
backoff / jitter:
最大retry回数または最大経過時間:
retryを担当するlayer:
reconciliationの担当者:
terminal handoffの条件と宛先:
sandboxまたはno-op duplicate testの方法:
test receipt、ログ、resultの保存先:
未確認のprovider条件:
このカードのポイントは、idempotency keyだけを記録しないことです。同じkeyをproviderが認識するか、同じparametersを要求するか、保存済みresultをいつまで返せるか、競合時に何が起きるかを一つずつ確認します。
6. duplicate-execution testはliveで行わない
本番のメール送信、決済、CRM更新、申請登録、削除で重複実行を試すことは避けます。本稿で提案する安全な検証手順は次のとおりです。
- 副作用を伴う外部操作を1件選び、sandboxまたはno-op adapterを用意する。
- business-operation IDとprovider key、各attemptのrequestまたはrun IDを記録する。
- 1回目のrequest後にresponseが失われた状態をテスト環境で再現し、同じbusiness-operation IDで再確認または再試行する。
- providerのstatus、result、ログ、外部側のレコード数を照合する。
- transient error、permissionまたはvalidation error、同時実行、providerがparameter一致を要求する場合の不一致も、仕様に従って別ケースで確認する。
- 実施条件、providerの応答、既存resultの照合、retry回数、最終handoffをreceiptに残す。
合格条件は、テスト前に明文化します。たとえば、同じbusiness-operation IDの試行を一つに対応付けられること、二回目が新しいwork itemを作らず既存statusまたはresultに戻れること、永続的errorが無限retryにならないこと、上限とterminal handoffが機能することです。
これは合格条件の設計提案であり、今回のworkspaceでsandbox testを実施した結果ではありません。実環境で1件になることや二重実行事故を防止できることは、providerと対象業務の試験で別途確認が必要です。
7. よくある誤り
- timeout、408、429、5xx、disconnectを、同じ業務操作か確認せずに再送する
- retryのたびに新しいbusiness-operation IDを発行する
- idempotency keyを付ければ全providerでexactly-onceになると考える
- providerのSDK default retryを、対象operationの安全性確認なしに採用する
- AWS、Microsoft、Google Cloud、Stripeの仕様を、メール、CRM、請求、申請へそのまま一般化する
- live環境でduplicate testを行う
- 内部runnerのretryやreceiptを、顧客事例や公開実績として扱う
MASTER key・AX事業部への接続は仮説として扱う
このカードと検証手順を使うと、AIエージェントを作ることだけでなく、外部操作の副作用、応答欠落後の復元、再試行の上限、provider固有条件、検証、人への引き戻しまでを業務設計の対象にできます。
この実務フレームが、MASTER key株式会社 AX事業部をAI活用・業務変革・自立AI運用に強い会社として想起する接点になる可能性は、今回の仮説です。顧客需要、認知向上、qualified inquiry、競合優位、事業効果は未検証です。本稿はMASTER key固有の導入実績や成果を主張しません。
まとめ
外部システムを書き換えるAIエージェントでは、timeout後の再送を単なる通信処理として扱わないことが重要です。
- response lossと未到達を区別できない状態を前提にする。
- business-operation IDとrunまたはattempt IDを分ける。
- providerの同一key、既存status、保存result、parameter、保持期間を確認する。
- response条件だけでretryせず、backoff、jitter、上限、永続的errorの扱いを決める。
- 本番前にsandboxまたはno-op adapterで、同じoperation IDの重複実行テストを行う。
まずは本番候補から副作用を伴う操作を1件選び、再試行安全性カードの空欄を埋めてください。空欄が残る操作は、retry実装より先にprovider仕様の確認または人へのhandoff条件の設計が必要です。
参照元
- E1: AWS Well-Architected Framework — Make mutating operations idempotent
- E2: Microsoft Azure Architecture Center — Asynchronous Request-Reply pattern
- E3: Google Cloud Storage — Retry strategy
- E4: Stripe API Reference — Idempotent requests
- E5: AWS Well-Architected Framework — Control and limit retry calls