0
0

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で検査する

0
Posted at

生成AIの試験運用では、要約や返信下書きが作成できた時点で「処理が完了した」と考えがちです。しかし実務で止まりやすいのは、AIの出力後に、誰が、いつ、何を確認するのかが記録されていないケースです。

この記事では、GoogleスプレッドシートとGoogle Apps Script(GAS)で、AIの最終判断を自動化せずに、次アクションの抜けだけを検査する台帳を作ります。問い合わせ本文や顧客情報をAIへ送る処理、メール送信、CRM更新は扱いません。

この記事で作るもの

  • AI試験運用の1件を next_actions シートへ記録する
  • 判断理由と次アクションを別々の列で管理する
  • 承認・修正・保留・停止の行に、担当者と期限があるか検査する
  • 期限切れと未入力を一覧化し、人間が次の確認を行えるようにする

問い合わせ受付から人間確認までのレビューゲート

この実装はAIの判定を正しいとみなす仕組みではありません。人が判断した後に、引き継ぎに必要な記録が揃っているかを点検する小さな補助です。

1. 完了状態を先に決める

対象業務を「AIが下書きを作った」までで終わらせず、次のように定義します。

対象: FAQに基づく一般問い合わせの返信下書き
AIの担当: 伏せ字済み情報の要約、FAQ候補、返信下書きの作成
人の担当: 原文、宛先、根拠、例外、次アクションの確認
完了: 送信可否、担当者、期限、理由が記録されている
保留: 情報不足、根拠不明、マスク未確認
停止: 契約・返金・苦情・事故・権限外の依頼

「確認済み」だけを記録すると、次の担当者が動けません。判断理由(なぜそう決めたか)と、次アクション(次に何をするか)は別の項目にします。

2. シートの列を用意する

スプレッドシートに next_actions という名前のシートを作り、1行目へ次の見出しを入力します。

record_id,workflow,classification,decision,decision_reason,
owner,next_action,due_at,source_ref,reviewed_at

各列の役割は次のとおりです。

列 例 注意点
record_id INQ-2026-0813-004 本文の代わりに管理用IDを残す
workflow faq_reply_draft 対象業務を1つに絞る
classification normal / boundary / stop 迷ったら boundary に戻す
decision 承認 / 修正 / 保留 / 停止 自由記述にしない
decision_reason FAQ v3と一致 判断の根拠を書く
owner support-lead 次に動く役割または担当者
next_action 宛先を確認して送信 「対応する」だけにしない
due_at 2026-08-13 17:00 期限を必須にする
source_ref faq-v3#refund 権限管理された参照IDだけにする
reviewed_at 2026-08-13 10:30 人が確認した時刻

顧客名、メールアドレス、電話番号、契約書の本文などをこの台帳へコピーしないでください。業務上必要な場合も、権限管理された正本へ戻れる参照IDを使います。

3. ヘッダー名で列を解決する

列番号を直接コードへ書くと、列を追加した時に別の値を読む危険があります。まず見出しから列番号を作ります。

function headerIndex(headers) {
  return headers.reduce((index, value, position) => {
    const key = String(value).trim();
    if (key) index[key] = position;
    return index;
  }, {});
}

function requireHeaders(index, names) {
  const missing = names.filter((name) => index[name] === undefined);
  if (missing.length > 0) {
    throw new Error(`必要な列がありません: ${missing.join(', ')}`);
  }
}

headerIndex は1行目の値を { record_id: 0, workflow: 1, ... } のようなオブジェクトへ変換します。見出しが足りない場合は、検査を続けずにエラーにします。

4. 次アクションの必須項目を検査する

次の関数は、AIを呼び出さず、1行の値だけを検査します。

const DECISIONS = new Set(['承認', '修正', '保留', '停止']);

function validateNextActionRow(row, index) {
  const recordId = String(row[index.record_id] ?? '').trim();
  if (!recordId) return { recordId: '', valid: true, errors: [] };

  const decision = String(row[index.decision] ?? '').trim();
  const errors = [];

  if (!DECISIONS.has(decision)) {
    errors.push('decisionが未入力または許可されていません');
  }
  if (!String(row[index.decision_reason] ?? '').trim()) {
    errors.push('decision_reasonが未入力です');
  }
  if (!String(row[index.owner] ?? '').trim()) {
    errors.push('ownerが未入力です');
  }
  if (!String(row[index.next_action] ?? '').trim()) {
    errors.push('next_actionが未入力です');
  }
  if (!row[index.due_at]) {
    errors.push('due_atが未入力です');
  }

  return { recordId, valid: errors.length === 0, errors };
}

未入力を 承認 と解釈しないことが重要です。形式が不正な行は通常処理へ進めず、エラー一覧へ戻します。

5. 未完了の行を検査結果シートへ出す

