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
Last updated at Posted at 2026-09-25

AIのモデル、プロンプト、FAQ、問い合わせフォームを変更すると、変更したファイル以外にも確認が必要な場所が増えます。変更履歴を「プロンプト v3 を v4 にした」の一行で終えると、次の担当者は次のことを判断できません。

  • どの入力項目が変わるのか
  • 返信下書きやCRM記録へ影響するのか
  • 通常・境界・停止のどのケースを確認するのか
  • どの条件で反映を止め、誰へ戻すのか

この記事では、GoogleスプレッドシートとGoogle Apps Script(GAS)で、変更元から影響先と確認ケースをたどる「変更影響マップ」を作ります。AI APIの呼び出し、外部通知、顧客への自動返信は扱いません。変更の候補を記録し、人間が反映可否を判断する手前までが対象です。

問い合わせ対応の変更を影響先と人間確認へたどるMiraigentのレビューゲート

この記事で作るもの

次の2シートを持つ最小構成です。

シート 役割
AI_CHANGE_IMPACT_LOG 1件の変更、影響先、確認ケース、停止条件を記録する
AI_CHANGE_CASES 通常・境界・停止の期待結果と確認状態を記録する

完成状態は、変更を登録したときに、確認が必要な影響先と未確認ケースを抽出できることです。反映を自動承認することは完成条件に含めません。

1. 変更影響マップの列を先に固定する

変更ログには顧客本文やAIレスポンス全文をコピーせず、正本へ戻る参照IDと短い分類値だけを保存します。最初の行に次の見出しを置きます。

change_id,changed_at,target,change_kind,before_ref,after_ref,reason_code,
impacted_workflows,review_owner,stop_condition,status,next_review_at,notes
列 例 記録する内容
change_id CHG-20260925-001 変更を追跡する固定ID
target reply_prompt 変更対象の名前
change_kind prompt model / prompt / faq / form など
before_ref reply-prompt-v3 変更前の正本参照
after_ref reply-prompt-v4 変更後の正本参照
impacted_workflows reply_draft,crm_note 影響する業務の分類値
review_owner operations_owner 反映前に確認する役割
stop_condition source_conflict 反映を止める条件
status OPEN OPEN / VERIFIED / BLOCKED

impacted_workflows は編集したファイルの一覧ではありません。プロンプトを変更した結果、返信下書き、確認キュー、CRMメモの形式が変わるなら、3つすべてを影響先に含めます。

2. 影響先と停止条件をコードで限定する

自由入力の文字列だけで運用すると、同じ意味の値が増えて抽出漏れが起きます。候補値をコードで限定し、未知の値は通常扱いにしないようにします。

const CHANGE_CONFIG = Object.freeze({
  sheetName: 'AI_CHANGE_IMPACT_LOG',
  caseSheetName: 'AI_CHANGE_CASES',
  status: {
    open: 'OPEN',
    verified: 'VERIFIED',
    blocked: 'BLOCKED',
  },
  impacts: [
    'intake',
    'ai_processing',
    'human_review',
    'external_output',
    'crm_record',
  ],
  stopReasons: new Set([
    'contract_or_money',
    'personal_data_boundary',
    'credential_or_access',
    'source_conflict',
    'external_send_rule',
    'decision_condition_changed',
  ]),
});

function requiresStopReview(reasonCodes) {
  return reasonCodes.some((code) => CHANGE_CONFIG.stopReasons.has(code));
}

stopReasons にない理由を安全とみなしてはいけません。未登録の理由は後述の BLOCKED に送り、担当者が分類を追加してから再確認します。

3. 変更影響マップを重複なく登録する

GASからスプレッドシートへ書き込む関数は、顧客情報ではなく変更記録のオブジェクトを受け取るようにします。change_id の重複を先に確認し、同じ変更を二重登録しないようにします。

function registerChange(change) {
  const sheet = SpreadsheetApp
    .getActiveSpreadsheet()
    .getSheetByName('AI_CHANGE_IMPACT_LOG');

  if (!sheet) throw new Error('CHANGE_LOG_SHEET_NOT_FOUND');
  if (!change.changeId || !change.target || !change.afterRef) {
    throw new Error('CHANGE_REQUIRED_FIELD_MISSING');
  }

  const values = sheet.getDataRange().getValues();
  const headers = values.shift();
  const idIndex = headers.indexOf('change_id');
  if (idIndex < 0) throw new Error('CHANGE_ID_COLUMN_NOT_FOUND');

  if (values.some((row) => row[idIndex] === change.changeId)) {
    return { created: false, reason: 'DUPLICATE_CHANGE_ID' };
  }

  const reasonCodes = change.reasonCodes || [];
  const unknownReason = reasonCodes.some((code) => ![
    'contract_or_money',
    'personal_data_boundary',
    'credential_or_access',
    'source_conflict',
    'external_send_rule',
    'decision_condition_changed',
  ].includes(code));
  const status = unknownReason || requiresStopReview(reasonCodes)
    ? 'BLOCKED'
    : 'OPEN';

  sheet.appendRow([
    change.changeId,
    new Date(),
    change.target,
    change.changeKind || 'unknown',
    change.beforeRef || '',
    change.afterRef,
    reasonCodes.join(','),
    (change.impactedWorkflows || []).join(','),
    change.reviewOwner || '',
    change.stopCondition || 'UNSPECIFIED',
    status,
    change.nextReviewAt || '',
    unknownReason ? 'UNKNOWN_REASON_REQUIRES_REVIEW' : '',
  ]);

  return { created: true, status };
}

