鍵を入れ替えた直後に、夜間の自動実行が静かに止まっていたことがありました。漏洩を防ぐために古い API キーを無効化したのですが、無効化と新キーの配布の間に数分の隙間ができ、ちょうどその時刻に走ったジョブが認証エラーで落ちていました。翌朝、生成されているはずの記事がないことで気づきました。
鍵を定期的に入れ替えること自体は正しい習慣です。問題は、無人で動くエージェントにとって「入れ替えの瞬間」が一番の弱点になることです。人がそばにいれば 401 を見て手で直せますが、夜間や移動中のエージェントは、認証が切れたことを誰にも伝えられないまま止まります。ここでは、止めずに鍵を回すための設計を書きます。
入れ替えを「一瞬の切替」にしない
最初に捨てるべき発想は、古い鍵を消して新しい鍵を置く、という一瞬の切替です。どれだけ手早くやっても、無効化と配布の間には必ず時間差が生まれます。その時間差にジョブが当たれば落ちます。
代わりに必要なのは、新旧2つの鍵がしばらく同時に有効である「重複期間」です。新しい鍵を先に有効化し、読み手側が新旧どちらでも通るようにしてから、書き手側を新へ切り替え、最後に古い鍵を退役させます。瞬間の切替を、緩やかな移行に置き換える発想です。
4段階で回す
私は鍵のローテーションを次の4段階に分けています。
- 発行: 新しい鍵を作るが、まだ誰にも使わせない
- 受容: すべての読み手が新旧どちらの鍵でも認証を通せる状態にする
- 切替: 書き手(エージェント本体)が使う鍵を新へ寄せる
- 退役: 古い鍵を無効化する
肝は2と3を必ず分けることです。読み手が両対応になる前に書き手を切り替えると、まさに冒頭の隙間が生まれます。逆に、受容を先に済ませておけば、切替はいつ起きても穴になりません。
# secrets.yaml — 重複期間を明示する設定
api_key:
primary: "${API_KEY_NEW}" # 切替後はこちらを使う
secondary: "${API_KEY_OLD}" # 重複期間だけ受容する
overlap_until: "2026-06-29T15:00+09:00" # この時刻に退役
overlap_until を設定に持たせておくと、退役の判断を勘ではなく時刻で下せます。私はこの窓を48時間に取っています。週末をまたいでも、長めのジョブが走り切るのに十分で、かつ古い鍵を長く生かしすぎない長さだからです。
ローテーションを自動化する
手作業の入れ替えは、忘れるか、急ぐかのどちらかに転びます。私は90日ごとに自動で回す仕組みにしました。
# rotate-secret.sh — 重複期間つきで鍵を入れ替える
set -euo pipefail
NEW=$(secret-cli generate --scope agent-api)
# 1) 受容: 読み手を新旧両対応にしてから配布
secret-cli set api_key.secondary "$(secret-cli get api_key.primary)"
secret-cli set api_key.primary "$NEW"
secret-cli publish --wait # すべての読み手へ反映を待つ
# 2) 切替: 新キーで疎通確認(失敗したら退役へ進まない)
agy auth check --key "$NEW" || { echo "❌ 新キー疎通失敗・退役中止"; exit 1; }
# 3) 退役予約: 48時間後に古い鍵を無効化
at "now + 48 hours" <<< "secret-cli revoke api_key.secondary"
echo "✅ ローテーション開始: 退役は $(TZ=Asia/Tokyo date -d '+48 hours' +%m/%d\ %H:%M)"
agy auth check で新キーの疎通を確かめてから退役を予約しているのが要点です。新キーが通らない状態で古い鍵を消すと、両方使えない最悪の状態に落ちます。確認に失敗したら退役へ進まず、その場で止めます。
無人運用で事故になる3つの落とし穴
設計どおりに組んでも、無人だからこそ踏む落とし穴があります。私が実際にハマった3つを挙げます。
第一に、キャッシュが古い鍵を握り続けることです。エッジキャッシュや実行環境が鍵を一定時間保持していると、設定上は切り替わっていても、現場では古い鍵で叩き続けます。私は重複期間をキャッシュの保持時間より必ず長く取ることで回避しています。
第二に、実行中の長いジョブです。切替の瞬間に走っているジョブが、途中から鍵を変えられず古い鍵のまま完走しようとします。重複期間があれば古い鍵でも通るので、ジョブを殺さずに済みます。これが瞬間切替を避ける最大の理由です。
第三に、API キーと再認証トークンを混同することです。両者は寿命も入れ替え方も違います。API キーは自分で計画的に回せますが、CLI の再認証トークンは期限切れで強制的に失効します。私は前者をこの設計で能動的に回し、後者は期限の手前で先んじて更新する、と扱いを分けています。同じ「鍵」として一括管理しようとすると、必ずどちらかで詰まります。
入れ替えの間隔をどう決めるか
90日という間隔は、最初から確信して選んだわけではありません。短くすれば漏洩への耐性は上がりますが、入れ替えのたびに重複期間の管理が発生し、運用が重くなります。長くすれば楽ですが、万一漏れたときに気づかず使われ続ける窓が広がります。私はこの二つの綱引きの中間として、まず90日から始めました。
実際に半年ほど回してみると、90日ごとの入れ替えは1回あたり実作業で5分ほどに収まり、年4回でも負担になりませんでした。一方で、補助的な鍵まで90日で回そうとすると、対象が増えるほど管理表が膨らみ、かえって取りこぼしが出ました。そこで重要度の高い鍵だけを90日、それ以外は半年や、漏洩の兆候があったときだけ、と間隔を分けています。
間隔を決めるときに私が見ているのは、その鍵が万一漏れたときに「気づくまでの平均時間」です。監視で数時間以内に気づける鍵なら、間隔は長めでも被害を抑えられます。逆に、気づく手立てが乏しい鍵ほど、入れ替えの間隔を詰めて窓を狭めるのが理にかなっています。間隔は一律の決まりではなく、検知の速さと運用の重さから一本ずつ引いていくものだと考えています。
個人開発の現場での線引き
個人開発で AdMob や App Store、Google Play の資格情報を扱っていると、入れ替えたいけれど止めたくない、という板挟みは日常的に起きます。私は重要度で扱いを分けています。
止まると収益に直結する経路の鍵は、必ず重複期間つきで回します。一方、失敗しても被害が小さい補助的な鍵は、多少の隙間を許容して簡素に入れ替えます。すべてを最も丁寧な設計で回すと、運用そのものが重くなって続かないからです。続けられる重さに収めることも、設計の一部だと考えています。
判断に迷ったときは、その鍵が切れた瞬間に何が止まり、誰が困るかを一度書き出してみてください。困る相手が読者や自分の収益であれば、重複期間を惜しまない価値があります。
次の一歩
まず、自分のエージェントが使っている鍵を一覧にして、それぞれに最後に入れ替えた日付を添えてみてください。日付の空欄や、何年も前のままの鍵が見つかるはずです。次に、いちばん重要な1本だけを、この4段階で一度入れ替えてみてください。重複期間を挟む手触りが分かれば、残りの鍵にも同じ設計を広げられます。