ケーススタディ3: 個人用の自動化ユーティリティ
アイデア
純粋に利己的なものです。毎朝その日のカレンダーの予定と天気を取得し、1行の要約を整形して、個人のTelegramチャットに送るスクリプト。狙いは、コーヒーの前に3つのアプリを開くのをやめることでした。
仕様
私のタイムゾーンで朝7時に走るスケジュールジョブ。私のカレンダーから
今日の予定を読み、私の街の予報を取得し、こんなTelegramメッセージを
1通送る: 「今日は3件、最初は9:30。最高24C、16時以降に雨。」
どれかのソースが失敗しても、手元にあるものは送り、何が欠けているかを
書き添える。
最後の一文(クラッシュせずに優雅に劣化する)は、明示的に頼まなければならない種類の振る舞いです。AIはそれを前提にしてくれません。言わずにおくと、モデルが手を伸ばすデフォルトは「エラーでthrow」であり、朝7時のcronジョブにとってそれは、静かな朝と、なぜそうなったのかの手がかりの不在を意味します。
スタック
単一のスケジュール実行されるサーバーレス関数(CronでトリガーされるWorker)。動かし続けるマシンが不要だからです。全体は1つのファイルとスケジュール1つです。個人用ユーティリティでは、これは聞こえる以上に重要です。世話をするサーバーがあるものは何であれ、いずれあなたが支払いを忘れてしまい、プロジェクトは失敗ではなく放置で死ぬのです。
鍵となったプロンプト
Asia/Seoul の朝7時にcronでトリガーされる Cloudflare Worker を
書いて。天気APIとカレンダーAPI(両方のトークンはシークレットとして
渡す)を呼び、1行の要約を組み立て、Telegram Bot APIにPOSTする。
1つの失敗がメッセージを潰さないよう、各外部呼び出しを try/catch で
囲む。すべてのトークンは env から読む。
朝7時を待たずに文言を反復したくなったときは、こうしました。
手動トリガーを追加して: WorkerがGETリクエストで ?test=1 という
クエリパラメータ付きで叩かれたら、同じロジックを即座に実行し、
送信する代わりにメッセージのテキストをレスポンスで返す。これを
シークレットトークンの背後に置いて、私だけがトリガーできるようにする。
そのテストトリガーは、過酷なフィードバックループから私たちを救ってくれました。1日1回ではなく、必要なときに出力を見られたのです。これは盗む価値のある一般的な手です。コードがスケジュールで走るときはいつでも、時計を待つと決める前に、今オンデマンドで走らせる方法を自分用に用意しておくこと。
障害
Telegramメッセージは届きましたが、時刻が間違っていました。予定がUTCで表示され、韓国時間ではなかったのです。天気は問題ありませんでした。私たちは原因を切り分けました。
カレンダーの時刻が9時間ずれている — Asia/Seoul ではなくUTCで
表示されている。天気の時刻(「16時以降に雨」)は正しい。両方を
こう整形している: [貼り付け]。カレンダーの整形だけを直して、
なぜ天気のパスは最初から正しかったのかを教えて。
AIは、天気APIはすでにローカライズされた文字列を返していたのに対し、カレンダーAPIはUTCのタイムスタンプを返していて、私たちがそれをそのまま出力していた、と説明しました。AIはカレンダーの整形ステップにタイムゾーン変換を1つ追加しました。修正を「カレンダーのパスだけ」に絞ったことで、動いている天気のコードを書き換えるのを止められました。AIの修正が、問題なかったものを壊してしまうのはよくあるパターンです。そのプロンプトの後半 — 「なぜ天気のパスは最初から正しかったのかを教えて」 — は二重の役目を果たしました。推測ではなく実際の根本原因を教えてくれたうえ、AIにその違いを言語化させることで、修正が2つのパスを1つの壊れたものへうっかり「統一」しないようにしたのです。
ローンチ
ここでの「ローンチ」は、単にWorkerをデプロイし、cronスケジュールを設定し、APIトークンを暗号化されたシークレットとして追加することを意味しただけでした。私たちは ?test=1 エンドポイントを何度か叩いてメッセージがうまく読めることを確認し、それから放置しました。以来、毎朝走っています — そして優雅な劣化の一行は、1か月後に天気APIが障害を起こしたときその真価を証明しました。メッセージはやはり届き、ただ予報だけが欠けていたのです。