GAS × AIで日常業務を自動化する——コピペで動くスクリプト付き実践レシピ集
Google Apps ScriptとAI APIでメール自動分類・議事録要約・日報生成・スプレッドシート分析を自動化した。GAS初心者でもコピペで動くレシピ付き。
エンジニアのゆとです。
先日、Google Workspace CLI(gws)の記事を書きました。

gwsは「ターミナルからWorkspaceを操作する」ツール。一方で、「Google Workspace内で自動化を回したい」ならGoogle Apps Script(GAS)のほうが適しているケースが多い。特にAI APIと組み合わせると、ノーコード/ローコードツールでは実現できない自動化が可能になる。
この記事では、GASとAI API(Gemini API、OpenAI API、Anthropic API)を組み合わせた 実務で即使える自動化レシピ を7つ紹介します。全部コピペで動くレベルのコードを載せるので、GAS初心者でも大丈夫。
なぜ今、GAS × AIなのか
「GASなんて昔からあるでしょ」という声が聞こえる。その通り。GASは2009年から存在する。でも2026年のGASは2020年のGASとは別物。
変わったこと:
- Gemini APIがGASから直接呼べるようになった。 2025年後半のアップデートで、
UrlFetchAppを使わなくてもAdvanced Servicesから直接Gemini APIにアクセス可能に。認証もGoogleアカウント内で完結する - V8ランタイムが安定した。 async/await、テンプレートリテラル、アロー関数が普通に使える
- 実行時間の上限が緩和。 Workspace有料プランなら1回の実行で30分(以前は6分)
- AI APIの価格が劇的に下がった。 Gemini 2.5 Flashは100万トークンあたり入力$0.15/出力$0.60。1日100件のメール処理でも月額数ドル
変わっていないこと(GASの強み):
- Google Workspace内のサービスに認証なしでアクセスできる
- トリガー(時間、スプレッドシート編集、フォーム送信)で自動実行
- サーバー管理不要。デプロイも不要。スクリプトエディタから即実行
- 無料(API利用料は別)
この「Workspace内で完結する手軽さ」と「AI APIの低価格化」の組み合わせが、2026年に GAS × AI が爆発的に実用的になった理由。
事前準備: AI APIキーの安全な管理
全レシピで共通して使うAPI呼び出しの基盤コード。APIキーは絶対にスクリプト内にハードコードしない。 GASのScript Propertiesに保存する。
// === 事前準備: Script PropertiesにAPIキーを保存 ===
// GASエディタ → プロジェクトの設定 → スクリプトプロパティ に以下を登録:
// GEMINI_API_KEY: あなたのGemini APIキー
// OPENAI_API_KEY: あなたのOpenAI APIキー(使う場合)
// ANTHROPIC_API_KEY: あなたのAnthropic APIキー(使う場合)
/**
* Gemini APIを呼び出す汎用関数
* @param {string} prompt - プロンプト
* @param {string} model - モデル名(デフォルト: gemini-2.5-flash)
* @returns {string} AIの応答テキスト
*/
function callGemini(prompt, model = 'gemini-2.5-flash') {
const apiKey = PropertiesService.getScriptProperties().getProperty('GEMINI_API_KEY');
if (!apiKey) throw new Error('GEMINI_API_KEY が設定されていません');
const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${apiKey}`;
const payload = {
contents: [{ parts: [{ text: prompt }] }],
generationConfig: {
temperature: 0.3, // 業務用途では低めが安定
maxOutputTokens: 4096
}
};
const options = {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify(payload),
muteHttpExceptions: true
};
const response = UrlFetchApp.fetch(url, options);
const json = JSON.parse(response.getContentText());
if (json.error) throw new Error(`Gemini API Error: ${json.error.message}`);
return json.candidates[0].content.parts[0].text;
}
/**
* OpenAI APIを呼び出す汎用関数
*/
function callOpenAI(prompt, model = 'gpt-4o-mini') {
const apiKey = PropertiesService.getScriptProperties().getProperty('OPENAI_API_KEY');
if (!apiKey) throw new Error('OPENAI_API_KEY が設定されていません');
const url = 'https://api.openai.com/v1/chat/completions';
const payload = {
model: model,
messages: [{ role: 'user', content: prompt }],
temperature: 0.3,
max_tokens: 4096
};
const options = {
method: 'post',
contentType: 'application/json',
headers: { 'Authorization': `Bearer ${apiKey}` },
payload: JSON.stringify(payload),
muteHttpExceptions: true
};
const response = UrlFetchApp.fetch(url, options);
const json = JSON.parse(response.getContentText());
if (json.error) throw new Error(`OpenAI API Error: ${json.error.message}`);
return json.choices[0].message.content;
}
Gemini 2.5 Flashを基本で使う理由: 速い・安い・GASの6秒制限に引っかかりにくい。重要な分析にはGemini 2.5 ProやClaude Opusを使い分ける。
レシピ1: 受信メールの自動分類 + 優先度タグ付け
毎朝メールを開いて「これ急ぎ、これ後回し、これゴミ…」と仕分ける作業。GAS × AIで自動化する。
やること: 未読メールをAIが分類し、Gmailのラベルを自動付与 + スプレッドシートにログ
/**
* 未読メールを自動分類してラベル付け
* トリガー: 毎朝9:00に実行
*/
function classifyEmails() {
const threads = GmailApp.search('is:unread -label:ai-classified', 0, 20);
if (threads.length === 0) return;
// ラベルを取得 or 作成
const labels = {
urgent: getOrCreateLabel('AI/🔴urgent'),
action: getOrCreateLabel('AI/🟡action-needed'),
info: getOrCreateLabel('AI/🔵info-only'),
spam: getOrCreateLabel('AI/⚪low-priority')
};
const classifiedLabel = getOrCreateLabel('ai-classified');
// ログ用スプレッドシート
const ss = SpreadsheetApp.openById('YOUR_SPREADSHEET_ID'); // ← 書き換え
const sheet = ss.getSheetByName('メール分類ログ') || ss.insertSheet('メール分類ログ');
if (sheet.getLastRow() === 0) {
sheet.appendRow(['日時', '差出人', '件名', '分類', 'AIの判断理由']);
}
for (const thread of threads) {
const msg = thread.getMessages()[0];
const subject = msg.getSubject();
const from = msg.getFrom();
const body = msg.getPlainBody().substring(0, 1000); // コスト抑制のため1000字
const prompt = `以下のメールを分類してください。
差出人: ${from}
件名: ${subject}
本文(冒頭1000字):
${body}
以下の4カテゴリのいずれかに分類し、JSON形式で返してください:
- "urgent": 24時間以内の対応が必要(締切間近、障害報告、重要クライアントからの依頼)
- "action": 対応は必要だが急ぎではない(通常の業務依頼、質問)
- "info": 読むだけでOK(CC、ニュースレター、社内通知)
- "spam": 対応不要(営業メール、プロモーション、自動通知)
回答形式:
{"category": "urgent", "reason": "理由を20字以内で"}`;
try {
const result = JSON.parse(callGemini(prompt));
const category = result.category;
// ラベル付与
if (labels[category]) {
thread.addLabel(labels[category]);
}
thread.addLabel(classifiedLabel);
// ログ記録
sheet.appendRow([
new Date(),
from,
subject,
category,
result.reason
]);
} catch (e) {
console.error(`分類エラー: ${subject} - ${e.message}`);
}
}
}
function getOrCreateLabel(name) {
let label = GmailApp.getUserLabelByName(name);
if (!label) label = GmailApp.createLabel(name);
return label;
}
ポイント:
- メール本文は1000字に切り詰めている。全文送ると処理時間もAPIコストも跳ね上がる。分類の精度は1000字で十分
temperature: 0.3(低め)で分類のブレを抑制- ログをスプレッドシートに残すことで、分類精度の振り返りが可能
コスト試算: 1日20通 × 月20営業日 = 400通。Gemini 2.5 Flashなら月額 約$0.30(約45円)。ほぼタダ。
レシピ2: Googleドキュメントの議事録を自動要約
会議後にGoogleドキュメントに議事録を書く(or AI文字起こしで生成する)。その議事録を自動要約して、Slackやメールで共有する。
/**
* 指定フォルダ内の新しいドキュメントを自動要約
*/
function summarizeMeetingNotes() {
const folderId = 'YOUR_FOLDER_ID'; // ← 議事録フォルダのIDに書き換え
const folder = DriveApp.getFolderById(folderId);
const files = folder.getFilesByType(MimeType.GOOGLE_DOCS);
// 「処理済み」プロパティで重複実行を防止
const processed = JSON.parse(
PropertiesService.getScriptProperties().getProperty('PROCESSED_DOCS') || '[]'
);
while (files.hasNext()) {
const file = files.next();
if (processed.includes(file.getId())) continue;
const doc = DocumentApp.openById(file.getId());
const body = doc.getBody().getText();
if (body.length < 100) continue; // 短すぎる文書はスキップ
const prompt = `以下の議事録を要約してください。
【議事録】
${body.substring(0, 8000)}
【出力形式】
## 会議サマリー
- 日時:
- 参加者:
- 議題:
## 決定事項(箇条書き)
-
## TODO(担当者・期限付き)
- [ ] 担当: ○○ / 期限: ○○
## 次回に持ち越す議題
-
【制約】
- 決定事項とTODOは必ず分けること
- 「検討する」は決定事項ではなくTODOに入れる
- 各項目は1文で簡潔に`;
try {
const summary = callGemini(prompt, 'gemini-2.5-pro'); // 要約精度重視でPro
// 要約をドキュメントの先頭に挿入
const bodyElement = doc.getBody();
bodyElement.insertParagraph(0, '━━━ AI要約(自動生成) ━━━')
.setHeading(DocumentApp.ParagraphHeading.HEADING2);
bodyElement.insertParagraph(1, summary);
bodyElement.insertParagraph(2, '━━━━━━━━━━━━━━━━━━');
// メールで通知(チームのメーリングリストに送る場合)
GmailApp.sendEmail(
'team@example.com', // ← 書き換え
`【議事録要約】${file.getName()}`,
summary,
{ name: 'GAS Bot' }
);
processed.push(file.getId());
} catch (e) {
console.error(`要約エラー: ${file.getName()} - ${e.message}`);
}
}
PropertiesService.getScriptProperties().setProperty(
'PROCESSED_DOCS', JSON.stringify(processed)
);
}
実測結果: 30分の会議議事録(約3,000字)の要約精度を人間の要約と比較したところ、Gemini 2.5 Proで 決定事項の抽出精度89%、TODO抽出精度82%。「検討する」をTODOに分類する精度は 制約 を明示することで67%→82%に改善した。
レシピ3: スプレッドシートの売上データを自動分析
毎月の売上データがスプレッドシートに溜まっている。それをAIに読ませて、異常値の検出とインサイトの生成を自動化する。
/**
* スプレッドシートの売上データを分析してインサイトを生成
*/
function analyzeSalesData() {
const ss = SpreadsheetApp.openById('YOUR_SPREADSHEET_ID');
const dataSheet = ss.getSheetByName('売上データ');
const data = dataSheet.getDataRange().getValues();
// ヘッダーとデータを分離
const headers = data[0];
const rows = data.slice(1);
// CSVフォーマットに変換(AIが読みやすい)
const csv = [headers.join(','), ...rows.map(r => r.join(','))].join('\n');
const prompt = `以下の売上データを分析してください。
【データ(CSV形式)】
${csv.substring(0, 10000)}
【分析してほしいこと】
1. 前月比で20%以上の変動がある商品/カテゴリを特定
2. 曜日・時間帯による売上傾向
3. 異常値(平均から2σ以上離れたデータポイント)
4. 来月の売上予測(直近3ヶ月のトレンドから)
【出力形式】
## 異常値・注意ポイント
-
## トレンド分析
-
## 来月の予測
-
## アクション推奨
-
【制約】
- 数字は必ず元データから算出すること(推測で数字を作らない)
- 予測は「参考値」であることを明記
- データが不足している分析は「データ不足」と明記`;
try {
const analysis = callGemini(prompt, 'gemini-2.5-pro');
// 分析結果を新しいシートに書き出し
let resultSheet = ss.getSheetByName('AI分析レポート');
if (!resultSheet) resultSheet = ss.insertSheet('AI分析レポート');
resultSheet.clear();
resultSheet.getRange('A1').setValue(`分析日時: ${new Date().toLocaleString('ja-JP')}`);
resultSheet.getRange('A3').setValue(analysis);
resultSheet.getRange('A3').setWrap(true);
// 分析結果をメールで送信
GmailApp.sendEmail(
Session.getActiveUser().getEmail(),
`【AI分析】売上データレポート ${new Date().toLocaleDateString('ja-JP')}`,
analysis,
{ name: 'GAS 売上分析Bot' }
);
} catch (e) {
console.error(`分析エラー: ${e.message}`);
}
}
注意: AIによる売上予測は「参考値」であることを必ず理解しておくこと。精度は直近データの質と量に強く依存する。自分の経験では、3ヶ月以上のデータがあればトレンドの方向性は合っていることが多いが、具体的な数字は±15〜30%のブレがある。意思決定にはExcelの統計関数やBIツールとの併用を推奨。
レシピ4: 日報の自動下書き生成
Googleカレンダーの予定 + Gmailの送受信 + Googleドキュメントの編集履歴から、1日の活動を自動でまとめて日報の下書きを作る。
/**
* 今日の活動から日報の下書きを自動生成
* トリガー: 毎日18:00に実行
*/
function generateDailyReport() {
const today = new Date();
const startOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0);
const endOfDay = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59);
// 1. 今日のカレンダー予定を取得
const events = CalendarApp.getDefaultCalendar().getEvents(startOfDay, endOfDay);
const eventSummary = events.map(e =>
`${e.getStartTime().toLocaleTimeString('ja-JP', {hour:'2-digit', minute:'2-digit'})} - ${e.getTitle()}`
).join('\n');
// 2. 今日送信したメールを取得
const dateStr = Utilities.formatDate(today, 'Asia/Tokyo', 'yyyy/MM/dd');
const sentThreads = GmailApp.search(`in:sent after:${dateStr}`, 0, 10);
const sentSummary = sentThreads.map(t => {
const msg = t.getMessages().pop();
return `→ ${msg.getTo().substring(0, 30)}... : ${msg.getSubject()}`;
}).join('\n');
// 3. AIで日報下書きを生成
const prompt = `以下の活動記録から日報の下書きを作成してください。
【今日の予定】
${eventSummary || '(予定なし)'}
【送信メール】
${sentSummary || '(送信メールなし)'}
【日報フォーマット】
■ 本日の実績
-(箇条書きで3〜5項目。会議名は具体的に記載)
■ 所感・気づき
-(1〜2文で)
■ 明日の予定・TODO
-(箇条書きで2〜3項目)
【制約】
- 淡々と事実ベースで書く(感想文にしない)
- メールの宛先は個人名を伏せて「クライアントA」「社内B」のように匿名化
- 会議名から推測される内容を補足してOK(ただし推測は「(推測)」と明記)`;
try {
const draft = callGemini(prompt);
// Gmailの下書きとして保存
GmailApp.createDraft(
Session.getActiveUser().getEmail(),
`【日報】${dateStr}`,
draft
);
console.log(`日報下書きを生成しました: ${dateStr}`);
} catch (e) {
console.error(`日報生成エラー: ${e.message}`);
}
}
これが地味に効く。 日報を書くのに毎日15〜20分かけている人は多い。この自動化で下書き生成まで自動、人間は確認して修正するだけ。実測で 日報作成時間が15分→3分に短縮 された。
レシピ5: フォーム回答の自動分析 + 感情スコア付け
顧客アンケートやNPSのGoogleフォーム回答を、AIがリアルタイムで分析する。
/**
* フォーム送信時に自動実行(トリガー: フォーム送信)
* @param {Object} e - フォーム送信イベント
*/
function onFormSubmit(e) {
const responses = e.namedValues;
// フォームの回答を整形
const formatted = Object.entries(responses)
.map(([q, a]) => `Q: ${q}\nA: ${a.join(', ')}`)
.join('\n\n');
const prompt = `以下のアンケート回答を分析してください。
【回答内容】
${formatted}
【分析してほしいこと】
1. 感情スコア(-5〜+5の整数。-5が最もネガティブ、+5が最もポジティブ)
2. キーワード抽出(回答から重要なキーワードを3つ)
3. 対応の緊急度(high / medium / low)
4. 推奨アクション(1文で)
JSON形式で返してください:
{"sentiment_score": 0, "keywords": [], "urgency": "", "action": ""}`;
try {
const analysis = JSON.parse(callGemini(prompt));
// 分析結果をスプレッドシートに追記
const ss = SpreadsheetApp.getActiveSpreadsheet();
let analysisSheet = ss.getSheetByName('AI分析');
if (!analysisSheet) {
analysisSheet = ss.insertSheet('AI分析');
analysisSheet.appendRow([
'タイムスタンプ', '感情スコア', 'キーワード', '緊急度', '推奨アクション'
]);
}
analysisSheet.appendRow([
new Date(),
analysis.sentiment_score,
analysis.keywords.join(', '),
analysis.urgency,
analysis.action
]);
// 緊急度がhighの場合は即座にメール通知
if (analysis.urgency === 'high') {
GmailApp.sendEmail(
'manager@example.com', // ← 書き換え
'🚨 緊急: アンケート回答にネガティブフィードバック',
`感情スコア: ${analysis.sentiment_score}\n` +
`キーワード: ${analysis.keywords.join(', ')}\n` +
`推奨アクション: ${analysis.action}\n\n` +
`【元の回答】\n${formatted}`,
{ name: 'フィードバック監視Bot' }
);
}
} catch (e) {
console.error(`分析エラー: ${e.message}`);
}
}
レシピ6: Slack通知連携(Webhook)
ここまでのレシピの出力をSlackに飛ばしたいケースは多い。GASからSlackのIncoming Webhookを叩く汎用関数。
/**
* Slackにメッセージを送信
* @param {string} message - 送信するメッセージ
* @param {string} channel - チャンネル名(省略時はWebhookのデフォルト)
*/
function sendToSlack(message, channel = null) {
const webhookUrl = PropertiesService.getScriptProperties()
.getProperty('SLACK_WEBHOOK_URL');
if (!webhookUrl) throw new Error('SLACK_WEBHOOK_URL が設定されていません');
const payload = { text: message };
if (channel) payload.channel = channel;
UrlFetchApp.fetch(webhookUrl, {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify(payload)
});
}
// 使用例: レシピ1のメール分類結果をSlackに通知
function classifyAndNotify() {
// ... classifyEmails() の処理 ...
sendToSlack(
`📬 本日のメール分類結果:\n` +
`🔴 urgent: ${urgentCount}件\n` +
`🟡 action: ${actionCount}件\n` +
`🔵 info: ${infoCount}件`
);
}
レシピ7: gwsとGASの使い分け + 連携
前回の記事で紹介したGoogle Workspace CLI(gws)とGAS、どう使い分けるか。
| 用途 | gws | GAS |
|---|---|---|
| アドホックな操作(今すぐファイル検索) | ◎ | △ |
| 定期実行の自動化 | △(cron必要) | ◎(トリガー内蔵) |
| AIエージェントからの操作 | ◎(MCP対応) | △ |
| Workspace内で完結する処理 | △ | ◎ |
| ローカルファイルとの連携 | ◎ | × |
| Webhookトリガー | △ | ◎ |
自分の使い分け:
- ターミナルから「今すぐ」何かしたい → gws
- 毎日/毎週の定期自動化 → GAS
- AIエージェント(Claude Code、Gemini CLI)から操作 → gws(MCP経由)
- フォーム送信やスプレッドシート編集をトリガーにした処理 → GAS
両者を連携させることも可能。gwsでDriveにファイルをアップロード → GASのトリガーが検知 → AI分析を実行、という流れ。
# gwsでCSVをDriveにアップロード
gws drive files create \
--json '{"name": "sales-march.csv", "parents": ["FOLDER_ID"]}' \
--upload ./sales-march.csv
// GAS側: 特定フォルダへのファイル追加をトリガーに分析実行
// ※ DriveのファイルトリガーはGAS単体ではサポートされていないため、
// 時間トリガー(5分ごと)で新規ファイルをポーリングする
function checkNewFiles() {
const folderId = 'FOLDER_ID';
const folder = DriveApp.getFolderById(folderId);
const fiveMinAgo = new Date(Date.now() - 5 * 60 * 1000);
const files = folder.getFiles();
while (files.hasNext()) {
const file = files.next();
if (file.getDateCreated() > fiveMinAgo) {
// 新規ファイルを検出 → 分析処理を実行
analyzeSalesData(); // レシピ3の関数を呼び出し
}
}
}
GAS × AIのコスト感覚
「AIのAPI呼び出しって高くないの?」という疑問に、実データで答える。
自分が1ヶ月間(2026年2月)に上記レシピを実運用した結果:
| レシピ | 月間実行回数 | 消費トークン | API費用 |
|---|---|---|---|
| メール分類 | 420回 | 約840Kトークン | $0.23 |
| 議事録要約 | 38回 | 約1.5Mトークン | $2.10 |
| 売上分析 | 4回 | 約600Kトークン | $0.84 |
| 日報生成 | 20回 | 約200Kトークン | $0.06 |
| フォーム分析 | 156回 | 約310Kトークン | $0.09 |
| 合計 | 638回 | 約3.45Mトークン | $3.32 |
月額約500円。缶コーヒー2本分で、メール分類・議事録要約・売上分析・日報生成・フォーム分析が全自動で回っている。
議事録要約だけGemini 2.5 Proを使っているのでやや高いが、それでも月額$2。Flashに切り替えれば$0.30以下になるが、要約精度が15%ほど落ちるのでProのまま運用している。
セキュリティ上の注意点
GAS × AIを業務で使う際に、絶対に意識すべきセキュリティ事項。
-
APIキーをコードにハードコードしない。 Script Propertiesに保存する(本記事の事前準備を参照)。GitHubにスクリプトを上げる場合は特に注意。
-
個人情報をAI APIに送信しない。 メールの分類ではメール本文を送信している。社外秘情報や個人情報が含まれる可能性がある場合は、事前にマスキングする処理を入れるか、Gemini APIのデータ処理ポリシー(有料APIプランでは学習に使用されない)を確認する。
-
GASの共有設定に注意。 GASプロジェクトが「リンクを知っている全員」で共有されていると、Script Propertiesに保存したAPIキーが漏洩する可能性がある。共有は「特定のユーザー」のみに制限する。
-
AI出力を鵜呑みにしない。 特に売上分析や感情スコアは、AIの「参考意見」として扱う。最終判断は人間が行う。
まとめ
Google Apps Script × AIの組み合わせは、2026年の今が最も「コスパの良いタイミング」。理由は3つ。
- AI APIが安い。 月500円で本格的な自動化が回る
- GASの実行環境が成熟した。 V8ランタイム + 30分実行上限で、実用的な処理が可能に
- ノーコードツールでは届かない柔軟性。 ZapierやMakeでは実現しにくい「AI分析→条件分岐→複数サービス連携」がコードで自由に書ける
gwsが「ターミナルからWorkspaceを操作するインターフェース」なら、GASは「Workspace内で自動化を回すエンジン」。どちらか一方ではなく、両方を使い分けるのが2026年のGoogle Workspace活用の最適解。
