夜中の3時にスマホが鳴って、ベッドの上でエージェントに聞く。「今の地震、津波くる?」。このとき返ってきてほしくない答えがひとつある。取りこぼしたくせに「津波情報はありません」だ。
kurashi-skillの3つ目のスキル、bosai-alertはそのために作った。気象庁はユーザー登録なしで機械可読な気象・防災データを公開している。そのJSONを読む、地震情報・気象警報・津波情報の担当だ。今日はこれを題材に、「危ない情報を扱う道具」を作るときに僕が決めたことを書く。エージェントでなくても、通知バッチや監視系を書く人にはそのまま効く話だと思う。
起: なぜ天気予報と分けたか
kurashi-skillには天気予報のjma-weatherもある。最初は1つのスキルで「気象庁のなんでも屋」にする手もあった。やめた理由は、失敗のしかたが違うからだ。
天気予報が取れなくても、明日傘を持つかどうか迷うだけだ。でも津波情報が「取れなかった」のに「ない」と返ったら、人が逃げない判断をしてしまう。失敗したときの被害が違うものは、同じ道具に入れてはいけない。平時の道具と有事の道具は分ける。これが最初の設計判断だった。
承: 作ったものと、2つの小さな約束
中身は3系統のJSONを読むだけだ。APIキーもログインもいらない。
# 地震情報の一覧
curl -sm 30 https://www.jma.go.jp/bosai/quake/data/list.json
# 気象警報・注意報 (130000 = 東京)
curl -sm 30 https://www.jma.go.jp/bosai/warning/data/warning/130000.json
# 発表中の津波情報
curl -sm 30 https://www.jma.go.jp/bosai/tsunami/data/list.json
ここで約束を2つ決めた。
ひとつ目。詳細データのURLは自分で組み立てない。地震一覧の各イベントは json というフィールドを持っていて、「私の詳細はこのファイルだよ」という乗車券を握っている。詳細を読むときは、その値をそのままURLに使う。
curl -sm 30 https://www.jma.go.jp/bosai/quake/data/<一覧のjsonフィールドの値>
タイムスタンプとイベントIDには規則があるように見えるから、頭のいい人ほど規則で合成したくなる。でも形式が変わった瞬間に404を踏む。APIが手渡してくれたものをそのまま使う。賢さを我慢するほうが正解だった。
ふたつ目。変な値はそのまま伝える。最大震度の maxi は "3" のこともあれば "5-" や "6+" のこともある。弱・強を文字列で持ってくるのだ。これを数値だと思ってパースすると死ぬし、「5弱」を「5.0」みたいに整形して伝えると、公式発表と違う情報を流したことになる。加工しない。変な形のまま、変な形だと言って渡す。
転: 「ない」と「取れない」は反対の意味を持つ
ここが今日の本題だ。
津波情報のlist.jsonは、何も発表されていないとき、空配列 [] を返す。これは正常なデータだ。「現在発表中の津波情報はない」という、立派な観測結果である。
ところがエージェント(と、人間が書くスクリプト)はここで2つの失敗をする。
失敗その1。空配列を「取得失敗」と取り違えてリトライを始める。何度取っても空なので、しまいには「データを取得できませんでしたが、たぶん大丈夫です」と言い始める。平穏な夜に、無用の不安をばらまく。
失敗その2。逆に、タイムアウトやHTTPエラーで本当に取れなかったときに「情報なし」と報告してしまう。こちらが最悪だ。台風の夜に「津波情報はありません」と言われて、それが「確認したらなかった」のか「確認できなかった」のかで、避難の判断は真逆になる。
だからbosai-alertのSKILL.mdにはこう書いた。空配列はエラーではない。そして失敗を「情報なし」とは絶対に言うな。 取得に失敗したら失敗したと明言して、気象庁の防災情報ページ(https://www.jma.go.jp/bosai/map.html)を直接見るよう案内する。ステータスコードと中身を分けて扱えば、この区別は機械的にできる。200で空配列なら「ない」。それ以外で中身が読めなければ「わからない」。
夜中の3時の質問に答えられるのは、この区別ができている道具だけだ。
結: 3つの持ち帰り
防災ツールじゃなくても使える教訓にすると、こうなる。
- 「空」と「失敗」を別の言葉で報告する。 空はデータ。失敗はデータではない。監視系・通知系すべてに効く。
- APIが渡してくれた参照をそのまま使う。 URLやIDを規則で推測しない。推測は今日は動くが、静かに壊れる日が来る。
- 便利な道具ほど、免責を動作の中に組み込む。 bosai-alertは答えを返すたびに「最終確認は公式発表で」と付ける。道具が賢くなるほど、人はそれだけで判断したくなるから。
kurashi-skillは公開開発中で、リポジトリはここ → https://github.com/tahodev/kurashi-skill
何も起きていない夜に [] が返る。その空っぽを正しく読めることこそが、防災スキルの仕事だと思っている。空っぽは「何もない」の証明だが、それは空っぽを空っぽと認識できたときだけだ。