古い正解で実行しない、AIワークフローの「鮮度予算」
AIエージェントが数分前の在庫や権限を根拠に更新してしまう。これを防ぎたい開発責任者向けに、項目別の「鮮度予算」と実行直前の再検証を組み込む方法を示します。
一つのTTLでは業務判断を守れない
取得時に正しかった値も、実行時まで正しいとは限りません。HTTPキャッシュでは、生成または再検証からの経過時間が鮮度寿命を超えるとstaleになり、条件付きリクエストで再検証できます。[1] この考え方をAIのツール結果にも持ち込みます。
ただし、商品名、販売価格、在庫数、操作者の権限では、変化の速さと誤ったときの損失が違います。Microsoftも、キャッシュ期間はアクセス特性に合わせ、全項目に一つの方針を当てないよう示しています。[2]
業務責任者は「古くても許せる時間」と失敗時の扱いを決め、基盤担当は取得時刻、原本の版、再取得結果を記録します。入力は、参照元、項目、次の副作用、許容経過時間、再検証手段です。
コピーして使う鮮度契約
TTLをキャッシュ容量の都合だけで決めず、実行を誤ったときの影響から逆算します。max_age_sec: 0は、保存値を使わず原本へ毎回問い合わせる意味です。
freshness_contract:
- field: product_name
source: product_master
max_age_sec: 86400
revalidate_before: none
on_failure: use_cached
- field: sale_price
source: pricing_api
max_age_sec: 60
revalidate_before: order_submit
on_failure: block
- field: stock_qty
source: inventory_api
max_age_sec: 15
revalidate_before: reserve
on_failure: block
- field: write_permission
source: authorization_service
max_age_sec: 0
revalidate_before: crm_update
on_failure: block
evidence: [fetched_at, source_version, checked_at, age_sec]
HTTPのmust-revalidateは、期限切れ後に原本で検証できるまで再利用を許さない指示です。[1] 上のon_failure: blockも同じ発想で、速さより誤実行回避を優先します。
実装は「読む」と「実行する」を分ける
- 判断用に取得する。 値と同時に
fetched_at、source_versionを保存します。受信時刻だけでなく、原本が返す版や更新時刻を優先します。 - 副作用ごとに必要項目を列挙する。 予約なら在庫、受注なら価格、更新なら権限というように、実行に必要な項目だけを束ねます。
- 直前に年齢を計算する。
age_sec = checked_at - fetched_atとし、予算超過かrevalidate_before一致なら原本へ再問い合わせします。 - 版の変化を扱う。 値または版が変われば判断を作り直します。取得不能で
blockなら成功扱いにせず、理由付きで保留キューへ送ります。 - 証拠を残す。 実行記録に、使用値、年齢、再検証時刻、原本版を保存します。
【仮想例】営業支援エージェントが9時に商品名、価格、在庫を読み、注文案を作ります。担当者の承認が9時5分なら、商品名は再利用できますが、価格と在庫は予算超過です。送信直前に価格を再取得し、在庫を予約します。さらに書込権限をその場で確認します。価格が変われば承認へ戻し、在庫不足または照会不能なら注文を止めます。完了条件は「実行に使った全項目が予算内」「必須再検証が成功」「実行記録に原本版がある」の三点です。
失敗モードと適用境界
全項目を短いTTLにすると原本への負荷と待ち時間が増えます。逆に長いTTLへそろえると、価格や権限の変更を見逃します。項目別に分け、同時失効の集中を避けるため、表示用途の再取得時刻には小さな揺らぎを加えます。ただし、副作用直前の必須再検証には揺らぎを入れません。
端末時計だけを使うと時刻ずれで年齢を誤ります。RFC 9111も鮮度計算でローカル時刻帯の影響を排除し、原本側の時刻情報を使う手順を定めています。[1] システム間ではUTC、単調増加する版番号、サーバー時刻のいずれかを基準にします。
更新されない規程PDFなど、版が固定され、古い参照が副作用を誤らせないという場合には向きません。その場合は内容ハッシュと版だけを確認すれば十分です。権限や機密データは共有キャッシュへ置かず、原本から取得します。[2]
明日から使える実装チェックリスト
- [ ] 副作用ごとに必要項目を列挙した
- [ ] 各項目に
max_age_secと根拠を付けた - [ ] 価格、在庫、権限の再検証失敗を
blockにした - [ ] 値だけでなく取得時刻と原本版を保存した
- [ ] 版が変わったら判断または承認へ戻す
- [ ] 原本停止時に古い値で実行しないテストを追加した
- [ ] 実行記録から使用時の年齢を追跡できる
最初は一つの更新APIで、取得後に時計を進める試験と原本停止試験を作ります。合格は、予算内だけが通り、期限切れと再検証失敗が必ず止まることです。
参考資料
本記事はAIを活用して作成し、公開前に自動レビューを実施しています。情報の確認日:2026-10-23。
Tác giả
ELYSAI編集部