AIエージェントや自動返信を入れる前に、まず業務フローを「人間が確認できる設定」として残すための実装メモです。
ここでは、問い合わせ対応を例にして、YAMLでフロー定義を書き、Googleスプレッドシートで運用し、Google Apps Scriptで不足や危険な自動化範囲を点検します。
作るもの
次の3つを作ります。
| 作るもの | 目的 |
|---|---|
workflow.yml |
業務ステップ、人間確認、AI利用可否を定義する |
Workflow シート |
現場で確認できる一覧にする |
| GASチェック | 承認者なし、例外条件なし、AI任せにしすぎた行を検出する |
この記事で扱うのは、AI APIの呼び出しではありません。
AIに何を任せるかを決める前に、どの業務ステップで止めるか、誰が確認するか、どの情報をAIに渡さないかを固定するための下準備です。
workflow.yml
まず、業務フローをYAMLで定義します。
version: 1
workflow_name: inquiry_reply_before_agent
steps:
- step_id: intake
name: 問い合わせ受付
owner: cs
ai_allowed: false
human_review_required: true
review_owner: cs_lead
input_data:
- channel
- inquiry_summary
- customer_type
blocked_data:
- raw_email_body
- phone_number
- contract_file
- step_id: classify
name: 問い合わせ分類
owner: cs
ai_allowed: true
human_review_required: true
review_owner: cs_lead
allowed_ai_input:
- masked_summary
- category_candidates
exception_when:
- includes_personal_data
- includes_price_or_contract
- complaint_or_legal_risk
- step_id: draft_reply
name: 返信下書き
owner: cs
ai_allowed: true
human_review_required: true
review_owner: business_owner
allowed_ai_input:
- masked_summary
- public_faq
- service_scope
exception_when:
- customer_visible_output
- claim_about_result
- refund_or_contract
- step_id: send
name: 送信
owner: cs
ai_allowed: false
human_review_required: true
review_owner: business_owner
exception_when:
- always
ポイントは、ai_allowed と human_review_required を別の項目にすることです。
AIを使ってよいステップでも、外部送信や契約に触れる内容は人間確認を残します。
Workflowシート
スプレッドシート側では、次の列を用意します。
step_id
name
owner
ai_allowed
human_review_required
review_owner
allowed_ai_input
blocked_data
exception_when
status
note
YAMLをそのまま読む実装にしてもよいですが、最初は手入力で十分です。
重要なのは、AIエージェントを作る前に、業務ステップごとの確認ルールを1枚の表で見られることです。
GASで危険な行を検出する
次のGASは、Workflow シートを読み、最低限のルール違反を検出します。
const SHEET_NAME = 'Workflow';
function checkWorkflowMap() {
const sheet = SpreadsheetApp.getActive().getSheetByName(SHEET_NAME);
if (!sheet) throw new Error(`missing sheet: ${SHEET_NAME}`);
const values = sheet.getDataRange().getValues();
const headers = values.shift();
const rows = values.map((row, index) => toRecord(headers, row, index + 2));
const errors = [];
for (const row of rows) {
if (!row.step_id) errors.push(`${row.rowNumber}: step_id is required`);
if (!row.owner) errors.push(`${row.rowNumber}: owner is required`);
const aiAllowed = String(row.ai_allowed).toLowerCase() === 'true';
const reviewRequired = String(row.human_review_required).toLowerCase() === 'true';
if (aiAllowed && !row.allowed_ai_input) {
errors.push(`${row.rowNumber}: ai_allowed=true requires allowed_ai_input`);
}
if (reviewRequired && !row.review_owner) {
errors.push(`${row.rowNumber}: human_review_required=true requires review_owner`);
}
if (aiAllowed && !row.exception_when) {
errors.push(`${row.rowNumber}: ai_allowed=true requires exception_when`);
}
if (String(row.name).match(/送信|公開|契約|返金/) && aiAllowed) {
errors.push(`${row.rowNumber}: customer-visible or contract step must not be ai_allowed`);
}
}
const resultSheet = getOrCreateSheet_('WorkflowCheck');
resultSheet.clear();
resultSheet.getRange(1, 1, 1, 2).setValues([['status', 'message']]);
if (errors.length === 0) {
resultSheet.getRange(2, 1, 1, 2).setValues([['green', 'workflow check passed']]);
return;
}
resultSheet.getRange(2, 1, errors.length, 2).setValues(
errors.map((message) => ['red', message])
);
}
function toRecord(headers, row, rowNumber) {
return headers.reduce((record, header, index) => {
record[String(header).trim()] = row[index];
record.rowNumber = rowNumber;
return record;
}, {});
}
function getOrCreateSheet_(name) {
const ss = SpreadsheetApp.getActive();
return ss.getSheetByName(name) || ss.insertSheet(name);
}
このチェックは完璧な監査ではありません。
ただ、AIエージェント導入前の「危ない見落とし」を早めに見つけるには十分です。
検出したい状態
最初に検出したいのは、次の状態です。
| 状態 | なぜ危ないか |
|---|---|
ai_allowed=true なのに allowed_ai_input が空 |
AIへ渡す情報の境界がない |
human_review_required=true なのに review_owner が空 |
誰が止めるか分からない |
exception_when が空 |
例外ケースで止められない |
送信、公開、契約、返金ステップが ai_allowed=true
|
外部影響がある判断までAI任せになる |
blocked_data が空 |
渡してはいけない情報を決めていない |
AIエージェントを作る時は、うまく動く通常ケースに目が向きます。
しかし実務で止まりやすいのは、例外ケース、情報不足、人間確認、送信前確認です。
シートにメニューを追加する
運用担当者が実行しやすいよう、メニューを追加します。
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('AI運用チェック')
.addItem('業務フローを点検', 'checkWorkflowMap')
.addToUi();
}
これで、スプレッドシートのメニューからチェックを実行できます。
判断ログへつなげる
チェックで赤になった行は、ただ直して終わりにしない方がよいです。
次の列を持つ DecisionLog シートへ残します。
decision_id
checked_at
step_id
issue_type
decision
reason
owner
next_action
例です。
decision_id,checked_at,step_id,issue_type,decision,reason,owner,next_action
DEC-20260704-001,2026-07-04,draft_reply,missing_exception,hold,返金相談を例外に入れていなかった,cs_lead,exception_whenにrefund_or_contractを追加
DEC-20260704-002,2026-07-04,send,ai_allowed_customer_visible,reject,送信は人間確認を必須にする,business_owner,ai_allowedをfalseに変更
AIエージェント導入の準備では、設定ファイルそのものより、なぜそのルールにしたかを残すことが大切です。
後から担当者が変わっても、判断理由を追えるからです。
AIに任せない範囲
この構成では、次の作業はAIに任せません。
- 顧客への最終送信
- 契約、返金、請求、法務に近い判断
- 個人情報を含む原文の扱い
- 公開前の成果保証表現の判断
- 例外ケースの最終承認
AIは、分類候補、要約、FAQ候補、返信下書きのたたき台に使います。
最終判断と外部送信は、人間が確認する前提にします。
まとめ
AIエージェントを作る前に、業務フローを設定として見える化しておくと、実装後の事故を減らせます。
- ステップごとに
ai_allowedを決める - 人間確認が必要なステップに
review_ownerを置く - 例外条件を
exception_whenに固定する - GASで危険な行を検出する
- 判断ログに「なぜ止めたか」を残す
Miraigentでは、AI導入相談でも、ツール選定より先に業務フロー、人間確認、送ってはいけない情報、判断ログの有無を確認します。
