社会人のテニスクラブがコートの予約と雨天の中止の連絡を、スプレッドシートと Apps Script と AI で会員に送る
テニスクラブの幹事がスプレッドシートに持つコートの予約表から、練習の案内と雨天の中止・変更の連絡を Apps Script と AI が下書きします。幹事は判断の欄を変えて下書きを確かめるだけで、会員へ一斉に送れます。
- 生成AI
- ChatGPT/Claude/Gemini
- 連携・自動化
- Google Apps Script/Make/Zapier
- 対象業界
- その他/教育
- 対象部門
- 総務
- 対象業務
- 問い合わせ対応/書類作成
- 主な課題
- 属人化している/書類作成に時間がかかる/期限・対応漏れが起きる
- AIで行う処理
- 生成
- 主な効果
- 対応スピード向上/属人化解消/工数削減
- 導入難易度
- ★☆☆☆☆
- 実装レベル
- 半自動化
- 費用感
- API連携(中)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- 予約係が抽選の結果と民間のコートの予約を予約表に書く
- 連絡係が練習の3日前に、予約表を見て日時・コート・集合・当番・費用を書いた案内のメールを書く
- 出欠のフォームの回答を見て、前日に参加の人数と面数の割り振りを書いた確定の連絡を送る
- 雨の朝、予約係が空とコートの管理事務所の案内を見て中止を決め、連絡係にチャットで伝える
- 連絡係が中止のメールを書く。取消料がかかるときは、その扱いも書く
- 「何時に集合でしたっけ」「今日はやりますか」の問い合わせに個別に返す
- 人予約係が予約表に日付・時間・コート名・面数・集合・当番・費用を書く(今と同じ)
- 自動毎日18時台に、3日後の練習があれば Apps Script が予約表と出欠から事実を集める
- 自動Claude API が案内の文を下書きし、スクリプトが日付とコート名が文に入っているかを確かめる
- 自動下書きを送信待ちの表に書き、連絡係へ「確認してください」のメールを送る
- 人連絡係が送信待ちの表で文を読み、直すところがあれば直して「送る」の欄に印を付ける
- 自動印をきっかけに会員へ一斉に送り、送った日時を記録する
- 人雨の朝、予約係が予約表の判断の欄を「中止」「短縮」「変更」のどれかにする
- 自動判断の欄の変更をきっかけに、コートの一覧の取消の扱いとあわせて中止・変更の連絡を下書きし、送信待ちの表に書いて2人に知らせる
- 人2人のどちらかが下書きを確かめて「送る」に印を付ける
各工程の詳しい説明を読む
- 予約係が抽選の結果と民間のコートの予約を予約表に書く
- 連絡係が練習の3日前に、予約表を見て日時・コート・集合・当番・費用を書いた案内のメールを書く
- 出欠のフォームの回答を見て、前日に参加の人数と面数の割り振りを書いた確定の連絡を送る
- 雨の朝、予約係が空とコートの管理事務所の案内を見て中止を決め、連絡係にチャットで伝える
- 連絡係が中止のメールを書く。取消料がかかるときは、その扱いも書く
- 「何時に集合でしたっけ」「今日はやりますか」の問い合わせに個別に返す
(a)毎回、一から文を書いている。 案内も確定の連絡も、項目はほぼ同じなのに、前回のメールをコピーして日付とコートを書き換えるやり方です。書き換え忘れが起きやすく、先週のコート名のまま送ってしまうことがあります。
(b)雨の朝の連絡が遅れる。 4番目と5番目のあいだに、予約係から連絡係へのやりとりが挟まります。連絡係が通勤の電車の中だと、中止の連絡が集合の30分前になることがあります。
(c)書き漏れが問い合わせになる。 集合の時刻、ナイターの照明代、ボールの当番のどれかが抜けると、会員から個別の問い合わせが来て、その返事にまた時間を取られます。
(d)連絡係の書き方に頼っている。 取消料の扱いや、時間を短縮したときの費用の割り方は、連絡係が覚えて書いています。連絡係が出張の週は、予約係が慣れない文を書くことになります。
(e)宛先がそろわない。 前回のメールに返信する形で送ると、その後に入会した会員が宛先から漏れます。新しい会員ほど連絡が届かず、「中止を知らずにコートへ行った」という話になりがちです。 名簿から毎回宛先を作り直せば防げますが、手で行うと手間がかかります。
- 【人】 予約係が予約表に日付・時間・コート名・面数・集合・当番・費用を書く(今と同じ)
- 【自動】 毎日18時台に、3日後の練習があれば Apps Script が予約表と出欠から事実を集める
- 【自動】 Claude API が案内の文を下書きし、スクリプトが日付とコート名が文に入っているかを確かめる
- 【自動】 下書きを送信待ちの表に書き、連絡係へ「確認してください」のメールを送る
- 【人】 連絡係が送信待ちの表で文を読み、直すところがあれば直して「送る」の欄に印を付ける
- 【自動】 印をきっかけに会員へ一斉に送り、送った日時を記録する
- 【人】 雨の朝、予約係が予約表の判断の欄を「中止」「短縮」「変更」のどれかにする
- 【自動】 判断の欄の変更をきっかけに、コートの一覧の取消の扱いとあわせて中止・変更の連絡を下書きし、送信待ちの表に書いて2人に知らせる
- 【人】 2人のどちらかが下書きを確かめて「送る」に印を付ける
7番目と9番目の両方を人にしているのが、この設計の分かれ目です。 中止を決めるのも、中止の連絡を送るのも人です。自動にしたのは、その間の文づくりと送り先の準備だけです。 その代わり、予約係が1人で判断から送信まで済ませられるので、(b) のやりとりがなくなります。
送信を自動にしないのは、一度送った連絡は取り消せないからです。 中止でない日に中止の連絡が届くと、半分の会員が来なくなります。
02今回想定するシステム構成
予約表・コートの一覧・会員の名簿(Google スプレッドシート) 出欠の回答(Google フォーム → 同じスプレッドシート) │ ▼【トリガー①】毎日18時台(時間主導型) ▼【トリガー②】判断の欄の変更(編集時) Google Apps Script ├──▶ 予約表から3日後の練習、または判断が変わった練習の事実を集める ├──▶ 出欠の回答から参加の人数を数える ▼ Claude API(構造化出力)── 案内・中止・変更の連絡の文を下書き ▼ Google Apps Script ── 日付・コート名・時刻が文に入っているかを確かめる ▼ 送信待ちの表 ──▶ 幹事へ「確認してください」のメール ▼【トリガー③】「送る」の欄の変更(編集時) MailApp ── 会員へ一斉に送る(BCC) ▼ 送信の記録
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| 実行環境 | Google Apps Script | Make、Zapier |
| 生成AI | Claude API(Messages API、構造化出力) | OpenAI API、Gemini API |
| 保管 | Google スプレッドシート(予約表、コートの一覧、会員の名簿、出欠、送信待ち、送信の記録) | - |
| メール | MailApp(クラブのアカウントから送る) | GmailApp |
新しく足すのは、Apps Script と、コートの一覧・送信待ち・送信の記録の3つのシートだけです。 予約表と会員の名簿は今のものを使い、予約表に「判断」の列を1つ足します。
Apps Script を実行環境にしているのは、データがすべてスプレッドシートにあるからです。 インストール型のトリガーには、時間主導型、スプレッドシートの編集時、フォームの送信時などがあり、時間主導型は毎分から月1回までの間隔で動かせます。 新しいサーバーを持たずに、毎日の案内と、雨の朝の判断を起点にした処理の両方を組めます。
送信は MailApp で行います。 クラブの Gmail のアカウントで動かす場合、1日に送れる宛先は100件まで、1通の宛先は50件までです。会員45名に1通ずつ BCC で送ると、1回の連絡で45件を使います。同じ日に案内と中止の連絡の2回を送ると90件で、上限に近づきます。 第7章で、その扱いを書きます。
03どうやって実装するのか
処理の起点を決める
トリガーは3つあります。
①毎日18時台の時間主導型のトリガー。 3日後に練習がある日だけ案内を下書きし、前日に練習がある日は確定の連絡を下書きします。時間主導型のトリガーは、9時に設定すると9時から10時のあいだに動くように、実行の時刻が少しばらつきます。 18時台のどこかで動けば足りる用途なので、この構成では問題になりません。
②予約表の編集時のトリガー。 予約係が判断の欄を変えたときに動きます。編集時のトリガーは、変わったセルの範囲と、1つのセルの編集なら変更の前後の値を受け取れます。判断の列のセルが1つだけ変わったときにだけ処理を進め、 他の列の編集や、複数のセルの貼り付けでは何もしません。
③送信待ちの表の編集時のトリガー。 幹事が「送る」の欄に印を付けたときに、その行の連絡を送ります。
②と③は、インストール型のトリガーにします。 インストール型のトリガーは作った人のアカウントで動きます。 クラブのアカウントでトリガーを作っておけば、どちらの幹事が編集しても、送信はクラブのアカウントから行われます。
スクリプトが書き込んだ変更では、トリガーは動きません。 公式の説明には、スクリプトの実行や API のリクエストではトリガーは動かないとあります。スクリプトが送信待ちの表に下書きを書いても③は動かず、人が印を付けたときだけ送られます。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 予約表 | 練習の ID、日付、開始と終了の時刻、コート名、面数、集合の時刻と場所、当番、1人あたりの費用、判断(予定/中止/短縮/変更)、短縮・変更の内容 | 予約表のシート |
| コートの一覧 | コート名、住所、駐車場、雨天のときの扱い、取消の扱い(幹事が書いた文) | コートの一覧のシート |
| 出欠 | 練習の ID、参加・不参加、到着の遅れ | 出欠のフォームの回答のシート |
| 会員の名簿 | 名前、メールアドレス、連絡を受けるか | 会員の名簿のシート |
AIに渡すのは、上の3つだけです。 会員の名簿はAIに渡しません。メールアドレスはスクリプトが送信のときに使うだけで、当番も名前ではなく「当番A」「当番B」の記号で渡し、 文ができてからスクリプトが名前に置き換えます。
質を決めるのは、コートの一覧の「取消の扱い」の欄です。 「前日の17時までなら取消料なし。当日は全額。費用は参加予定者で割る」のように、幹事がコートごとに文で書いておきます。 AIはこの文を言い換えるだけで、取消料の有無を自分では決めません。
データの取得方法を決める
- 予約表を読む …
getDataRange().getValues()で全行を読み、①なら日付が3日後か1日後の行、②なら編集された行を選ぶ - コートの一覧を引く … その行のコート名でコートの一覧を引く。見つからなければ下書きを作らずに幹事へ知らせる
- 出欠を数える … 出欠の回答のシートから、その練習の ID の参加・不参加を数える。確定の連絡と短縮の連絡に人数を入れる
- 事実の表を作る … 1〜3をまとめて、AIに渡す事実の表(項目名と値の組)を作る
- Claude API を呼ぶ …
UrlFetchApp.fetchで Messages API を呼ぶ。muteHttpExceptionsをtrueにして、失敗の応答でも例外で止めずに中身を記録する
呼び出しの形は、おおむね次のとおりです。
const res = UrlFetchApp.fetch('https://api.anthropic.com/v1/messages', {
method: 'post',
contentType: 'application/json',
headers: {
'x-api-key': PropertiesService.getScriptProperties().getProperty('CLAUDE_KEY'),
'anthropic-version': '2023-06-01'
},
payload: JSON.stringify({
model: MODEL_ID, // 使うモデルはスクリプトのプロパティで切り替える
max_tokens: 1024,
messages: [{ role: 'user', content: prompt }],
output_config: { format: { type: 'json_schema', schema: NOTICE_SCHEMA } }
}),
muteHttpExceptions: true
});
if (res.getResponseCode() !== 200) { logError_(res.getContentText()); return; }
API キーは、スクリプトのコードに書かず、スクリプトのプロパティに置きます。 スクリプトは幹事2人で共有するので、コードに書くと見えてしまいます。モデルの名前もプロパティに置き、 公式のモデルの一覧が変わったときにコードを開かずに差し替えられるようにします。
AIへ渡す前に整形する
- 日付と時刻の書式をそろえる … 予約表の日付は日付の型で持ち、AIへは「11月8日(土)」「9時00分」のような文字にしてから渡します。曜日はスクリプトが付けます
- 空の欄を明示する … 集合の場所や費用が空なら、値を「(未記入)」にして渡します。空の欄を黙って省くと、AIが文の流れで埋めます
- 当番を記号に置き換える … 当番の名前を「当番A」「当番B」にし、対応はスクリプトが持ちます
- 判断の欄の値を確かめる … 「中止」「短縮」「変更」以外の値なら処理しません
- 同じ練習の重複を止める … 送信待ちの表に同じ練習の ID・同じ種類の未送信の下書きがあれば、新しく作らずに古いものを上書きします
2番目が地味に効きます。 費用の欄が空のまま渡すと、AIは「費用はいつもどおりです」のように書きます。「いつもどおり」は会員によって思い浮かべる額が違うので、問い合わせのもとになります。 「(未記入)」を受けたら missing_facts に挙げさせ、幹事が埋めてから送ります。
AIに処理させる
させるのは、事実の表から連絡の文を組み立てることだけです。 連絡の種類は4つです。
| 種類 | 入れる事実 | 入れ方の決まり |
|---|---|---|
| 案内(3日前) | 日付、時刻、コート名、面数、集合、当番、費用、出欠の締め切り | 冒頭に日付とコート名。出欠のフォームのURLは差し込み位置だけ示す |
| 確定(前日) | 上記+参加の人数 | 人数は数字のまま |
| 中止 | 日付、コート名、取消の扱い | 件名の頭に【中止】。取消の扱いは書かれた文の範囲で |
| 短縮・変更 | 日付、変わった内容(時刻・面数・コート)、費用の変化 | 件名の頭に【変更】。前と後を並べる |
| させないこと | 理由 |
|---|---|
| 中止にするかの判断 | 決めるのは幹事。AIは判断の欄の値に従う |
| 取消料の有無や額の推測 | コートの一覧に書かれた文だけを使う |
| 天気の予想を書くこと | 予報は事実の表に無い。書くと根拠のない連絡になる |
| 書かれていない集合場所や費用を補うこと | 空の欄は missing_facts に挙げる |
| 会員の名前を書くこと | 当番は記号のまま。名前はスクリプトが入れる |
3行目がいちばん起きやすい失敗です。 中止の連絡を書かせると、AIは「午後には天気が回復する見込みですが」のような一文を足しがちです。それを読んだ会員が「午後に再開するのか」と問い合わせてきます。 事実の表に無いことは書かせません。
指示内容を固定する
あなたは社会人のテニスクラブの連絡係として、会員へ送るメールの文を書きます。
下の【事実の表】に書かれたことだけを使ってください。
【連絡の種類】{notice_type} (案内/確定/中止/短縮・変更)
【事実の表】
{facts}
【コートの取消の扱い(幹事が書いた文)】
{cancel_rule}
【書き方】
- 件名は「{日付} {コート名} 練習の案内」の形にしてください。
中止なら頭に【中止】、短縮・変更なら頭に【変更】を付けます。
- 本文の最初の行に、日付・曜日・コート名をそのまま書いてください。
- 日付、時刻、コート名、面数、費用は、事実の表の文字をそのまま写してください。
言い換えたり、別の書き方に直したりしないでください。
- 当番は「当番A」「当番B」のまま書いてください。
- 出欠のフォームの場所には {FORM_URL} とだけ書いてください。
- 丁寧すぎず、仲間うちの連絡として読みやすい文にしてください。300字以内を目安にします。
【厳守事項】
- 事実の表に無いことを書かないでください。天気の見込み、代わりの練習、
次回の予定などを足さないでください。
- 値が「(未記入)」の項目は本文に書かず、missing_facts にその項目名を入れてください。
- 取消料・費用の扱いは、【コートの取消の扱い】に書かれた範囲だけで書いてください。
書かれていなければ費用の扱いには触れず、missing_facts に「取消の扱い」と入れてください。
- 中止にした理由を推測して書かないでください。理由が事実の表にあればそれだけを書きます。
「事実の表の文字をそのまま写す」を明記するのは、後でスクリプトが照らし合わせるためです。 「11月8日(土)」が「8日の土曜日」と書き換えられると、文としては正しくても機械では確かめられません。 そろえておけば、送る前の確認を文字列の一致で行えます。
出欠のフォームのURLをAIに渡さないのは、URLを書き写すときの1文字の誤りを避けるためです。 差し込みの印だけ書かせ、スクリプトが本物のURLに置き換えます。
出力形式を固定する
Claude API の構造化出力で、次の形の JSON を受け取ります。 スキーマは output_config.format に type: "json_schema" で渡します。
{
"subject": "【中止】11月8日(土) 中央公園テニスコート 練習の案内",
"body": "11月8日(土) 中央公園テニスコートの練習は、雨のため中止にします。……",
"missing_facts": [],
"notes_for_organizer": ""
}
1つ目の理由は、件名と本文を分けて受け取れることです。 スクリプトは subject を MailApp の件名に、body を本文に入れるだけで済みます。
2つ目は、missing_facts で送る前に止められることです。 配列が空でなければ、送信待ちの表のその行に「要記入」の印を付け、「送る」の印を付けても送らずに幹事へ知らせます。
スキーマの制約には注意します。 構造化出力では、数値の範囲や文字列の長さの制約(minimum・maxLength など)は使えず、指定すると400のエラーになります。 300字の目安はプロンプトに書き、長さはスクリプトの側で数えます。オブジェクトには additionalProperties: false を付けます。また、enum の値は大文字・小文字が変わって返ることがあるとされているので、種類の値を比べるときは大文字・小文字を区別しません。
応答が途中で切れることも考えます。 停止の理由が max_tokens のときは出力が不完全でスキーマに合わないことがあるとされているので、stop_reason が end_turn 以外なら下書きを使わずに作り直すか、幹事へ知らせます。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| 予約表・コートの一覧・出欠 | SpreadsheetApp で読む | 事実の表を作る |
| Claude API | UrlFetchApp で Messages API を呼ぶ | 連絡の文の下書き |
| 送信待ちの表 | SpreadsheetApp で書く | 下書き・確認の結果・「送る」の欄 |
| 幹事 | MailApp で知らせる | 「確認してください」のメール |
| 会員 | MailApp で送る(BCC) | 案内・中止・変更の連絡 |
送る前に、スクリプトが3つを確かめます。 ①本文に事実の表の日付とコート名がそのまま入っているか、②中止・変更なら件名の頭に【中止】【変更】があるか、③{FORM_URL} などの差し込みの印が残っていないか。1つでも外れたら、送らずに送信待ちの表へ「要修正」と書きます。
宛先の数も送る前に数えます。 MailApp.getRemainingDailyQuota() で、その日にあと何件の宛先に送れるかが分かります。残りが会員の数より少なければ送らずに、幹事へ「今日は送れない。チャットで連絡を」と知らせます。 1通の宛先は50件までなので、会員が50名を超えたら2通に分けます。
会員へのメールは BCC で送ります。 宛先の欄にはクラブのアドレスを入れ、会員のアドレスは BCC に並べます。会員どうしでメールアドレスが見えないようにするためです。
人が確認する
幹事が見るのは、送信待ちの表の下書きだけです。
- 件名と1行目 … 日付・曜日・コート名が合っているか。スクリプトも確かめていますが、「そもそも予約表の日付が違う」は人にしか分かりません
- 費用と取消の扱い … 中止・変更の連絡では、取消料の扱いが今回のコートに合っているか
- 「要記入」「要修正」の行 … 空の欄を埋めるか、文を直してから「送る」に印を付けます
中止の連絡は、判断した予約係本人が確かめて送ってかまいません。 2人のどちらかが見れば足りる設計にしています。連絡係の確認を待つと、(b) の遅れが戻ってしまうからです。
確定の連絡では、人数と面数の釣り合いも見ます。 参加が12名で予約が2面なら問題ありませんが、5名で3面なら1面を取り消せるかもしれません。この判断は文の確認のついでに幹事が行い、 面数を変えたら予約表を直してから下書きを作り直します。スクリプトは、参加の人数が面数×2を下回るときに送信待ちの表へ「面数を確認」と書くだけで、取消はしません。
目標は、24件をならして1件5分です。 下書きを読んで印を付けるだけなら1〜2分、空の欄を埋めたり文を直したりすると数分かかります。
例外に対処する
| 起きること | 対応 |
|---|---|
| コートの一覧にコート名が無い | 下書きを作らずに幹事へ知らせる |
| 判断の欄に想定外の値 | 何もしない。幹事が直すまで待つ |
| 判断の欄を複数のセルまとめて変えた | 編集時のトリガーでは処理しない。1行ずつ変えてもらう |
missing_facts が空でない | 「要記入」にして、埋まるまで送らない |
| 文に日付・コート名が入っていない | 「要修正」にして送らない |
| Claude API がエラーかタイムアウト | 失敗の応答を記録し、幹事へ「下書きを作れなかった」と知らせる |
停止の理由が end_turn 以外 | 下書きを使わず、作り直すか幹事へ知らせる |
| その日の送信の上限が足りない | 送らずに幹事へ知らせる。チャットで連絡する |
| トリガーが失敗した | 所有者に失敗の要約のメールが届く。クラブのアカウントのメールを幹事へ転送しておく |
| 出欠の回答がまだ1件も無い | 確定の連絡に人数を入れず、「出欠の締め切りが過ぎています」と幹事へ知らせる |
| 同じ日に午前と夜の2つの練習がある | 練習の ID で分けて、1つずつ下書きする。判断の欄も行ごとに変える |
| 中止を取り消したい(雨が上がった) | 判断の欄を「予定」に戻しても自動では何も送らない。幹事が送信待ちの表に手で書いて送る |
最後の行は、意図して自動にしていません。 「中止の中止」は会員を最も混乱させる連絡で、人が言葉を選んで書くべきだからです。
トリガーの失敗の知らせは、トリガーを作ったアカウントに届きます。 クラブのアカウントを誰も見ていないと、失敗に気づけません。
記録を残す
- 送信待ちの表の全行(下書き、
missing_facts、確認の結果、「送る」を付けた人と日時) - 実際に送った件名と本文、宛先の数、送った日時
- AIに渡した事実の表と、AIが返した JSON の全文
- 幹事が下書きを直した場合は、直す前と後の文
- Claude API のエラーの応答
3つ目を残すのは、文の誤りがどこで入ったかを見分けるためです。 事実の表が正しくて文が違えばAIの問題、事実の表が違えば予約表の問題です。直す場所が変わります。
4つ目は、指示を直す材料です。 幹事が毎回同じところを直しているなら、プロンプトの書き方の決まりに足します。
記録は1年分を残し、それより古い行は年に1回、別のシートへ移します。 送信待ちの表が長くなると、スクリプトが毎回全行を読む時間が延び、1回の実行の上限(6分)に近づくからです。 会員が退会したら、名簿の行は消さずに「連絡を受けない」にして、過去の送信の記録と食い違わないようにします。
04実装レベルの3段階
最小構成は、確かめるための段階です。 月24件を手で回すと、文を書く時間は減っても事実を拾う時間が残ります。 半自動化で、1件20分が5分になる想定で、これが本記事の想定です。 事実の収集、下書き、送り先の準備が自動になり、残るのは下書きを読んで印を付けることだけです。 本格構成は、会員が増えてから考えれば足ります。 面数の割り振りは参加の人数とレベルの組み合わせで、幹事の判断が入る部分が大きいからです。 段階を飛ばさないでください。 半自動化を2〜3か月回すと、どのコートで中止が多いか、どの項目がよく「(未記入)」になるかが送信待ちの表に残ります。中止の多いコートは予約の取り方を見直す材料に、未記入の多い項目は予約表の書き方を見直す材料になります。 そこを直してから本格構成に進むほうが、連絡の手間はさらに減ります。
05工数削減シミュレーション
導入後 24件 × 5分 ÷ 60 = 2 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 社会人のテニス・バドミントン・フットサル・ソフトボールなどのクラブやサークルで、公営や民間のコート・体育館を毎月予約し、週に1〜3回の練習を行っている団体。会員が数十名で、練習の案内と雨天の中止の連絡を幹事がメールやチャットで一人ずつ書いて送っており、幹事が仕事の合間に連絡するため、雨の朝の連絡が遅れたり、集合や費用の書き漏れで問い合わせが来たりしている場合。会員の名簿と予約を Google スプレッドシートで持っている場合。
- 予約・出欠・連絡をまとめて扱う専用のサービスを使っていて、中止の通知がそのサービスで済んでいる団体。会員が十名ほどで、グループのチャットに一言書けば足りる場合。会員に18歳未満が含まれるジュニアのクラブ(未成年の保護者への連絡は別の配慮が要る)。なお、雨天で中止にするか、コートの取消料を誰が負担するかという判断は、この構成では代替できません。
07最小構成で試す方法
- 先月の練習のうち、案内・確定・中止の連絡を送った回を5回分選ぶ
- その回の予約表の行とコートの取消の扱いを、項目名と値の表にする
- 手元で使えるAIの画面に表を貼り、「この表の事実だけを使って、会員への連絡のメールを書いてください。表に無いことは書かないでください。日付とコート名は表のとおりに書いてください」と指示する
- 出てきた文を、実際に送ったメールと比べる
5回分で足ります。 スクリプトを書く前に、「事実の表さえあれば、そのまま送れる文になるのか」を確かめます。
| 出てきた内容 | 判断 |
|---|---|
| 送ったメールと同じ事実が入っている | スクリプトの作成に進む |
| 天気の見込みなど表に無いことを足した | 指示の書き方で直る。構成は有効 |
| 取消の扱いが書けない | コートの一覧の取消の扱いが足りない。 先に書き留める |
3行目は、連絡係の頭の中にあった決まりが外に出ていないということです。 この構成の前に、コートごとの取消の扱いを文にしておくこと自体が、(d) の属人化を減らします。
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| AIが天気の見込みや次回の予定を足す | 事実の表に無いことを書かないよう指示し、送る前に人が読む |
| 日付が別の書き方に直される | 「表の文字をそのまま写す」と指示し、スクリプトで一致を確かめる |
| 空の欄をAIが「いつもどおり」で埋める | 「(未記入)」と明示して渡し、missing_facts に挙げさせる |
スキーマに maxLength を入れて400になる | 長さの制約は使えない。プロンプトに書き、スクリプトで数える |
| 貼り付けで判断の欄を変えても動かない | 複数のセルの編集では変更の前後の値が取れない。1行ずつ変える |
| スクリプトの書き込みで送信が始まる心配 | スクリプトの実行ではトリガーは動かない。人の印だけで送られる |
| 同じ日に2回送ると上限に近づく | 送る前に残りの宛先の数を確かめる |
| 会員が50名を超えたら送れない | 1通の宛先は50件まで。2通に分ける |
| 幹事の個人のアカウントでトリガーを作った | クラブのアカウントで作り直す |
| トリガーの失敗に誰も気づかない | 失敗の知らせのメールを幹事へ転送する |
| 退会した会員に連絡が届き続ける | 名簿の「連絡を受けるか」の列から毎回宛先を作り直す |
| 送信待ちの表が長くなり処理が遅い | 1年より古い行を別のシートへ移す |
| 出欠のフォームのURLが壊れている | URLはAIに書かせず、差し込みの印をスクリプトが置き換える |
上の3行が、この構成の失敗のほとんどです。 どれもAIが文の流れを気にして事実を足すことから起きます。事実の表に無いことは書かない、を指示とスクリプトの両方で守ります。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: 練習の日時とコート名、費用、参加の人数、会員の名前とメールアドレスです。会員の名前とメールアドレスはAIに渡しません。
- AIに渡すのは事実の表だけにする … 当番は記号、出欠は人数だけにします。誰が来ないかという情報は、連絡の文には要りません
- 会員のメールアドレスを BCC にする … 宛先の欄に並べると、会員どうしでアドレスが見えます
- 送信を自動にしない … 一度届いた中止の連絡は取り消せません。幹事の印を必ず挟みます
- API キーをコードに書かない … スクリプトのプロパティに置き、スクリプトを共有する人を幹事に限ります
- アカウントの持ち主を決める … インストール型のトリガーは作った人のアカウントで動きます。クラブのアカウントで作り、パスワードの管理を2人で決めておきます
未成年の会員がいるクラブには、この構成をそのまま使わないでください。 保護者への連絡の仕方や、名簿の扱いに別の配慮が要ります。生成AIの製品によっては、18歳未満が使う(使いうる)サービスでの利用を規約で制限しているものもあります。
誤りが起きた場合のリスクは、中止でない日に中止を知らせることと、間違った日時やコートを知らせることの2つです。 どちらも、AIの文と予約表の事実の食い違いから起きます。送る前の文字列の照らし合わせと幹事の確認の2段で守ります。
10まず何から始めるか
1週目:コートの一覧を作る
コートごとに、住所、駐車場、雨天のときの扱い、取消の扱いを文で書きます。連絡係が覚えていることを、予約係も読める形にするのが目的です。 予約表に「判断」の列を足します。
2週目:5回分で試す
先月の5回分の事実を表にして、手元のAIの画面で連絡の文を書かせます。実際に送ったメールと比べ、表に無いことを足していないかを最優先で見ます。
3週目:案内の下書きを作る
毎日18時台のトリガーで、3日後の練習の案内を送信待ちの表に書くところまで作ります。この時点ではまだ送らず、連絡係が自分で書いた文と並べて1週間比べます。
4週目:中止の連絡と送信をつなぐ
判断の欄の変更から中止の連絡を下書きし、「送る」の印で一斉に送るところまで作ります。最初の雨の日は、予約係が下書きを確かめて送り、連絡係も同じものを読んで答え合わせをします。
2か月目: 確定の連絡と短縮・変更の連絡を足します。3か月目以降: 幹事が下書きを直した箇所を数え、プロンプトの決まりに足します。雨の朝の連絡が予約係1人で数分で終わるようになった時点で、この構成は完成です。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
| インストール型のトリガーに時間主導型・編集時・変更時・フォームの送信時などがあり、時間主導型は毎分から月1回までの間隔で動かせること。作った人のアカウントで動くこと。定時のトリガーは9時の設定なら9時〜10時に動くように時刻がばらつくこと。失敗すると要約のメールが届くこと。スクリプトの実行や API のリクエストではトリガーが動かないこと | Google for Developers: Installable triggers | 2026-10-28 |
編集時のイベントの oldValue・value が1つのセルの編集のときだけ得られ、range で編集された範囲が分かること | Google for Developers: Event objects | 2026-10-28 |
| メールの宛先が個人のアカウントで1日100件、Google Workspace で1日1,500件、1通の宛先が50件まで。1回の実行が6分、トリガーの合計の実行時間が個人のアカウントで1日90分であること | Google for Developers: Quotas for Google Services | 2026-10-28 |
MailApp.sendEmail に bcc・name・replyTo・htmlBody などのオプションがあること。getRemainingDailyQuota() でその日の残りの宛先の数が分かること。noReply は Google Workspace のアカウントだけで使えること | Google for Developers: Class MailApp | 2026-10-28 |
UrlFetchApp.fetch に method・contentType・headers・payload を渡せ、muteHttpExceptions を true にすると失敗の応答でも例外を投げないこと | Google for Developers: Class UrlFetchApp | 2026-10-28 |
構造化出力を output_config.format に type: "json_schema" で指定すること。数値の範囲と文字列の長さの制約は非対応で400になること。additionalProperties は false にすること。enum の値は大文字・小文字が違って返ることがあること。max_tokens で止まると出力がスキーマに合わないことがあること | Claude API Docs: Structured outputs | 2026-10-28 |
雨天で中止にするか、コートの取消料を誰が負担するかは、クラブの決まりとして幹事と会員で決めてください。 本記事は公開されている仕様で確認できた範囲だけを扱っています。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-2215)についてのご相談はこちらから。
