10分で読めます

AIにメール送信を任せる5段階|承認ゲート・自動停止・AIレビューで見つけた二重送信の穴

千書いた人:千葉 哲也(パンダオフィス代表)

この記事の要点

会社を全自動(レベル5)で回せるかを自社で試している。その一部として、自社の専門家を業界で知ってもらうための売り込みメールを、AIが書いて送る仕組みを作った。方針は「全自動・人は確認しない」と決めたが、実装はまず全件を人が承認する段階1から始めた。次に作ったのは送る仕組みではなく止める仕組みで、苦情率がしきい値を超えるとプログラムが全送信を止め、再開は人のボタンだけにした。そのうえで、AIに「売り物として評価してほしい」と頼んでコードを3周レビューさせた。テスト400件超がすべて通る状態で、タイムアウト時の二重送信、テスト送信が苦情率を薄めて自動停止を効きにくくする穴、その横展開漏れが見つかった。直したあとで、確率0.9以上を自動送信する段階2と、低リスクな返信から自動承認を広げる段階3を実装した。本番の送信はまだ0件で、段階2の条件には届いていない。任せる範囲を広げる前に、止め方と戻し方をコードで決めておく。これがこの実験で得た手順だ。

メール送信をAIに任せる段階:段階1(全件承認)→段階2(確率0.9以上を自動送信)→段階3(返信を自動承認)。苦情が出たら段階1へ戻る

「送信は全自動、人は確認しない」と決めた。それなのに、最初に作ったのは人が全件を承認する仕組みだった。

この記事は、自社の売り込みメールをAIに自動送信させる仕組みを、実際にマージしたPRの順に書いた実装記録である。どこを任せ、どこをAIにしないか、どうやって止めるか、そしてAIにAIのコードをレビューさせて何が出てきたかを、エンジニア向けに具体的に書く。


背景:会社を全自動で回す実験

Panda Office では、自社を「人は判断と決済だけ、他は全部AI」で回せるかを試している。自動運転の段階になぞらえて、最終目標を**レベル5(全自動)**と呼んでいる。全自動の会社が本当に回るのかは分からない。だから実験として行い、その過程を公開する。この記事もその一部だ。

今回の題材は、社内で「露出レーン」と呼んでいる仕組みである。自社の専門家を業界で知ってもらうために、講演の主催者や編集部へ売り込みメールを送る。 AIの役割は次のとおり。

  • 送り先ごとに提案文を書く
  • 送ってよいかを確率で判定する
  • 返信を仕分け、日程を調整する
  • 反応を点数にして、うまくいかない提案の型を入れ替える

外部へメールを送る以上、失敗はそのまま相手への迷惑になる。社内のチャットに誤字を送るのとは重さが違う。

ずんべぇ
ずんべぇ
全自動って決めたなら、最初から自動で送ればよかったのでは?
うぉんば
うぉんば
決めたのは行き先だよ。そこまでの道は段階に分けた。いきなり全自動にすると、最初の事故が起きた時点で全部止めるしかなくなるから。

段階1:全件を人が承認し、AIの判定は記録だけ