検査結果を next_action_review シートへ出力します。元の台帳を書き換えず、担当者が確認しやすい別シートへ出す構成です。

function reviewNextActions() {
  const book = SpreadsheetApp.getActiveSpreadsheet();
  const source = book.getSheetByName('next_actions');
  if (!source) throw new Error('next_actions シートがありません');

  const values = source.getDataRange().getValues();
  if (values.length < 2) throw new Error('検査対象の行がありません');

  const index = headerIndex(values[0]);
  requireHeaders(index, [
    'record_id', 'decision', 'decision_reason',
    'owner', 'next_action', 'due_at',
  ]);

  const output = [[
    'record_id', 'valid', 'errors', 'checked_at',
  ]];
  const checkedAt = new Date();

  values.slice(1).forEach((row) => {
    const result = validateNextActionRow(row, index);
    if (!result.recordId) return;
    output.push([
      result.recordId,
      result.valid,
      result.errors.join(' / '),
      checkedAt,
    ]);
  });

  const review = book.getSheetByName('next_action_review')
    || book.insertSheet('next_action_review');
  review.clearContents();
  review.getRange(1, 1, output.length, output[0].length).setValues(output);
}

この処理は「有効」と判定された行を送信したり、CRMへ反映したりしません。確認結果を表にするだけなので、最初は手動で reviewNextActions を実行して運用を観察できます。

6. 期限切れを別の条件で見る

必須項目が揃っていても、期限を過ぎたまま放置されることがあります。期限切れは入力エラーとは別の運用課題として集計します。

function findOverdueNextActions() {
  const book = SpreadsheetApp.getActiveSpreadsheet();
  const source = book.getSheetByName('next_actions');
  if (!source) throw new Error('next_actions シートがありません');

  const values = source.getDataRange().getValues();
  if (values.length < 2) return [];
  const index = headerIndex(values[0]);
  requireHeaders(index, ['record_id', 'decision', 'owner', 'next_action', 'due_at']);

  const now = new Date();
  return values.slice(1)
    .filter((row) => row[index.record_id])
    .filter((row) => row[index.decision] !== '停止')
    .filter((row) => row[index.due_at] instanceof Date)
    .filter((row) => row[index.due_at].getTime() < now.getTime())
    .map((row) => ({
      recordId: String(row[index.record_id]).trim(),
      owner: String(row[index.owner] ?? '').trim(),
      nextAction: String(row[index.next_action] ?? '').trim(),
      dueAt: row[index.due_at],
    }));
}

停止案件を通常の期限切れ一覧へ混ぜないようにしています。停止案件は契約、返金、苦情、事故、権限などを含む可能性があるため、権限のある担当者へ戻す別の扱いにします。

7. 最初の1日で確認すること

いきなり通知や自動送信を追加せず、まず1日分の記録で次を確認します。

  • 対象業務が1つに絞られている
  • AIが作るものと、人が確定するものが分かれている
  • 通常・境界・停止のケースを用意している
  • AIへ渡さない情報を決めている
  • decision_reason と next_action が別の列になっている
  • owner と due_at が必須になっている
  • 根拠を source_ref で追跡できる
  • 未完了の台帳を毎日誰が確認するか決めている

同じ理由が繰り返される場合は、AIのプロンプトを変更する前に、FAQの版番号、担当表、フォームの必須項目、CRMの状態定義などを見直します。未完了の台帳は失敗の記録ではなく、次に整える業務ルールの候補です。

AIに任せない範囲

この構成で自動化しているのは、記録の抜けを見つけることだけです。次の判断は人が行います。

  • 個人情報や機密情報をAIへ渡してよいか
  • 根拠の版と内容が一致しているか
  • 契約、返金、苦情、事故、権限に関わらないか
  • 宛先、期限、担当者が正しいか
  • 送信、公開、外部更新を実行してよいか

AI API接続、メール送信、CRM更新、権限変更を追加する場合は、マスキング、アクセス権、保存期間、承認者を別途決めてから拡張してください。

まとめ

生成AIの試験運用を止めないために、処理件数だけでなく、1件ごとの次の一歩を残します。

  1. decision_reason に判断理由を残す
  2. owner、next_action、due_at を必須にする
  3. GASで未入力と期限切れを検査する
  4. 繰り返す迷いをFAQ、フォーム、CRM、承認ルールへ戻す

まずは next_actions シートに10件だけ記録し、reviewNextActions を実行してください。下書き後に処理が止まる行が見つかったら、その行の next_action と担当者を決めることが、AIの利用件数を増やすより先の改善になります。

Miraigentでは、AI導入の前に対象業務、人間確認、記録の戻し先を確認する無料診断を案内しています。診断や外部公開へ進む場合も、最終判断と個人情報の扱いは人が確定します。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?