即時の知らせを本命にしない
Typewriter(タイプライター。代筆アプリ)を作り始めた。Slackで僕宛てに来たメッセージを拾って、返信の下書きを横に並べてくれる道具だ。仕事は下書きまで。送るのは、僕が送信ボタンを押して確認ウィンドウを通した時だけ。この順番は、僕が最初に描いたスケッチにそのまま入っていた。
作るのは、コーディングしてくれているClaude Code(以降Code)。
メッセージの受け取り方は2つある。Slackが新しい投稿をその場で送ってくれる即時の経路(Socket Modeという仕組み)と、こちらから履歴を読みに行く経路。最初は即時の経路が主だった。
Codeは作り始める前に、この道具のリスクをいくつか挙げていた。その中にこんな一つがあった。
Code「今までSlackの通知で拾っていたものをTypewriterに頼るようになると、Typewriterが止まった時に返信が全部止まる」
AIは最初、スレッドの返信が届かないのをSlackの決まりだと受け取った
本体を作る前に、Codeは小さな試作でいくつかのことを確かめた。その1つが、即時の経路で本当に知らせが届くかだった。
Codeの報告は「半分OK」。チャンネルの投稿とDMは届く。でも、スレッドの中の返信は届かない。こちらから読みに行くとちゃんとあるのに、即時の経路には来ない。
Codeはこれを、Slackの側でそういう決まりなのだと受け取った。仕様書にもそう書き、スレッドの返信だけは数分おきに読みに行って拾う形にするという。
本当は、接続がエラーも出さずに止まっていた
Typewriterが拾う「僕宛て」には、メンションも入る。僕は自分宛てにメンションを1つ投稿してみた。これも届かなかった。
Codeは、接続が切れたりつなぎ直したりする様子まで記録に残るようにして、受け取る側のプログラムを起動し直した。僕がもう一度メンションを投稿し、Codeがスレッドに返信を打ってみると、どちらも届いた。
Code「スレッド返信も届いた。さっきの結論は誤りだったので仕様書を訂正する。本当の発見は『接続が黙って死ぬことがある』の方」
Codeが調べると、最初の接続は、つないでから約2分で止まっていた。プログラムは動いたままで、エラーも出ていない。知らせだけが来なくなっていた。スレッドの返信が届かなかったのも、これが原因で、Slackの決まりではなかった。
Typewriterは動いて見えるのに、知らせだけが来ない。これでは止まったことにも気づけない。
即時の知らせは速報にして、本命は5分おきの照合にした
Codeが出した設計はこうだった。
Code「即時の経路は速報、5分おきの照合が正」
照合というのは、僕のアカウントで見える全部のチャンネルを、前回読んだところから読み直して、即時の経路が取りこぼした分を拾うこと。「正」は、本命として信じる方という意味だ。即時の方は速いから使うけど、信じるのは照合の方にする。
それとは別に、即時の経路が生きているかを30秒おきに確かめて、止まっていればつなぎ直す。さらに、最初に挙げていた「Typewriterが止まった時に返信が全部止まる」への手当てとして、Typewriterが動いているかを画面でも見られるようにした。一番下には、最後に知らせを受け取った時刻と、最後に照合した時刻を出す。
次の日のDMは、即時の経路ではなく照合が拾っていた
この時のTypewriterは、まだ僕のMacの上で動かしていた。
次の日、仕事のDMが1件、Typewriterに取り込まれていた。返信の下書きもできていた。
その少し前の昼、アプリの画面が開かなくなっていると僕がCodeに伝え、Codeが取り込みのプログラムを起動し直していた。Macがスリープから戻った直後で、しばらくネットにつながらず、取り込みのプログラムはSlackへのつなぎ直しを繰り返していたという。
Codeは、このDMを即時の経路で拾ったと報告した。けれどその日の作業の終わりに、HO(ハンドオーバー。セッションの終わりに残す引き継ぎメモ)を書く別のAIが、記録に残った受信の時刻と取り込みの時刻を照らして、食い違いに気づいた。DMが届いたのはMacがスリープしている間で、取り込まれたのはCodeが起動し直した直後だった。Codeはこう訂正した。
Code「5分おきの照合が拾っていた。Macがスリープ中に届き、起動し直した後の照合で回収した。設計どおりだが、報告が不正確だった」
即時の経路が受け取れない理由は、試作で見た「黙って止まる」だけではなかった。黙って止まらなくても、Macが寝ている間は受け取れない。黙って止まった時も、寝ていて受け取れなかった時も、メッセージを拾えたのは読みに行く方だった。