最初のPR(#108)では、AIの判定を記録するだけにした。

判定には、TypeSafe AI の判定専用モデル Jev を使った。「このメールを送ってよいか」を確率で返し、理由を「担当外」「事実未確認」「誇張」「利害未開示」「特に問題なし」から選ぶ。段階1では確率がいくつでも、必ず承認ゲートを通す。監視画面の承認一覧には確率・理由・下書き本文を並べ、人が見て送るかどうかを決める。

狙いは、AIの判定と人の判断を同じ台帳に並べることだ。人が承認したもの・却下したものと、AIの確率がどれだけ一致するか。この実績が、後で任せる範囲を広げるときの根拠になる。

同時に、AIにやらせない部分もはっきり分けた(#110)。

処理担当理由
送り先探し人が書いた候補一覧を取り込むだけ実在しない主催者や間違った宛先をAIが作ると、そのまま誤送信になる
提案文生成AI文章を書くのはAIが得意
送信の可否(お断り表示・同じ編集部へは月1件・重複)プログラムだけ規則で決まることを確率で判定させない
送ってよいかの判定判定AI誇張や事実未確認は規則で書けない

「営業お断り」の表示がある相手を除くのは、法令に関わる。ここを確率で判定させる理由はない。規則で書けることはコードで書き、書けないことだけをAIに渡す。


送る前に作ったのは「止める」仕組み

自動送信より先に作ったのが、見張り役(#114)である。

  • 15分おきに、直近7日の送信のうち苦情・配信停止の率を計算する
  • しきい値(仮に10%)を超えたら、プログラムだけで露出レーンの送信を全部止める
  • 判定は送信が5件以上たまってから始める。件数が少ないうちに1件の苦情で止まるのを防ぐため
  • 再開は人だけができる。 見張り役は止めることしかできず、監視画面の「再開する」ボタンでしか動き出さない

送信を止めるチェックは2か所:下書きを作る時点と、実際に送る直前

停止のチェックは2か所に入れた。ひとつは下書きを作る時点で、そもそも新しい下書きを作らせない。もうひとつは実際に送る直前だ。承認済みで送信を待っているメールも、ここで止まる。 承認そのものは残しておき、再開後にそのまま送る。

止める側をAIの判断にしなかったのは、止める理由をAIが言い負かせないようにするためだ。苦情率は数えれば出る。数えれば出るものは、コードで決める。


AIに「売り物として評価して」と頼んだ

ここまでで機能はそろい、テストも通っていた。そこで、別のAIセッションにコードをレビューさせた。

頼み方を変えたのが、この記事で一番伝えたいことだ。「レビューして」ではなく、「売り物として評価してほしい」と頼んだ。

「レビューして」と頼むと、AIは書き方の改善点や命名の揺れをきれいに並べてくる。間違いではないが、致命的な穴とは限らない。「売り物として」と言うと、評価の物差しが「お客さんの現場で事故にならないか」に変わる。3周回して、毎回なにかが出てきた。

AIレビュー3周で見つかった穴:1周目HIGH 2件、2周目HIGH 1件・MEDIUM 1件、3周目MEDIUM 1件

1周目:二重送信の穴(HIGH 2件)

1つ目は、同じ送り先への下書きの重複である(#119)。「もう連絡した相手」として数えていたのは送信済みのものだけで、下書き中・承認待ちを数えていなかった。1回のバッチの中で、同じ相手への下書きが積み上がる。

2つ目のほうが怖い。メールサーバーへの送信がタイムアウトしたとき、二重に送りうる。 タイムアウトは「届かなかった」とは限らない。届いたのに応答だけ遅れた場合、再試行すれば同じメールが2通届く。

直し方は、送信の直前に「これから送る」という印を台帳へ1文で書き込むことにした。印を書けなかった(すでに誰かが書いた)なら送らない。失敗したときは理由で分ける。

  • タイムアウトなら印を残す(届いた可能性があるので再送しない)
  • それ以外の失敗なら印を外す(確実に届いていないので再試行してよい)

2周目:テスト送信が苦情率を薄めていた(HIGH 1件・MEDIUM 1件)

2周目では、タイムアウトで止まった案件が放置される問題が出た(#120)。1周目の修正で「再送しない」ようにした結果、誰も気づかないまま宙に浮く。これは人に通知するようにした。

もう1件は、テスト送信の扱いだ。開発中、自分宛てのテスト用アドレスに何度も送っていた。このテスト送信が、苦情率の計算の分母に入っていた。

テスト送信が分母に入ると、本番の苦情率が実際より低く見え、自動停止が働きにくくなる

テスト宛ての送信は苦情にならない。分母だけが増え、本番の苦情率が実際より低く見える。つまり見張り役が止まるべきときに止まりにくくなっていた。 見学用の実績の数字が水増しされるだけの問題ではなかった。安全装置が鈍っていたのだ。送り先に「テスト用」の印を付け、苦情率と実績の集計から外した。

3周目:同じ原因の漏れ(MEDIUM 1件)

3周目で出たのは、2周目と同じ原因の取りこぼしである(#121)。AIは毎週、反応を点数にして、点数の低い提案の型を4週ごとに入れ替える。この点数計算に、テスト送信への反応がまだ混ざっていた。入れ替えは人の承認なしで実行されるので、ここも外した。

この3周のあいだ、テストは400件以上すべて通っていた。 テストは書いた人が想定したことしか確かめない。タイムアウトの意味や、テスト送信が分母に入ることは、書いた時点で想定していなかった。だからテストは通る。想定の外を見るには、物差しを変えて見直すしかない。

ずんべぇ
ずんべぇ
AIが書いたコードをAIに見せて、意味あるんですか?同じ考え方で見落としそう。
うぉんば
うぉんば
同じ頼み方ならね。「売り物として」と立場を変えると、見る場所が変わる。書く側は「動くか」を見て、売る側は「事故らないか」を見るから。

段階2と段階3:任せる範囲を広げる

穴を塞いでから、自動送信の仕組みを実装した。

段階2:確率0.9以上なら人の確認なしで送る(#122)

設計で決めたのは4点だ。

  • 有効にできる条件は、直近の送信が連続30件、苦情0件であること
  • 条件を満たしても自動では有効にならない。人が監視画面のボタンで有効にする
  • 苦情が出たら、自動で段階1(全件承認)へ戻る
  • 手動で無効にするボタンも置く

実装は済んでいるが、段階2にはまだ届いていない。2026年10月2日時点で、本物の送り先への送信は0件だ。動作確認で自分宛てに送ったテスト送信5件は、前述のとおり集計から外している。連続30件の条件を満たすには、実際の送り先へ人の承認つきで送る実績を積むしかない。

段階3:新規営業より先に、返信を任せる(#123)

次の一歩として、確率のしきい値を0.9から下げることは選ばなかった。任せる業務の種類を広げた。

対象にしたのは、相手から届いた返信への応答と日程の提案である。初めての相手に送る売り込みより、すでにやり取りが始まった相手への返信のほうが、外したときの損害が小さい。リスクの低いところで、自動承認という仕組みの実績を積む。条件と有効化の手順は段階2と同じ形にそろえ、2つは独立に有効・無効を切り替えられる。

一方で、クレームとトラブルだけはAIに文面を作らせない(#125)。受信をクレームと判定したら、下書きも承認依頼も作らず、人に直接、優先度を上げて通知する。謝罪の文面は、関係を左右する。ここは任せる範囲の外に置いた。


正直に書いておくこと:「0.9」の意味が変わった

途中で、判定AIを入れ替えている(#116)。Jev は早期アクセスの順番待ちで、APIキーがまだ手元になかった。そこで、手元にあった OpenRouter 経由の汎用LLMに、プロンプトで確率を答えさせる形に置き換えた。

ここで「0.9」の意味が変わる。判定専用モデルの確率は、実際の当たり外れに合わせて較正されている(0.9と言ったものが、だいたい9割当たる)。汎用LLMが答える「0.9」は、そういう約束のない数字だ。 設定ファイルにもその旨を書き残した。

それでも段階2の設計を変えなかった理由は、確率だけに頼っていないからだ。送信の可否はプログラムが決め、苦情が出れば自動で段階1へ戻り、再開は人しかできない。確率が多少ずれても、事故は1件で止まる。 判定AIを替えても段階の設計を変えずに済んだのは、そのためである。


まとめ:任せる前に、止め方と戻し方を決める

この実験で得た手順は、次のとおりだ。

  1. 全件承認から始め、AIの判定は記録する。 人の判断との一致を実績として残す
  2. 規則で書けることはコードで書く。 お断りの除外、送信の上限、送信の停止はAIにしない
  3. 送る仕組みより先に、止める仕組みを作る。 再開は人だけができるようにする
  4. 物差しを変えてレビューする。 「売り物として」と頼むと、テストが通る状態でも穴が出る
  5. しきい値を下げる前に、低リスクな業務から範囲を広げる。 戻る条件もコードに書く

指示の書き方が「手順」から「範囲」へ移ったという話は、AIへの指示は「手順」から「範囲」へに書いた。今回の段階設計は、その「範囲」をコードで書いたものだと言える。AIに任せる範囲を、人が決め、条件を満たしたら人が広げる。任せきりにはしない。

自社でAI社員を動かした前回の記録はAI社員4名の実稼働レポートに、品質崩壊を防ぐルールはAI活用の失敗と教訓にまとめている。レベル5の実験は続けており、次の段階に進んだらまた書く。

まずは30分、見学から。

無料・オンライン。動いている事務所をそのままお見せします。