養蜂家が直販の注文をフォームで受け、備考の書き込みから送り先ごとの発送の一覧とお礼の文を Apps Script と AI で作る
養蜂園の直販の注文フォームに書かれた備考から、AIが送り先ごとの品目と数・のし・希望日・カードの文を取り出し、発送の一覧の行にします。発送日ごとの一覧とお礼のメールの下書きが自動ででき、家族は確かめて箱に詰めるだけになります。
- 生成AI
- ChatGPT/Claude
- 連携・自動化
- Google Apps Script/Make/Zapier
- 対象業界
- EC/その他/製造
- 対象部門
- 営業
- 対象業務
- データ入力・転記/書類作成
- 主な課題
- 入力作業が多い/書類作成に時間がかかる/確認ミスが多い
- AIで行う処理
- 抽出
- 主な効果
- 入力漏れ削減/対応スピード向上/工数削減
- 導入難易度
- ★☆☆☆☆
- 実装レベル
- 半自動化
- 費用感
- API連携(中)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- フォームの回答が回答のスプレッドシートに入る
- 家族が1件ずつ開き、品目と数、送り先1〜3、備考を読む
- 備考を読み解き、送り先ごとに何を何本送るかを発送の一覧に書き写す
- のしの表書き、カードの文、希望日・時間帯を一覧に書き足す
- 振込の注文は通帳と照らして入金を確かめ、一覧に印を付ける
- 発送日の前日に、入金済みの行を送り状の作成のサービスに入力する
- 注文者へお礼のメールを一通ずつ書いて送る
- 人注文者がフォームに品目と数、送り先1〜3、備考を書いて送る(今と同じ)
- 自動回答がスプレッドシートに入ったことをきっかけに Apps Script が動く
- 自動品目と数、送り先の呼び名、備考を Claude API に渡し、送り先ごとの品目と数・のし・希望日・カードの文を取り出させる
- 自動スクリプトが送り先ごとの本数の合計を注文の合計と照らし、合えば発送の一覧へ、合わなければ確認の一覧へ書く
- 人確認の一覧の注文だけを見て直す。分からなければ注文者へ聞く
- 人振込の注文は入金を確かめて、注文の行に印を付ける
- 自動発送日の前日の夕方、入金済みの送り先の行を発送日ごとの一覧にまとめ、お礼のメールの下書きを Gmail に作る
- 人一覧を見て箱に詰め、送り状を作る。お礼の下書きを読んで送る
各工程の詳しい説明を読む
- フォームの回答が回答のスプレッドシートに入る
- 家族が1件ずつ開き、品目と数、送り先1〜3、備考を読む
- 備考を読み解き、送り先ごとに何を何本送るかを発送の一覧に書き写す
- のしの表書き、カードの文、希望日・時間帯を一覧に書き足す
- 振込の注文は通帳と照らして入金を確かめ、一覧に印を付ける
- 発送日の前日に、入金済みの行を送り状の作成のサービスに入力する
- 注文者へお礼のメールを一通ずつ書いて送る
(a)備考の読み解きに時間がかかる。 「アカシアの300gを2本、1本は母へ、もう1本と百花蜜は自宅に」のような書き込みは、送り先1〜3のどれが「母」かを住所の欄から推し量ることから始まります。名字が同じだと分かりにくく、聞き返しのメールが要ることもあります。
(b)書き写しで本数がずれる。 3番目で、送り先ごとの本数を足すと注文の合計と合わない、ということが起きます。気づかずに梱包すると、先方に1本多いか少ない箱が届きます。 贈答では、注文者に「届いた本数が違う」と言われて初めて気づくこともあります。
(c)お礼のメールを毎回書いている。 初めての注文か、贈答か、発送日はいつかで文が変わるので、定型文をコピーしても毎回どこかを直しています。 乳児にはちみつを与えない注意を入れ忘れることもあります。
(d)贈答の時期に一気に増える。 お中元とお歳暮の時期は、ふだんの月の倍近い注文が届きます。読み解きと書き写しが追いつかず、発送日に間に合わない注文が出ます。
- 【人】 注文者がフォームに品目と数、送り先1〜3、備考を書いて送る(今と同じ)
- 【自動】 回答がスプレッドシートに入ったことをきっかけに Apps Script が動く
- 【自動】 品目と数、送り先の呼び名、備考を Claude API に渡し、送り先ごとの品目と数・のし・希望日・カードの文を取り出させる
- 【自動】 スクリプトが送り先ごとの本数の合計を注文の合計と照らし、合えば発送の一覧へ、合わなければ確認の一覧へ書く
- 【人】 確認の一覧の注文だけを見て直す。分からなければ注文者へ聞く
- 【人】 振込の注文は入金を確かめて、注文の行に印を付ける
- 【自動】 発送日の前日の夕方、入金済みの送り先の行を発送日ごとの一覧にまとめ、お礼のメールの下書きを Gmail に作る
- 【人】 一覧を見て箱に詰め、送り状を作る。お礼の下書きを読んで送る
4番目が、この設計の分かれ目です。 AIが取り出した数をそのまま使わず、フォームの決まった欄の本数と必ず照らします。 合っていれば人は読み直さず、合わないものだけを人が見ます。
お礼のメールを送るのは人です。 下書きは自動でできますが、送るのは箱に詰め終えたあとです。発送が遅れる注文に「本日発送しました」と送ってしまわないためです。
02今回想定するシステム構成
注文者 │ Google フォーム(品目と数・送り先1〜3・備考) ▼【トリガー①】フォームの送信(回答のスプレッドシート) Google Apps Script ├──▶ 品目と数・送り先の呼び名・備考を集める ▼ Claude API(構造化出力)── 送り先ごとの品目と数・のし・希望日・カードの文を取り出す ▼ Google Apps Script ── 送り先ごとの本数の合計と注文の本数を照らす ├── 合う ──▶ 発送の一覧(送り先ごとの行) └── 合わない ─▶ 確認の一覧 ──▶【人が直す】 ▼【トリガー②】発送日の前日の夕方(時間主導型) Google Apps Script ── 入金済みの行を発送日ごとにまとめる ├──▶ 発送日ごとの一覧(梱包と送り状の作成に使う) └──▶ Gmail にお礼のメールの下書き(乳児への注意は決まった文を差し込む)
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| 実行環境 | Google Apps Script | Make、Zapier |
| 生成AI | Claude API(Messages API、構造化出力) | OpenAI API |
| 保管 | Google スプレッドシート(注文の回答、品目の一覧、発送の一覧、確認の一覧、処理の記録) | - |
| メール | Gmail(下書きを作るだけ。送るのは人) | - |
新しく足すのは、Apps Script と、品目の一覧・発送の一覧・確認の一覧・処理の記録の4つのシートだけです。 フォームと回答のスプレッドシートは今のものを使います。
Apps Script を実行環境にしているのは、注文がすでにスプレッドシートに入っているからです。 フォームの送信時のインストール型のトリガーで、回答が入るたびに1件ずつ処理できます。 発送日ごとのまとめは、時間主導型のトリガーで動かします。
生成AIを Claude API にしているのは、構造化出力で送り先ごとの配列を決まった形で受け取れるからです。 代替候補から Gemini API を外しているのは、直販のフォームは誰でも注文でき、18歳未満が使う(使いうる)サービスでの利用を規約で禁じている製品があるため、利用者の年齢を限らないこの構成では避けました。
03どうやって実装するのか
処理の起点を決める
トリガーは2つです。
①回答のスプレッドシートのフォームの送信時のトリガー。 注文が1件届くたびに動きます。イベントには、質問の名前と値の組(namedValues)、スプレッドシートの列の順の値(values)、書き込まれた範囲(range)が入ります。この構成では namedValues で欄の名前から値を取り、列の並びが変わっても壊れないようにします。
届くたびに処理するのは、確認の一覧を早く出すためです。 備考が読み解けない注文は、注文者に聞き返す必要があります。発送日の前日にまとめて読むと、聞き返しの返事が発送に間に合いません。
②時間主導型のトリガー。 毎日17時台に動き、翌日が発送日(月曜か木曜)のときだけ発送日ごとの一覧とお礼の下書きを作ります。定時のトリガーは、設定した時刻から1時間の間で実行の時刻がばらつくので、17時台のどこかで動けば足りる処理にしています。
どちらもインストール型のトリガーで、作った人のアカウントで動きます。 お礼の下書きはそのアカウントの Gmail にできるので、養蜂園の注文用のアカウントでトリガーを作ります。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 注文の回答 | 注文の番号、注文者の名前とメール、品目ごとの数、送り先1〜3(名前・住所・電話)、送り先ごとの呼び名、支払いの方法、備考 | 回答のスプレッドシート |
| 品目の一覧 | 品目のコード、品名、容量、贈答の箱に入るか、発送の可否(在庫切れ) | 品目の一覧のシート |
| 注文者の履歴 | 過去の注文の回数(メールアドレスで数える) | 回答のスプレッドシート |
AIに渡すのは、品目と数、送り先の呼び名、備考だけです。 送り先の名前・住所・電話は渡しません。フォームに「送り先1を何と呼ぶか(例:自宅、母、田中さん)」の欄を作り、AIはその呼び名で振り分けを答えます。 住所はスクリプトが呼び名から引き当てます。
この「呼び名」の欄が、(a) をほぼ解きます。 注文者が備考に「母へ」と書いたとき、送り先1〜3のどれが母かを住所から推し量る必要がなくなります。呼び名の欄が空の送り先は「送り先2」のような番号の名前で渡します。
品目の一覧は、品名と容量の組み合わせを渡します。 備考に「アカシアの大きいほう」と書かれても、どれが「大きいほう」かを一覧から読めるようにするためです。
データの取得方法を決める
namedValuesから欄を取る … 品目ごとの数、送り先の呼び名、支払いの方法、備考- 品目の一覧を読む … 品目のコード・品名・容量の3列だけを文字にします
- 注文者の履歴を数える … 同じメールアドレスの過去の注文の数を数え、お礼の文に使います。AIには渡しません
- Claude API を呼ぶ …
UrlFetchApp.fetchで Messages API を呼びます。muteHttpExceptionsをtrueにし、失敗の応答でも例外で止めずに処理の記録へ書きます - 結果を照らして書く … 発送の一覧か確認の一覧に、送り先ごとに1行ずつ書きます
備考が空の注文は、AIを呼びません。 送り先が1つで備考が無ければ、注文の品目と数をそのまま送り先1の行にします。AIを呼ぶのは、送り先が2つ以上あるか、備考に何か書かれている注文だけです。 呼ぶ回数が減り、費用と読み違いの機会の両方が減ります。
API キーは、スクリプトのコードに書かずにスクリプトのプロパティに置きます。
AIへ渡す前に整形する
- 品目と数を数字にする … フォームの数の欄を数字にそろえ、0の品目を外します
- 送り先の数を数える … 名前の欄が埋まっている送り先だけを数えます
- 呼び名を作る … 呼び名の欄が空なら「送り先1」「送り先2」にします
- 品目の一覧から在庫切れを外す … 発送の可否が「不可」の品目は渡さず、注文にあれば確認の一覧へ回します
- 備考の文字数を見る … 1,000字を超える備考は、AIに渡さずに確認の一覧へ回します
3番目で呼び名を必ず作るのは、AIの答えを住所に結び付ける鍵だからです。 AIが「実家」と答えても、呼び名の欄に「実家」が無ければ、どの住所か決まりません。AIには、渡した呼び名のどれかだけで答えさせます。
AIに処理させる
させるのは、備考を読んで、送り先ごとに何を何本送るか、のし・希望日・カードの文は何かを取り出すことだけです。
| 取り出すもの | 取り出し方 | 決められないときの扱い |
|---|---|---|
| 送り先ごとの品目と数 | 注文の品目と数を、備考の書き込みに従って呼び名ごとに振り分ける | 振り分けが書かれていなければ unassigned に残す |
| のしの表書き | 「御中元」「御歳暮」「御礼」など書かれた文字のまま | 「のしを付けて」だけなら表書きを空にして noshi_unclear |
| 名入れ | のしに入れる名前が書かれていればそのまま | 書かれていなければ空 |
| 希望日・時間帯 | 書かれた日付・言い回しのまま | 「お盆の前」など日付でないものは原文のまま date_text に |
| カードの文 | 「カードに『いつもありがとう』と」の中の文をそのまま | 文が書かれていなければ空 |
| 問い合わせ | 備考に質問が書かれていれば、その文 | - |
表の1行目の「振り分けが書かれていなければ残す」が、この構成の安全装置です。 注文が3本で送り先が2つ、備考に何も無いとき、AIは「2本と1本」に分けたくなります。分け方を決めるのは注文者です。 書かれていなければ、振り分けずに unassigned に残させます。
| させないこと | 理由 |
|---|---|
| 書かれていない振り分けを決めること | 注文者に聞く。推し量った振り分けで箱を詰めない |
| 日付の計算(「お盆の前」を何日か) | 発送日の判断は家族が行う |
| 品目の言い換え(「大きいほう」を500gと決めること)の確定 | 候補として返し、一覧と照らす |
| 注意の文やお礼の文の作成 | 乳児への注意は決まった文。お礼は別の手順で下書きする |
| 送り先の名前・住所の扱い | AIには渡していない |
3行目は、取り出しと確定を分けるという意味です。 「アカシアの大きいほう」と書かれたら、AIは品目の一覧からアカシアの500gを候補として返します。スクリプトは、その品目が注文の品目と数の欄にあるかを確かめ、無ければ確認の一覧に回します。
指示内容を固定する
あなたは養蜂園の直販の受付として、注文の備考を読み、送り先ごとの発送の内容に分けます。
【注文の品目と数】(この合計を超えて振り分けないでください)
{order_items}
【送り先の呼び名】{recipient_labels}
【品目の一覧(コード|品名|容量)】
{item_list}
【備考】
{note}
【やること】
1. 備考の書き込みに従って、注文の品目と数を送り先の呼び名ごとに分けてください。
2. 送り先ごとに、のしの表書き、名入れ、希望日・時間帯、カードの文を取り出してください。
3. 備考に質問があれば、questions にそのまま写してください。
【厳守事項】
- 送り先は【送り先の呼び名】にあるものだけを使ってください。
備考に別の呼び方(「母」と「お母さん」など)があっても、最も近い呼び名に当てはめず、
当てはまるものが無ければ flags に recipient_unclear を入れてください。
- 振り分けが書かれていない品目は、どの送り先にも入れず unassigned に入れてください。
均等に分けたり、送り先1に寄せたりしないでください。
- 数を足したり引いたりしないでください。注文の数を超える振り分けを作らないでください。
- のしの表書き、カードの文は、書かれた文字をそのまま写してください。
言い直したり、敬語に直したりしないでください。
- 希望日が「お盆の前」「父の日に」など日付でない場合は、日付に直さず date_text に原文を写してください。
- 書かれていないことは空にしてください。推測で埋めないでください。
「最も近い呼び名に当てはめない」を書いているのは、取り違えの多くがここで起きるからです。 呼び名が「実家」と「義実家」のとき、備考の「母へ」はどちらとも読めます。AIが片方を選ぶと、それらしく見えるので誰も気づきません。 当てはまらないと答えさせ、人が注文者に聞きます。
カードの文を「そのまま写す」のも同じ理由です。 AIは丁寧な言い回しに直したくなりますが、カードは注文者から先方への言葉です。 一字でも変わると、注文者の言葉ではなくなります。
出力形式を固定する
Claude API の構造化出力で、次の形の JSON を受け取ります。 スキーマは output_config.format に type: "json_schema" で渡します。
{
"shipments": [
{
"recipient_label": "実家",
"items": [{ "item_code": "AC-300", "quantity": 1 }],
"noshi": "御中元",
"noshi_name": "山田",
"date_text": "8月10日まで",
"card_message": "いつもありがとう。暑いのでお体に気をつけて"
}
],
"unassigned": [{ "item_code": "HY-120", "quantity": 1 }],
"flags": ["noshi_unclear"],
"questions": ""
}
1つ目の理由は、送り先ごとの行にそのままなることです。 shipments の要素1つが発送の一覧の1行になり、呼び名から住所を引いて送り状に使う形がそろいます。
2つ目は、本数の照らし合わせを機械でできることです。 スクリプトは shipments と unassigned の数を品目ごとに足し、注文の数と比べます。
function checkAllocation_(order, ai) {
const sum = {};
ai.shipments.forEach(s => s.items.forEach(i => {
sum[i.item_code] = (sum[i.item_code] || 0) + i.quantity;
}));
ai.unassigned.forEach(i => { sum[i.item_code] = (sum[i.item_code] || 0) + i.quantity; });
const reasons = [];
Object.keys(order.items).forEach(code => {
if ((sum[code] || 0) !== order.items[code]) reasons.push('数が合わない: ' + code);
});
Object.keys(sum).forEach(code => {
if (!(code in order.items)) reasons.push('注文に無い品目: ' + code);
});
if (ai.unassigned.length) reasons.push('振り分けが無い品目あり');
if (ai.flags.length) reasons.push('要確認: ' + ai.flags.join(','));
if (ai.questions) reasons.push('質問あり');
return reasons; // 空なら発送の一覧へ、空でなければ確認の一覧へ
}
次のどれかに当たれば、確認の一覧へ回します。
| 条件 | 理由 |
|---|---|
| 品目ごとの合計が注文の数と違う | 振り分けの数がずれている |
unassigned が空でない | 振り分けが書かれていない品がある |
flags が空でない | 呼び名やのしが決まらない |
item_code が注文に無い品目 | 言い換えの候補が注文と合わない |
questions が空でない | 注文者からの質問に返事が要る |
スキーマには数値の範囲を入れません。 構造化出力は、minimum・maximum のような数値の制約に対応しておらず、指定すると400のエラーになります。 数が0以下でないか、注文の数を超えていないかは、スクリプトが確かめます。オブジェクトには additionalProperties: false を付けます。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| 回答のスプレッドシート | フォームの送信時のトリガー | 注文を1件ずつ受け取る |
| Claude API | UrlFetchApp で Messages API を呼ぶ | 備考の読み解き |
| 発送の一覧・確認の一覧 | SpreadsheetApp で書く | 送り先ごとの行と、確認の理由 |
| Gmail | GmailApp.createDraft | お礼のメールの下書き |
お礼のメールは、AIではなくスクリプトの決まった文で作ります。 文の差し替えは、初めての注文か、贈答か、発送日の3つだけで、スクリプトの条件分けで足ります。 発送日はトリガー②が決めた日付を入れます。
乳児への注意は、すべてのお礼のメールに同じ文で入れます。 消費者庁は、はちみつを生後1歳未満の乳児に与えてはいけないとし、ふだん乳児の世話をしていない人への情報の提供も大事だとしています。贈答で受け取る人に向けて、「贈り先に1歳未満のお子さまがいる場合はお伝えください」の一文も添えます。
下書きは GmailApp.createDraft(宛先, 件名, 本文, オプション) で作ります。 送るのは人で、発送を終えた注文の下書きだけを送ります。 この操作には Gmail の全体の権限(https://mail.google.com/)が要るので、注文用のアカウントで承認します。
人が確認する
人が見るのは、確認の一覧の注文と、発送日ごとの一覧です。
- 確認の一覧(毎日) … 理由の欄を読み、備考と照らして振り分けを直します。分からなければ注文者にメールで聞きます。 直したら「確認済み」にし、発送の一覧へ移します
- 入金の確認(毎日) … 振込の注文は、通帳と照らして注文の行に印を付けます。この印が無い注文は、発送日ごとの一覧に入りません
- 発送日ごとの一覧(発送日の前日) … 品目ごとの合計の本数を見て、瓶と箱が足りるかを確かめます
- お礼の下書き(発送の後) … 発送を終えた注文の下書きを読んで送ります
1番目を省かないでください。 確認の一覧に入る注文は、AIが「分からない」と言ったものです。そこを人が推し量らずに注文者へ聞くことが、(b) を防ぐ最後の段です。
贈答の時期は、確認の一覧を1日2回見ます。 注文が倍近くに増えると確認の一覧も増え、夕方にまとめて見ると、注文者への聞き返しが翌日の返事になって発送日を1回逃します。 朝と昼過ぎに見て、聞き返しのメールを早めに出します。
目標は、150件をならして1件2分です。 そのまま発送の一覧に入った注文は発送日の一覧で数十秒、確認の一覧の注文は数分かかります。
例外に対処する
| 起きること | 対応 |
|---|---|
| 振り分けの数が注文の数と合わない | 確認の一覧へ。注文者に聞く |
| 備考の呼び名が送り先の呼び名に無い | recipient_unclear で確認の一覧へ |
| 在庫切れの品目の注文 | 確認の一覧へ。代わりの品を勧めるかは家族が決める |
| 備考に質問が書かれている | 確認の一覧へ。返事は人が書く |
| 備考が1,000字を超える | AIに渡さずに確認の一覧へ |
| Claude API がエラーかタイムアウト | 処理の記録に失敗の応答を書き、注文を「未処理」にする。翌朝のトリガーで再試行するか、人が読む |
停止の理由が end_turn 以外 | 出力を使わずに「未処理」にする |
| 同じ注文が二度送られた | 同じメールアドレス・同じ品目と数・同じ送り先が10分以内なら「重複の疑い」 |
| 発送日に間に合わない希望日 | date_text を見て人が判断する。自動では弾かない |
上の4行が大半を占めます。 どれもAIの失敗ではなく、注文の書き方と在庫の問題です。 確認の理由を月ごとに数え、多い理由からフォームの説明文を直します。
「未処理」の注文は、スクリプトの側で拾い直します。 トリガー②が動くとき、未処理の注文が残っていればもう一度 AI に渡し、それでも失敗したものは発送日ごとの一覧の先頭に「未処理」として載せます。
記録を残す
- 注文の回答の全文(回答のスプレッドシートに残る)
- AIに渡した品目と数・呼び名・備考と、返った JSON の全文
- 照らし合わせの結果と、確認の一覧に入った理由
- 人が直した振り分けと、直した人・日時
- お礼の下書きを作った日時と、送った日時(Gmail の送信済みに残る)
- Claude API のエラーの応答
2つ目と4つ目を並べて残すのは、AIの読み違いと注文者の書き方の問題を分けるためです。 同じ直しが続くなら、プロンプトかフォームの説明文のどちらかに足します。
04実装レベルの3段階
最小構成は、確かめるための段階です。 月150件を手で貼るのは続きません。 半自動化で、1件8分が2分になる想定で、これが本記事の想定です。 読み解きと書き写しとお礼の文が自動になり、残るのは確認の一覧と発送日の一覧を見ることです。 本格構成は、送り状の作成のサービスが受け取れるファイルの形と、決済の記録の取り出し方を確かめてからです。 どちらも使っているサービスの仕様しだいなので、この記事では扱いません。
05工数削減シミュレーション
導入後 150件 × 2分 ÷ 60 = 5 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 養蜂園、果樹園、茶園、米農家、ジャムや干物の小さな加工場など、自家の産品を Google フォームやホームページのフォームで直販し、贈答の注文が多い生産者。注文の備考に送り先の振り分けやのし・カードの文が自由に書かれ、それを読み解いて発送の一覧に書き写し、お礼のメールを一通ずつ書くのに、家族の誰かが毎週半日以上かけている場合。
- ネットショップの仕組みで注文・決済・送り状・お礼のメールまで済んでいる場合。注文が月に十数件で、手で書き写しても負担にならない場合。贈答がほとんど無く、1件の注文がそのまま1件の発送になる場合。なお、在庫が足りないときにどの注文を先に送るか、値引きや送料の負担をどうするかという判断は、この構成では代替できません。
07最小構成で試す方法
- 去年の贈答の時期の注文から、送り先が2つ以上あるものを30件選ぶ
- その注文の品目と数、送り先の呼び名、備考を表にする(名前と住所は外す)
- 手元で使えるAIの画面に貼り、「備考に従って送り先ごとに品目と数を分けてください。書かれていない振り分けは決めずに残してください。のしとカードの文は書かれたとおりに写してください」と指示する
- 出てきた振り分けを、実際に送った内容と突き合わせる
30件は必ずやってください。 スクリプトを書く前に、「呼び名の欄があれば、備考から振り分けを取り出せるのか」を確かめます。
| 出てきた内容 | 判断 |
|---|---|
| 実際に送った振り分けと同じになった | スクリプトの作成に進む |
| 書かれていない振り分けを決めた | 指示の書き方で直る。構成は有効 |
| 呼び名が無くて振り分けられない | フォームに呼び名の欄を足すのが先 |
3行目が出ることは珍しくありません。 これまで送り先1〜3のどれが「母」かを家族が住所から推し量っていた、ということです。フォームの側を直すだけで、AIを入れる前から読み解きは楽になります。
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| 書かれていない振り分けをAIが決める | unassigned に残すよう指示し、数の照らし合わせで止める |
| 「母」を近い呼び名に当てはめる | 当てはまらなければ recipient_unclear を返させる |
| カードの文が丁寧に直される | 書かれた文字をそのまま写すよう指示する |
| 「お盆の前」を日付に直す | 日付にせず原文で返させ、人が判断する |
スキーマに minimum を入れて400になる | 数値の制約は使えない。範囲はスクリプトで確かめる |
| フォームの列を並べ替えたら壊れた | values ではなく namedValues で欄の名前から取る |
| 乳児への注意を入れ忘れる | AIに書かせず、決まった文をスクリプトが差し込む |
| お礼の下書きが個人のアカウントにできる | 注文用のアカウントでトリガーを作る |
| 発送前にお礼を送ってしまう | 送るのは発送を終えた注文の下書きだけにする |
| 「いつもの」と書かれた注文をAIが過去の注文で埋める | 過去の注文はAIに渡さない。確認の一覧へ回して人が過去の注文を見る |
| 贈答の時期に確認の一覧がたまる | 1日2回見て、聞き返しを早めに出す |
上の2行が、この構成の失敗のほとんどです。 どちらも、分からないことをAIが「それらしく」埋めることから起きます。分からないと言わせ、数で止める、の2つを設計で守ります。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: 注文者と送り先の名前・住所・電話・メールアドレス、注文の品目と数、備考、のしとカードの文です。送り先の名前と住所は、贈答では注文者以外の人の情報です。
- AIに名前と住所を渡さない … 呼び名の欄を作り、AIには呼び名と備考だけを渡します。住所はスクリプトが呼び名から引き当てます
- 備考に書かれた個人の情報に気をつける … 備考に先方の事情(入院中、出産祝い など)が書かれることがあります。AIの出力には書かれたことしか入りませんが、処理の記録に残るので、記録のシートを見られる人を家族に限ります
- 乳児への注意を必ず入れる … 贈答では、受け取る家庭に1歳未満の乳児がいるかを注文者も知らないことがあります。決まった文をすべてのお礼に入れ、商品の瓶のラベルにも同じ注意を表示します
- お礼を自動で送らない … 発送の遅れや中止があっても、下書きなら送らずに済みます
- 記録を残す期間を決める … 送り先の住所は、発送が終わって問い合わせの期間が過ぎたら、発送の一覧から消すか、別の保管の場所へ移します
消費者庁のページは、はちみつと、はちみつを含む食品に「1歳未満の乳児には与えないで下さい。」とわかりやすく表示することが必要だとしています。 瓶のラベルの表示はこの構成の外ですが、お礼のメールの注意と同じ文にそろえておくと、問い合わせのときに説明がそろいます。
誤りが起きた場合のリスクは、先方に違う品や違う本数が届くことと、乳児への注意が伝わらないことの2つです。 前者は数の照らし合わせで、後者はAIに書かせない決まった文で防ぎます。
10まず何から始めるか
1週目:フォームに呼び名の欄を足す
送り先1〜3のそれぞれに「この送り先を何と呼ぶか(例:自宅、母、田中さん)」の欄を足し、備考には呼び名を使って振り分けを書いてもらうよう説明文を直します。品目の一覧のシートを作ります。
2週目:30件で試す
去年の贈答の注文から30件を選び、名前と住所を外して手元のAIの画面で振り分けさせます。書かれていない振り分けを決めていないかを最優先で見ます。
3週目:振り分けと照らし合わせを作る
フォームの送信時のトリガーで、AIの振り分けを注文の数と照らし、発送の一覧か確認の一覧に書くところまで作ります。この時点では、これまでどおり手で書いた発送の一覧と並べて比べます。
4週目:発送日ごとの一覧とお礼の下書きを足す
時間主導型のトリガーで、入金済みの行を発送日ごとにまとめ、お礼の下書きを作ります。乳児への注意の文が全件に入っているかを、最初の数回は目で確かめます。
2か月目: 確認の一覧に入った理由を数え、フォームの説明文を直します。次の贈答の時期: 1件8分が何分になったかを実測し、発送日に間に合わない注文が出なくなった時点で、この構成は完成です。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
| インストール型のトリガーにフォームの送信時(フォームとスプレッドシート)と時間主導型があること。作った人のアカウントで動くこと。定時のトリガーは設定の時刻から1時間の間で実行の時刻がばらつくこと | Google for Developers: Installable triggers | 2026-10-28 |
スプレッドシートのフォームの送信時のイベントに namedValues(質問の名前と値)・values(列の順の値)・range が入ること | Google for Developers: Event objects | 2026-10-28 |
| URL の取得が個人のアカウントで1日20,000回、1回の実行が6分、トリガーの合計の実行時間が個人のアカウントで1日90分であること | Google for Developers: Quotas for Google Services | 2026-10-28 |
GmailApp.createDraft(recipient, subject, body, options) で下書きを作れ、htmlBody・replyTo・name などのオプションがあること。https://mail.google.com/ の権限が要ること | Google for Developers: Class GmailApp | 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" で指定すること。数値の範囲(minimum・maximum)と文字列の長さの制約は非対応で400になること。additionalProperties は false にすること。max_tokens で止まると出力がスキーマに合わないことがあること | Claude API Docs: Structured outputs | 2026-10-28 |
| API の利用者は18歳以上であることが求められ、18歳未満を対象とする、または18歳未満が利用しうるサービスの一部として使わないこととされていること | Google AI for Developers: Gemini API Additional Terms of Service | 2026-10-28 |
| はちみつを生後1歳未満の乳児に与えてはいけないこと。ふだん乳児の世話をしていない人への情報の提供も大事なこと。はちみつとはちみつを含む食品に「1歳未満の乳児には与えないで下さい。」とわかりやすい表示が必要なこと | 消費者庁: ハチミツによる乳児のボツリヌス症 | 2026-10-28 |
在庫が足りないときの注文の順番や、送料・値引きの扱いは、養蜂園の決まりとして家族で決めてください。 本記事は公開されている仕様と消費者庁の案内で確認できた範囲だけを扱っています。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-2216)についてのご相談はこちらから。
