1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIに任せない問い合わせ業務をGASで管理する:除外ルールと人間確認キュー

1
Posted at

問い合わせ対応へ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を保証するものではありません。実際の運用では、組織の規程と担当者の判断を優先してください。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?