定期実行するAIタスクは、失敗せずに無音で死ぬ——3つのパターンと見つけ方
AIエージェントの定期タスクが2週間まるごと空回りしていた。ステータスは「稼働中」、最終実行時刻も更新され続けていたので、一覧をいくら見ても気づけない。作業ディレクトリの取り残し、ヘッドレスで通らない対話認証、検知しても書き戻す先が無い。どれも「失敗」として現れないタイプの壊れ方。
AI エージェントに定期タスクを組むと、壊れたときに例外が飛んでこない。ジョブは起動し、正常終了し、最終実行時刻も更新される。ただ何も起きていない。実際に4本のタスクが2週間空回りしていたのを、一覧を見ても最後まで発見できなかった。
事象
共通する見え方はこうだ。
- タスク一覧のステータスは「稼働中」
lastRunAt(最終実行時刻)は毎回きちんと更新されている- 通知フックも予定どおり鳴る
- なのに、そのタスクが生むはずの成果物が一つも増えていない
エラー通知は来ない。ログを開けば異常が書いてあることもあるが、そもそも開くきっかけが無い。
原因1:作業ディレクトリを保存しているので、リポジトリを移すと死ぬ
定期タスクは、プロンプトとは別に作成時の作業ディレクトリ(cwd)をレジストリに保存する実装が多い。リポジトリを別の場所へ移設すると、cwd が古いパスのまま取り残される。タスクは起動するが、存在しないディレクトリで動くので No such file or directory を並べて何もせず終わる。
一番たちが悪いのは lastRunAt が正常に更新されることだ。一覧を見るかぎり「毎日ちゃんと動いている」ようにしか見えない。この壊れ方は、一覧やステータスからは原理的に検知できない。
見つけ方
実行ログ(transcript)が、ある日を境に途絶えていないかを見る。一覧は嘘をつくが、実行ログは嘘をつかない。
決め手になったのは「移設後に作ったタスクだけが正常だった」ことだった。壊れているものと壊れていないものの境界が、そのまま原因の日付を指していた。古いパス側にログのディレクトリが残っていることもあるので、そこも見に行く。
直し方
cwd を更新する API は無いことが多い(作成にも更新にも引数が無い)。プロンプトを定義ファイルから回収して、削除してから同じ ID で作り直す。
このとき、作成元セッションの cwd が引き継がれる。正しい場所で作業しているセッションから作るのが肝で、これを間違えると同じ壊れ方をもう一度作ることになる。
原因2:対話でログインする道具は、ヘッドレスでは持てない
対話セッションでは動いていた連携(メール確認、ブラウザ操作など)を定期タスクに載せた瞬間に空回りする。OAuth のような対話認証が要る連携は、ヘッドレス実行で認証を通せないからだ。
ここでも失敗が無音になる。タスクは「成功」して終わり、ただ中身が空になる。気づくのは数週間後だ。
見分け方は単純で、その連携が初回にブラウザでログイン画面を出したかを思い出せばいい。出したなら定期実行では使えないと考えていい。
設計としては、定期タスク側はファイル鍵で認証できる API(.p8 のような秘密鍵ファイル)だけで完結させる。人が見て判断する部分は対話セッションに残し、定期側は実測値を取って分岐するだけにする。
原因3:検知しても、書き戻す先が無い
3つ目は実装のバグですらない。設計の穴だ。
ある監視タスクは、待っていた状態の変化を朝いちで検知し、報告して自分を無効化するところまで設計どおりに動いた。完璧に仕事をした。それでも成果はゼロだった。検知した結果を、人が次に見る場所へ書き戻す手が誰にも割り当てられていなかったからだ。待ち行列は古い状態のまま2日間放置され、その先の作業がまるごと止まった。
自己無効化するタスクは特に危ない。止まった瞬間に、誰もそのタスクを見なくなる。
一般化すると、「検知」と「検知の反映」は別の仕事だということになる。前者だけ自動化すると、成果はゼロのまま「動いている」ようには見える。
解決策
定期タスクを作るときに、この3つを条件にしている。
1つ目は、作った場所と実行される場所が同じかを確認すること。移設したら定期タスクは全部作り直す前提でいる。
2つ目は、認証がファイル鍵で完結するかを先に確かめること。ブラウザを開く連携は定期側に置かない。
3つ目は、出口をプロンプトに書くこと。「検知したら、その結果をどこそこへ書き戻す」まで含めて指示する。これが無いタスクは、成功しても成果が出ない。
補足
健全性を測るときは、ステータスではなく成果物を数える。「リマインダーが鳴ったか」ではなく「記事が増えたか」「レビューが公開されたか」で判定する。
同じ日に見つかった3件は、症状の向きが揃っていた。ステータスは正常を示すが、成果はゼロ。逆向きもあって、同期の警告がファイル更新時刻しか見ていないせいで「未同期」と誤報するものもあった。どちらも、表示されている状態と実態がつながっていない。
自動化を足すたびに監視対象が増えるので、定期的に機械で点検するスクリプトを1本持っておくのがいちばん効いた。cwd が実在するか、実行ログが途絶えていないか。この2つを見るだけで、上の原因1は自動で拾える。