契約・料金、個人情報の境界、権限、正本の競合、外部送信、判定条件の変更を BLOCKED にします。BLOCKED は失敗を意味する固定値ではなく、反映前に人が確認すべき状態です。

4. 通常・境界・停止のケースを作る

変更の動作確認を成功例だけで終わらせると、停止条件を通過してしまう変更を見逃します。テスト入力は実データではなく、固定IDと属性で作ります。

case_id,change_id,case_type,input_profile,expected_decision,review_status,evidence_ref
CASE-001,CHG-20260925-001,NORMAL,required_fields_complete,REVIEW_REQUIRED,OPEN,fixture-normal-001
CASE-002,CHG-20260925-001,BOUNDARY,missing_context,REVIEW_REQUIRED,OPEN,fixture-boundary-001
CASE-003,CHG-20260925-001,STOP,source_conflict,BLOCKED,OPEN,fixture-stop-001
ケース 入力の特徴 期待する結果
NORMAL 必須項目があり、参照先が一つ 下書き候補を作って人が確認
BOUNDARY 必須項目の一部不足、条件が曖昧 不足項目を記録して確認キューへ
STOP 正本が競合、権限不足、外部送信に影響 反映を止め、担当者へ戻す

未確認のケースだけを抽出する

function listReviewRequiredCases(rows) {
  return rows.filter((row) => {
    const notVerified = row.reviewStatus !== 'VERIFIED';
    const isBoundaryOrStop = ['BOUNDARY', 'STOP'].includes(row.caseType);
    return notVerified || isBoundaryOrStop;
  });
}

この関数は確認対象を絞るだけで、承認や公開を行いません。STOP が VERIFIED になっていても、停止条件を解除してよいかは別の人間確認として残します。

5. 変更前チェックを時間主導トリガーにする

定期確認では、未確認の変更とケースの組み合わせを一覧にするだけにします。メール送信や外部サービスへの通知は、社内の権限・宛先・保存方針を確認してから別途設計してください。

function buildChangeReviewQueue() {
  const book = SpreadsheetApp.getActiveSpreadsheet();
  const log = book.getSheetByName('AI_CHANGE_IMPACT_LOG');
  const cases = book.getSheetByName('AI_CHANGE_CASES');
  if (!log || !cases) throw new Error('REVIEW_SHEET_NOT_FOUND');

  const pendingChanges = readObjects(log)
    .filter((row) => row.status !== 'VERIFIED');
  const pendingCases = readObjects(cases)
    .filter((row) => row.review_status !== 'VERIFIED');

  return {
    generatedAt: new Date().toISOString(),
    changeIds: pendingChanges.map((row) => row.change_id),
    caseIds: pendingCases.map((row) => row.case_id),
    requiresHumanReview: pendingChanges.length > 0 || pendingCases.length > 0,
  };
}

readObjects は1行目をキーにして行をオブジェクトへ変換する自社関数を想定しています。ログや戻り値へ問い合わせ本文、氏名、連絡先、認証情報、APIキー、AIレスポンス全文を入れないでください。

ローカルで確認する5ケース

本番のシートへ顧客情報を書き込まず、固定値の配列で少なくとも次を検証します。

  1. 新しい change_id が OPEN として一度だけ登録される
  2. 同じ change_id の再実行が DUPLICATE_CHANGE_ID になる
  3. missing_context の境界ケースが未確認キューへ残る
  4. source_conflict が BLOCKED になり、反映済みにならない
  5. external_send_rule が含まれる変更を人間確認へ戻せる

テストが通っただけで、実際の変更を本番へ反映してよいとは限りません。確認者、代理担当、正本の版、反映後の再確認日を記録します。

反映前チェックリスト

  • 変更IDと変更前後の正本参照を記録した
  • 影響先を入力・AI処理・人間確認・出力・記録に分けた
  • 通常・境界・停止の3ケースを用意した
  • 実データや秘密情報をテストへ複製していない
  • 未登録の理由コードを BLOCKED にした
  • 停止条件を通過した場合の戻し先を決めた
  • 外部送信、CRM更新、FAQ公開を自動確定にしていない
  • 変更の確認者と代理担当を記録した
  • 反映後の再確認日と正本の更新先を記録した

AIに任せること、人が確定すること

AIには、変更記録から影響先候補を列挙すること、ケースごとの差分を要約すること、未確認行をグループ化することを任せられます。

一方、次は人が確定します。

  • 変更を本番相当の業務へ反映するか
  • 正本として採用する資料と版
  • 個人情報・機密情報を扱う範囲
  • 停止条件を解除する条件
  • 顧客への返信、外部送信、公開の最終可否

まとめ

変更影響マップは、変更したファイルの一覧ではなく、変更が入力・AI処理・人間確認・出力・記録へどのように届くかを追うための運用台帳です。

まずは直近の変更を1件選び、5つの影響先、3つの確認ケース、1つの停止条件を記録してください。変更前に「止める人」と「戻る正本」を言えるようにしておくと、担当者が変わった後も確認の起点を失いにくくなります。

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?