冪等性キー(Idempotency Key)

同じ操作を安全にリトライできるようにするためのAPI/CLI設計パターン。クライアントが操作ごとに一意なIDを生成し、リクエストに添えてサーバーへ送る。サーバーはそのIDと結果を紐付けて記憶しておき、同じIDでのリクエストが再度来たら実際の処理を繰り返さず、最初の結果をそのまま返す。非対話型確認プロトコルでも、AIエージェントがタイムアウト等で同じコマンドを再実行するケースへの対策として触れた。

なぜ必要か

ネットワークは本質的に信頼できない。リクエストを送って何も応答が返ってこないとき、失敗のパターンは大きく3つに分かれ、クライアント側からはどれが起きたのか区別できない。

  1. 接続確立自体に失敗した — サーバーは何も受け取っていない。
  2. 処理の途中で失敗した — サーバー側で一部だけ処理が進んでいる可能性がある。
  3. 処理は成功したが、応答がクライアントに届く前に通信が切れた — サーバー側では既に完了している。

この不確実性がある状態で単純に「もう一度リクエストを送る」と、3のケースでは決済の二重実行のような操作を二回行ってしまう。冪等性キーは、この曖昧さを解消し、クライアントが安心してリトライできる状態を作るための仕組み。

実装のポイント(Stripeの例)

  • キー生成: V4 UUIDなど、衝突を避けるのに十分なエントロピーを持つランダム文字列を使う。Idempotency-Keyヘッダーとして送る。
  • リトライループの外で生成する: キーは1回の論理的な操作につき1つ生成し、リトライのたびに再生成してはいけない。再生成すると冪等性の仕組みそのものが無効になる。
  • スコープはユーザー単位: 一意制約はidem_key単体ではなく(user_id, idem_key)にかける。異なるユーザーが偶然同じキーを生成しても衝突しないようにする。
  • 結果のキャッシュ: 最初のリクエストで得られたレスポンス(ステータスコード・ボディ)を、成功・失敗問わずそのまま保存する。同じキーでの再リクエストにはそのキャッシュを返す(500エラーだった場合もそのまま返す)。
  • 保持期間: Stripeはキーを24時間で破棄している。自動リトライが起きうる時間幅を十分にカバーしつつ、テーブルを肥大化させない現実的なデフォルト値として選ばれている。

リトライ戦略との組み合わせ

冪等性キーは「リトライしても安全」を保証するだけで、いつ・どうリトライするかは別途設計が必要。

  • 指数バックオフ: 失敗回数nに対して2^nのように待機時間を延ばしていく。
  • ジッター: 待機時間に乱数を加える。多数のクライアントが同時に同じタイミングでリトライして負荷が集中する「thundering herd問題」を避けるため。

AIエージェント文脈での位置づけ

AIエージェントはタイムアウトや通信エラーを検知すると、人間よりも機械的に同じコマンド・APIコールを再実行しがちで、冪等性のない操作では二重実行のリスクが人間の操作より高くなる。Hugging Faceのhf CLIが--exist-okフラグで「既に存在するリポジトリの作成をエラーではなくno-opにする」のも、専用のキーではなく操作自体を冪等にすることでこの問題に対処する一例(非対話型確認プロトコル参照)。

#api #cli #ai-agent

出典

作成日時: 2026-08-27 16:49 / 更新日時: 2026-08-27 16:49