問い合わせ対応へ生成AIを入れるとき、いきなり返信文の生成から始めると、受付経路や責任者が揃っていないために確認が止まりやすくなります。本記事では、Googleスプレッドシートの点検表とGASで、AI化の前に7段階の準備度を判定する最小構成を作ります。
返信の自動送信、契約・料金・返金・苦情・個人情報に関する判断は扱いません。GASは準備度の記録と次の整備先の提示だけを行い、AIに渡す情報と送信の最終判断は人間が管理します。
1. 7段階の準備度を決める
READINESS シートの1行目を次にします。
check_id,checked_at,owner,stage,score,blocked_reason,next_action,evidence_ref
stage は次の7つから選びます。
RECEIVE -> RECORD -> CLASSIFY -> SOURCE -> DRAFT -> REVIEW -> IMPROVE
各段階の完了条件を先に固定します。
| 段階 | 完了条件 | 未達時の次の作業 |
|---|---|---|
| RECEIVE | 受付経路と受付時刻が記録される | フォーム・メールの入口をそろえる |
| RECORD | 問い合わせIDと原文の保存先がある | CRMまたは台帳の正本を決める |
| CLASSIFY | 種別・緊急度・担当が選べる | 分類値を5〜8個に絞る |
| SOURCE | 回答の根拠リンクを確認できる | FAQ・規程の正本を決める |
| DRAFT | AIの出力を下書きとして保存できる | 出力項目と入力範囲を決める |
| REVIEW | 人間の確認者と差し戻し理由が残る | 承認ルールを追加する |
| IMPROVE | 差し戻しをFAQやフォームへ戻せる | 週次の改善先を記録する |
## 2. シートの選択肢を設定する
`SETTINGS` シートに、段階ごとの完了条件を置きます。自由記述だけにせず、判定値を固定するのがポイントです。
```text
stage,required,owner,review_required
RECEIVE,true,受付担当,false
RECORD,true,受付担当,false
CLASSIFY,true,運用責任者,true
SOURCE,true,業務責任者,true
DRAFT,false,AI担当,true
REVIEW,true,承認者,true
IMPROVE,false,運用責任者,true
3. ヘッダー名で列を参照する
列番号を直接書かず、ヘッダー名から参照します。列を追加しても別項目を上書きしにくくなります。
const SHEET_NAME = 'READINESS';
const STAGES = ['RECEIVE', 'RECORD', 'CLASSIFY', 'SOURCE', 'DRAFT', 'REVIEW', 'IMPROVE'];
function headerIndex_(headers) {
return Object.fromEntries(headers.map((value, index) => [String(value).trim(), index]));
}
function getReadinessSheet_() {
const sheet = SpreadsheetApp.getActive().getSheetByName(SHEET_NAME);
if (!sheet) throw new Error(`Sheet not found: ${SHEET_NAME}`);
return sheet;
}
4. 準備度を記録する
未達理由と次の作業を必須にします。スコアだけが残ると、点数を上げることが目的になってしまうためです。
function recordReadiness(input) {
const stage = String(input.stage || '').trim();
const owner = String(input.owner || '').trim();
const reason = String(input.blockedReason || '').trim();
const nextAction = String(input.nextAction || '').trim();
const score = Number(input.score);
if (!STAGES.includes(stage)) throw new Error('unknown stage');
if (!owner || !nextAction || !Number.isInteger(score) || score < 0 || score > 2) {
throw new Error('owner, nextAction and score(0..2) are required');
}
if (score < 2 && !reason) throw new Error('blockedReason is required below 2');
const sheet = getReadinessSheet_();
const values = sheet.getDataRange().getValues();
const col = headerIndex_(values[0]);
['check_id', 'checked_at', 'owner', 'stage', 'score', 'blocked_reason', 'next_action']
.forEach((name) => { if (!(name in col)) throw new Error(`Missing column: ${name}`); });
const row = Array(values[0].length).fill('');
row[col.check_id] = `READY-${Utilities.getUuid().slice(0, 8)}`;
row[col.checked_at] = new Date();
row[col.owner] = owner;
row[col.stage] = stage;
row[col.score] = score;
row[col.blocked_reason] = reason;
row[col.next_action] = nextAction;
sheet.appendRow(row);
}
5. 判定結果を運用へ戻す
7段階すべてが2点なら、AI返信の試行へ進めます。ただし、準備度が高いことは自動送信の許可ではありません。
function summarizeReadiness() {
const sheet = getReadinessSheet_();
const values = sheet.getDataRange().getValues();
const col = headerIndex_(values[0]);
const latest = new Map();
values.slice(1).forEach((row) => latest.set(String(row[col.stage]), row));
const missing = STAGES.filter((stage) => !latest.has(stage));
const blocked = STAGES.filter((stage) => latest.has(stage) && Number(latest.get(stage)[col.score]) < 2);
return { readyForDraftTrial: missing.length === 0 && blocked.length === 0, missing, blocked };
}
実運用チェックリスト
- 受付経路と問い合わせIDが一意になっている
- 原文・添付・顧客情報の保存先とアクセス範囲を決めた
- AIへ渡さない情報をマスキングできる
- 根拠となるFAQ・規程に更新日がある
- AI出力は下書きとして保存される
- 契約・金銭・苦情・個人情報は人間確認へ戻る
- 差し戻し理由と次の改善先を記録する
まとめ
AI化の準備度は「AIを使えるか」ではなく、受付から改善までのどこが戻れる状態かで点検します。7段階のうち一つでも未達なら、その段階の次の作業を決めてから小さく試します。Miraigentの業務診断でも、ツール選定より先にこの準備度と戻し先を確認します。
