生成AIを業務に入れる時、最初から大きな管理画面を作る必要はありません。
ただし、AIを「誰が、何に、どの判断で使ったか」が残らないまま運用を始めると、あとから改善も説明も難しくなります。
この記事では、小さな会社でも始めやすい形として、GoogleスプレッドシートとGASで AI活用ログ を作る最小実装を紹介します。AI APIの呼び出しや自動送信ではなく、AIを使う前後の記録を残すための土台です。
作るもの
スプレッドシートに ai_usage_log と weekly_summary を用意し、Apps Scriptで次を実装します。
- AIを使った業務、入力種別、出力種別を記録する
- 個人情報や契約・返金などの注意フラグを残す
- 人間確認が必要なケースを自動で
要確認にする - 週次で用途別の件数と要確認件数を集計する
- 改善対象をFAQ、フォーム、CRM、承認ルールへ戻す
完成形は、次のような流れです。
問い合わせ要約 / FAQ候補 / 返信下書き / 社内メモ整理
↓
AIを使う前後に ai_usage_log へ記録
↓
注意フラグと人間確認の要否を付ける
↓
週次で集計し、FAQ・フォーム・CRM・承認ルールを直す
なぜAI活用ログが必要か
AI活用ログは、監視のためだけの表ではありません。
小さな会社では、AI利用がチャットや個人のブラウザ上で始まりやすく、次の情報が残らないことがあります。
- どの業務でAIを使ったか
- どの情報をAIへ渡したか
- 出力をそのまま使ったのか、人間が直したのか
- なぜ人間確認に戻したのか
- 次にFAQやフォームへ反映すべき改善点は何か
この記録がないと、「AIで何が楽になったか」も「どこが危ないか」も判断しにくくなります。
最初に作るべきなのは、AIの成果を大きく見せるダッシュボードではなく、現場が毎回同じ粒度で残せるログです。
ai_usage_log の列
まず、ai_usage_log というシートを作ります。
| 列名 | 例 | 用途 |
|---|---|---|
| log_id | AILOG-20260627-001 | ログID |
| used_at | 2026/06/27 10:30 | AIを使った時刻 |
| requester | sales_member | 依頼者または利用者 |
| task_type | inquiry_summary | 用途 |
| input_type | inquiry_text | AIへ渡した情報の種類 |
| output_type | reply_draft | AIの出力種別 |
| ai_tool | ChatGPT / Gemini / Claude | 利用ツール |
| data_level | masked / internal / blocked | 情報の扱い |
| risk_flags | personal_data, contract | 注意点 |
| human_review_required | TRUE | 人間確認が必要か |
| review_status | 未確認 / 確認済み / 差し戻し | 確認状態 |
| improvement_target | faq / form / crm / approval_rule | 改善先 |
| note | 料金表現を責任者確認へ | 判断メモ |
prompt や customer_name をそのまま残す列は作りません。
ログに必要なのは、個人情報や機密情報そのものではなく、業務判断として後から見返せる分類です。
セットアップ用GAS
次のコードをスプレッドシートに紐づくApps Scriptへ貼り付けます。
const SHEETS = {
log: 'ai_usage_log',
summary: 'weekly_summary',
};
const LOG_HEADERS = [
'log_id',
'used_at',
'requester',
'task_type',
'input_type',
'output_type',
'ai_tool',
'data_level',
'risk_flags',
'human_review_required',
'review_status',
'improvement_target',
'note',
];
const SUMMARY_HEADERS = [
'week_start',
'task_type',
'total_count',
'review_required_count',
'blocked_count',
'main_improvement_target',
];
function setupAiUsageLog() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
ensureSheet_(ss, SHEETS.log, LOG_HEADERS);
ensureSheet_(ss, SHEETS.summary, SUMMARY_HEADERS);
}
function ensureSheet_(ss, name, headers) {
const sheet = ss.getSheetByName(name) || ss.insertSheet(name);
const current = sheet.getRange(1, 1, 1, headers.length).getValues()[0];
const isEmpty = current.every((value) => value === '');
if (isEmpty) {
sheet.getRange(1, 1, 1, headers.length).setValues([headers]);
sheet.setFrozenRows(1);
}
}
ログを追加する関数
次に、AI利用の記録を追加する関数を作ります。
function addAiUsageLog(entry) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName(SHEETS.log);
if (!sheet) throw new Error('setupAiUsageLog() を先に実行してください');
const taskType = normalizeTaskType_(entry.taskType);
const riskFlags = detectRiskFlags_(entry);
const dataLevel = decideDataLevel_(riskFlags, entry.dataLevel);
const humanReviewRequired = shouldReview_(taskType, riskFlags, dataLevel);
sheet.appendRow([
createLogId_(),
entry.usedAt || new Date(),
entry.requester || 'unknown',
taskType,
entry.inputType || 'unknown',
entry.outputType || 'unknown',
entry.aiTool || 'unknown',
dataLevel,
riskFlags.join(','),
humanReviewRequired,
'未確認',
decideImprovementTarget_(taskType, riskFlags),
entry.note || '',
]);
}
function normalizeTaskType_(value) {
const text = String(value || '').toLowerCase();
if (/inquiry|問い合わせ|相談/.test(text)) return 'inquiry_summary';
if (/reply|返信|下書き/.test(text)) return 'reply_draft';
if (/faq|よくある/.test(text)) return 'faq_candidate';
if (/crm|営業|顧客/.test(text)) return 'crm_note';
if (/article|sns|投稿|記事/.test(text)) return 'content_draft';
return 'other';
}
function detectRiskFlags_(entry) {
const text = [
entry.inputType,
entry.outputType,
entry.note,
entry.sampleText,
].map((value) => String(value || '')).join('\n');
const flags = [];
if (/住所|電話番号|メールアドレス|個人情報|本人確認/.test(text)) {
flags.push('personal_data');
}
if (/契約|返金|解約|請求|支払い|料金/.test(text)) {
flags.push('contract_or_money');
}
if (/パスワード|APIキー|Cookie|トークン|認証/.test(text)) {
flags.push('secret_or_auth');
}
if (/クレーム|苦情|炎上|法務|税務|医療/.test(text)) {
flags.push('sensitive_judgment');
}
return flags;
}
function decideDataLevel_(riskFlags, requestedLevel) {
if (riskFlags.includes('secret_or_auth')) return 'blocked';
if (riskFlags.includes('personal_data')) return 'masked';
if (requestedLevel) return requestedLevel;
return 'internal';
}
function shouldReview_(taskType, riskFlags, dataLevel) {
if (dataLevel === 'blocked') return true;
if (taskType === 'reply_draft' || taskType === 'content_draft') return true;
if (riskFlags.length > 0) return true;
return false;
}
function decideImprovementTarget_(taskType, riskFlags) {
if (riskFlags.includes('secret_or_auth')) return 'approval_rule';
if (riskFlags.includes('personal_data')) return 'form';
if (taskType === 'faq_candidate') return 'faq';
if (taskType === 'crm_note') return 'crm';
if (taskType === 'reply_draft') return 'approval_rule';
return 'none';
}
function createLogId_() {
const now = new Date();
const ymd = Utilities.formatDate(now, 'Asia/Tokyo', 'yyyyMMdd');
const suffix = Utilities.getUuid().slice(0, 8).toUpperCase();
return `AILOG-${ymd}-${suffix}`;
}
動作確認
Apps Scriptのエディタで setupAiUsageLog() を一度実行してから、次のテスト関数を実行します。
function testAddAiUsageLog() {
addAiUsageLog({
requester: 'cs_member',
taskType: '問い合わせ要約',
inputType: '問い合わせ本文',
outputType: '要約',
aiTool: 'ChatGPT',
dataLevel: 'masked',
sampleText: '料金について相談したい。電話番号はマスク済み。',
note: '料金に触れるため確認へ',
});
addAiUsageLog({
requester: 'sales_member',
taskType: 'FAQ候補',
inputType: '問い合わせ分類',
outputType: 'FAQ案',
aiTool: 'Gemini',
sampleText: '導入までの流れに関する質問',
note: 'FAQ化候補',
});
}
1件目は contract_or_money が付き、人間確認が必要になります。2件目はFAQ改善へ回すログになります。
週次集計を作る
ログが溜まったら、用途別に件数を集計します。
function buildWeeklySummary() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const logSheet = ss.getSheetByName(SHEETS.log);
const summarySheet = ss.getSheetByName(SHEETS.summary);
if (!logSheet || !summarySheet) {
throw new Error('setupAiUsageLog() を先に実行してください');
}
const values = logSheet.getDataRange().getValues();
const headers = values.shift();
const col = buildColumnMap_(headers);
const groups = {};
values.forEach((row) => {
const usedAt = row[col.used_at];
if (!usedAt) return;
const weekStart = formatWeekStart_(new Date(usedAt));
const taskType = String(row[col.task_type] || 'unknown');
const key = `${weekStart}__${taskType}`;
if (!groups[key]) {
groups[key] = {
weekStart,
taskType,
total: 0,
review: 0,
blocked: 0,
targets: {},
};
}
groups[key].total += 1;
if (row[col.human_review_required] === true || row[col.human_review_required] === 'TRUE') {
groups[key].review += 1;
}
if (String(row[col.data_level]) === 'blocked') {
groups[key].blocked += 1;
}
const target = String(row[col.improvement_target] || 'none');
groups[key].targets[target] = (groups[key].targets[target] || 0) + 1;
});
const rows = Object.values(groups).map((group) => [
group.weekStart,
group.taskType,
group.total,
group.review,
group.blocked,
mostFrequentKey_(group.targets),
]);
summarySheet.clearContents();
summarySheet.getRange(1, 1, 1, SUMMARY_HEADERS.length).setValues([SUMMARY_HEADERS]);
if (rows.length > 0) {
summarySheet.getRange(2, 1, rows.length, SUMMARY_HEADERS.length).setValues(rows);
}
}
function buildColumnMap_(headers) {
return Object.fromEntries(headers.map((header, index) => [String(header), index]));
}
function formatWeekStart_(date) {
const copied = new Date(date);
const day = copied.getDay();
const diff = day === 0 ? -6 : 1 - day;
copied.setDate(copied.getDate() + diff);
return Utilities.formatDate(copied, 'Asia/Tokyo', 'yyyy-MM-dd');
}
function mostFrequentKey_(counts) {
return Object.entries(counts)
.sort((a, b) => b[1] - a[1])
.map(([key]) => key)[0] || 'none';
}
週次で見るポイント
週次集計では、件数の多さだけを見ません。
次の3つを見ると、AI活用を改善へつなげやすくなります。
-
review_required_countが多い用途: 承認ルールやテンプレートが足りない -
blocked_countが多い用途: AIへ渡す前のフォームやマスキングを見直す -
main_improvement_targetが偏る用途: FAQ、CRM、フォームのどこを直すべきか分かる
AI活用ログは「AIを何回使ったか」を競うための表ではありません。
止まった理由を次の運用改善へ戻すための表です。
運用ルール
最小運用では、次のルールだけでも始められます。
- 顧客へ送る返信下書きは必ず人間確認にする
- 個人情報や認証情報を含む場合は、AIへ送る前に止める
- 料金、契約、返金に触れる場合は責任者確認にする
- AI出力を外部公開する場合は、事実確認済みにする
- 週1回、
weekly_summaryを見て改善先を1つだけ決める
大切なのは、ログを細かくしすぎないことです。
最初から20列以上にすると、入力されなくなります。まずは、用途、注意フラグ、人間確認、改善先だけを残します。
まとめ
AI活用ログを作ると、AI導入は「便利だった」で終わらなくなります。
- 何に使ったか
- どこで止めたか
- 何を人間が確認したか
- 次にどの運用を直すか
この4つが残ると、問い合わせ対応、FAQ整備、CRM改善、承認ルールの見直しへつなげやすくなります。
Miraigentでは、AIツールの導入前に、こうした活用ログ、例外ケース、人間確認ルールを先に整理することを重視しています。小さく始めるなら、まず1枚のスプレッドシートで「AIを使った記録」を残すところからで十分です。