問い合わせ対応へAIを入れるとき、「何を任せるか」から考え始めると、例外案件まで同じ流れに入れてしまいます。先に、AIへ渡さない業務を明示しておくと、担当者が確認すべき案件を見失いにくくなります。
この記事では、Googleスプレッドシートに除外ルールを置き、GASで問い合わせを human_review キューへ登録する最小構成を紹介します。AIによる判断、顧客への自動送信、権限変更は行いません。
作るシート
INQUIRIES は問い合わせの正本、EXCLUSION_RULES はAIへ渡さない条件、HUMAN_REVIEW_QUEUE は確認待ちを記録するシートです。
| シート | 主な列 | 役割 |
|---|---|---|
| INQUIRIES | inquiry_id, status, category, amount, has_personal_data | 正本を参照する |
| EXCLUSION_RULES | rule_id, field, operator, value, enabled, reason | 除外条件を管理する |
| HUMAN_REVIEW_QUEUE | queue_key, inquiry_id, rule_id, reason, state, queued_at | 人間確認の責任を可視化する |
例として、契約・返金・苦情・個人情報・高額案件はAIへ渡さないルールにします。ルールの値は業務ごとに管理者が決め、サンプルのまま本番へ流用しません。
GASで除外ルールを適用する
const CONFIG = {
inquirySheet: 'INQUIRIES',
ruleSheet: 'EXCLUSION_RULES',
queueSheet: 'HUMAN_REVIEW_QUEUE',
};
function enqueueExcludedInquiries() {
const book = SpreadsheetApp.getActive();
const inquiries = rows_(book.getSheetByName(CONFIG.inquirySheet));
const rules = rows_(book.getSheetByName(CONFIG.ruleSheet))
.filter(rule => String(rule.enabled).toLowerCase() === 'true');
const queueSheet = book.getSheetByName(CONFIG.queueSheet);
const existing = new Set(rows_(queueSheet).map(row => row.queue_key).filter(Boolean));
inquiries.forEach(inquiry => {
if (!inquiry.inquiry_id || inquiry.status !== 'unreviewed') return;
const matched = rules.find(rule => matches_(inquiry, rule));
if (!matched) return;
const key = `${inquiry.inquiry_id}:${matched.rule_id}`;
if (existing.has(key)) return;
queueSheet.appendRow([
key, inquiry.inquiry_id, matched.rule_id,
matched.reason || 'excluded_from_ai', 'waiting_human', new Date(),
]);
existing.add(key);
});
}
function matches_(inquiry, rule) {
const actual = String(inquiry[rule.field] ?? '').toLowerCase();
const expected = String(rule.value ?? '').toLowerCase();
if (rule.operator === 'equals') return actual === expected;
if (rule.operator === 'contains') return actual.includes(expected);
return false;
}
function rows_(sheet) {
const values = sheet.getDataRange().getValues();
const headers = values.shift().map(String);
return values.map(row => Object.fromEntries(headers.map((h, i) => [h, row[i]])));
}
queue_key に問い合わせIDとルールIDを含めることで、時間主導トリガーが複数回動いても同じ確認待ちを重ねません。ルールに一致しない案件だけを、別途定義したAI下書き処理の候補にします。
ルール変更を安全に扱う
-
enabledを変更した人と変更理由を別の変更ログへ残す - ルールを無効化しても、既存の確認キューは自動削除しない
- 契約、料金、返金、苦情、事故、個人情報は人間確認を必須にする
-
waiting_humanの案件をAI処理や外部送信へ進めない - ルールの見直し日と責任者を決める
除外ルールは「AIが苦手な一覧」ではなく、業務上の責任を人へ戻す境界です。条件に一致した理由を残すと、後からFAQや入力フォームを改善する材料にもなります。
導入前チェックリスト
- AIへ渡さない業務を具体的な条件で列挙した
- ルールごとに責任者・理由・見直し日を決めた
- 問い合わせ本文を確認キューへ複製していない
-
queue_keyで重複登録を防いだ - 未割当・期限超過・停止状態を確認できる
- ルール変更後に既存キューをどう扱うか決めた
-
人間が
send / revise / ask / stopを決める
このサンプルは確認対象を整理するためのものです。AIの正確性、返信品質、法令対応、SLAを保証するものではありません。実際の運用では、組織の規程と担当者の判断を優先してください。
