leale
第2期 Day 2
石垣商店
株式会社leale — AI 活用 企業研修 第2期(上級)

Day 2:Claude API
× エージェント開発

Claude API の仕組みを理解し、GAS から API を呼び出して
石垣商店の業務メールを自動分類・回答するエージェントを実装する 4 時間。

顧客
株式会社石垣商店
業種
銅・真鍮加工製造業
参加者
選抜数名
日程
2026年 月 日
0:00-0:15Day 1 振り返り
0:15-1:00Claude API 概要
1:10-2:10GAS x API 接続
2:20-3:20エージェント実装
3:30-4:00テスト・発表
Opening 0:00 - 0:15

Day 1 振り返り
× 本日のゴール

🎯 Day 2 のゴール

Claude API を GAS から呼び出し、石垣商店の業務メールを自動分類・回答案生成するエージェントを完成させる。

Day 1 振り返りチェック(5分)

  • ✅ GWS 管理コンソールで Gemini のグループ別設定ができる
  • ✅ 利用レポートの確認・2段階認証の強制設定を操作できた
  • ✅ GAS スクリプトエディタでメール送信スクリプトを実行できた
  • ✅ スクリプトプロパティに値を設定する方法がわかる
Day 1 宿題確認:「実績シートのデータをメール送信するスクリプト」が動かなかった方はすぐ教えてください。Day 2 の土台になります。

今日作るもの:メール分類エージェントの全体像

受信メール
問い合わせ内容
GAS が
読み取り
Claude API
呼び出し
カテゴリ分け
+回答案生成
担当者に
メール通知
Section 1 / 講義 0:15 - 1:00 / 45分

Claude API の仕組み・料金・セキュリティ

🎯 ゴール

Claude API の料金・セキュリティ・APIキー管理を正しく理解し、安全に使えるようになる。

1-1. Claude.ai 無料版 vs Claude API の違い(15分)

claude.ai(手動利用)
  • ✅ ブラウザで手動利用
  • ✅ 月額固定費(Pro: $20/月)
  • ❌ プログラムから呼び出せない
  • ❌ 自動化・バッチ処理不可
Claude API(プログラム連携)
  • 🔷 GAS 等から自動呼び出し
  • 🔷 従量課金(使った分だけ)
  • 🔷 バッチ処理・定期実行が可能
  • 🔷 自社システムへの組み込みが可能

1-2. 従量課金モデルとコスト感(10分)

「トークン(token)」で課金されます。1トークン ≈ 英字4文字 / 日本語1〜2文字。

モデルInput (1Mトークン)Output (1Mトークン)用途の目安
claude-3-5-haiku$0.80$4.00高速・低コスト。分類・短文生成に最適
claude-3-5-sonnet$3.00$15.00バランス型。今回のメイン
claude-opus-4$15.00$75.00最高品質。複雑な推論が必要な場合
石垣商店の試算:1件のメール問い合わせ処理 ≈ 500 tokens。月100件処理しても $0.20(約30円)程度。非常に低コストです。

1-3. APIキーの取得手順(10分)

HANDS-ON

Anthropic Console で APIキーを取得する

  1. ブラウザで console.anthropic.com にアクセス
  2. 「Sign Up」または「Log In」でアカウントを作成・ログイン
  3. 左メニュー「API Keys」→「Create Key」をクリック
  4. キー名を「石垣商店_GAS_テスト」等わかりやすい名前にする
  5. 「Create Key」→ 表示された sk-ant-... から始まるキーをコピーして一時保存
  6. 注意:このキーは一度しか表示されません。必ず保存してください。
所要時間:10分

1-4. APIキーのセキュリティ管理(10分)

絶対にやってはいけないこと:
  • ❌ コードの中に直接 API キーを書く(ハードコーディング)
  • ❌ スプレッドシートのセルに API キーを保存する
  • ❌ メールや Slack で API キーを送信する
  • ❌ GitHub や Google Drive のパブリックファイルに含める
正しい保存方法:GAS のスクリプトプロパティを使う
スクリプトプロパティへの保存 + 取得コード
// スクリプトエディタで: // 「プロジェクトの設定」→「スクリプトプロパティ」→「追加」 // プロパティ名:CLAUDE_API_KEY 値:sk-ant-xxxxxx // コードからは以下で取得する(安全) function getApiKey() { return PropertiesService.getScriptProperties() .getProperty('CLAUDE_API_KEY'); } // 絶対にこう書かない(NG例): // const API_KEY = "sk-ant-api03-xxxxxxxx"; ← ハードコード禁止!
ここは何度も強調してください。APIキーの漏洩はそのまま費用被害につながります。「GitHubにキーを公開してしまった事例」を紹介すると刺さります。受講者がキーをチャットやメールで送らないよう注意してください。
Live Poll — チェックポイント
APIキーを取得できましたか?
QRコード
(講師設定)
スマホで
QR を読み取り投票
取得できた。スクリプトプロパティに保存した
取得できたが、保存方法がまだわからない
アカウント作成でつまづいている
エラーが出ている(課金設定が必要な場合あり)
📋 講師:取得できていない人を優先してサポート。Anthropic は初回 $5 の無料クレジットが付与されます。
☕ 休憩 10分(1:00 - 1:10)
Section 2 / ハンズオン 1:10 - 2:10 / 60分

GAS × Claude API 接続
ハンズオン

🎯 ゴール

GAS の UrlFetchApp.fetch で Claude API を呼び出し、レスポンスをパースできる。メール自動分類の基礎コードを動かせる。

2-1. Claude API 呼び出しの基礎コード(20分)

まず最もシンプルな「テキストを送って返答させる」構成から始めます。

Claude API 最小構成 callClaude()
/** * Claude API を呼び出す基本関数 * GAS スクリプトエディタに貼り付けて実行する */ function callClaude(userMessage) { const apiKey = PropertiesService.getScriptProperties() .getProperty('CLAUDE_API_KEY'); if (!apiKey) throw new Error('CLAUDE_API_KEY が未設定です'); const payload = { model: "claude-3-5-haiku-20241022", max_tokens: 1024, messages: [{ role: "user", content: userMessage }] }; const options = { method: "post", headers: { "x-api-key": apiKey, "anthropic-version": "2023-06-01", "content-type": "application/json" }, payload: JSON.stringify(payload), muteHttpExceptions: true }; const response = UrlFetchApp.fetch( "https://api.anthropic.com/v1/messages", options ); const result = JSON.parse(response.getContentText()); if (result.error) { Logger.log("API エラー: " + JSON.stringify(result.error)); throw new Error(result.error.message); } return result.content[0].text; } // テスト実行 function testCallClaude() { const answer = callClaude("銅と真鍮の違いを50字以内で説明してください。"); Logger.log(answer); }
EXERCISE

コードを貼り付けてテスト実行する

  1. スクリプトエディタを開き、コードを貼り付けて保存
  2. 実行する関数を「testCallClaude」に選択して▶実行
  3. 「実行ログ」に Claude の返答が表示されることを確認
  4. エラーが出た場合は次のエラーハンドリングセクションへ
所要時間:10分

2-2. エラーハンドリングのパターン(15分)

本番運用に向けて、よくあるエラーへの対処を実装します。

エラーハンドリング付き callClaudeSafe()
/** * エラーハンドリング付きの安全な Claude API 呼び出し * 本番実装ではこちらを使う */ function callClaudeSafe(userMessage, systemPrompt) { const apiKey = PropertiesService.getScriptProperties() .getProperty('CLAUDE_API_KEY'); // APIキー未設定チェック if (!apiKey) { Logger.log('エラー: CLAUDE_API_KEY が未設定'); return null; } const messages = [{ role: "user", content: userMessage }]; const payload = { model: "claude-3-5-haiku-20241022", max_tokens: 1024, messages: messages }; // システムプロンプト(役割指定)があれば追加 if (systemPrompt) payload.system = systemPrompt; try { const options = { method: "post", headers: { "x-api-key": apiKey, "anthropic-version": "2023-06-01", "content-type": "application/json" }, payload: JSON.stringify(payload), muteHttpExceptions: true }; const response = UrlFetchApp.fetch( "https://api.anthropic.com/v1/messages", options ); const statusCode = response.getResponseCode(); // HTTP ステータスコードで大まかなエラー判定 if (statusCode === 401) { Logger.log('認証エラー: APIキーが無効'); return null; } if (statusCode === 429) { Logger.log('レート制限: しばらく待ってから再試行'); return null; } if (statusCode !== 200) { Logger.log('HTTP エラー: ' + statusCode); return null; } const result = JSON.parse(response.getContentText()); if (result.error) { Logger.log('API エラー: ' + result.error.message); return null; } return result.content[0].text; } catch (e) { Logger.log('例外発生: ' + e.toString()); return null; } }

2-3. 石垣商店向け — メール自動分類スクリプト(25分)

受信メールの内容を3カテゴリに自動分類します。

カテゴリA
材料問い合わせ
銅・真鍮の在庫・規格・単価
カテゴリB
納期相談
納期・スケジュール変更・急ぎ対応
カテゴリC
新規見積もり
初回取引・見積依頼・加工仕様確認
メール自動分類スクリプト
/** * メール内容を3カテゴリに自動分類する * @param {string} emailBody - メール本文 * @returns {Object} { category, reason, urgency } */ function classifyEmail(emailBody) { const systemPrompt = `あなたは銅・真鍮加工メーカー「石垣商店」の問い合わせ分類AIです。 メール本文を読んで、以下の3カテゴリのうち最も適切なものを選んでください。 カテゴリ: A. 材料問い合わせ(銅・真鍮の在庫・規格・単価に関する問い合わせ) B. 納期相談(納期・スケジュール変更・急ぎ対応に関する問い合わせ) C. 新規見積もり(初回取引・見積依頼・加工仕様確認に関する問い合わせ) 必ずJSON形式で回答してください: {"category": "A", "reason": "分類理由を20字以内", "urgency": "高/中/低"}`; const response = callClaudeSafe(emailBody, systemPrompt); if (!response) return null; try { // JSONとして解析 const jsonMatch = response.match(/\{[\s\S]*\}/); if (jsonMatch) return JSON.parse(jsonMatch[0]); } catch (e) { Logger.log('JSON解析エラー: ' + e.toString()); } return { category: '不明', reason: '解析失敗', urgency: '中' }; } // テスト用サンプルメール function testClassifyEmail() { const samples = [ "いつもお世話になっております。φ10mm銅丸棒の在庫状況をお教えいただけますか。", "先日ご注文した真鍮板の納期を1週間早めることは可能でしょうか。急ぎの案件が入りました。", "初めてご連絡します。銅パイプの切断加工について見積もりをいただきたく存じます。" ]; samples.forEach((mail, i) => { const result = classifyEmail(mail); Logger.log(`サンプル${i+1}: ${JSON.stringify(result)}`); }); }
JSON を返させる際、Claude が余分なテキストを付けることがあります。正規表現 /\{[\s\S]*\}/ で JSON 部分だけ抽出しています。この「Claude の出力を構造化する」パターンはエージェント開発の基本テクニックとして強調してください。
☕ 休憩 10分(2:10 - 2:20)
Section 3 / ハンズオン 2:20 - 3:20 / 60分

業務エージェントの設計・実装
— スプレッドシート連携

🎯 ゴール

スプレッドシートに問い合わせ内容を入力すると Claude が自動で回答案を生成して隣のセルに書き込むエージェントを完成させる。

3-1. エージェントの設計(入力→処理→出力)(15分)

INPUT(入力)
  • ・スプレッドシートの問い合わせ内容
  • ・送信者名・会社名
  • ・受信日時
PROCESS(処理)
  • ・Claude API でカテゴリ分類
  • ・緊急度の判定
  • ・回答文の自動生成
OUTPUT(出力)
  • ・隣のセルに結果を書き込み
  • ・担当者にメール通知
  • ・ステータスを「処理済」に更新

3-2. スプレッドシート連携エージェントの実装(45分)

A列=問い合わせ内容、B列=カテゴリ、C列=緊急度、D列=回答案、E列=ステータス という構成で実装します。

スプレッドシート連携エージェント 完全版
/** * 問い合わせ自動処理エージェント(完全版) * スプレッドシートの未処理行を読み取り Claude で処理する * * スプレッドシート列構成: * A: 問い合わせ内容 B: カテゴリ C: 緊急度 * D: 回答案 E: ステータス(空=未処理/処理済) */ function processInquiries() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const sheet = ss.getSheetByName("問い合わせ") || ss.getActiveSheet(); const lastRow = sheet.getLastRow(); if (lastRow < 2) { Logger.log("処理するデータがありません"); return; } let processedCount = 0; for (let row = 2; row <= lastRow; row++) { const status = sheet.getRange(row, 5).getValue(); if (status === "処理済") continue; // 処理済はスキップ const inquiry = sheet.getRange(row, 1).getValue(); if (!inquiry) continue; // 内容が空の行はスキップ Logger.log(`${row}行目を処理中: ${inquiry.substring(0, 30)}...`); // Step 1: カテゴリ分類 const classResult = classifyEmail(inquiry); if (!classResult) { sheet.getRange(row, 5).setValue("エラー"); continue; } // Step 2: 回答案を生成 const draftReply = generateReply(inquiry, classResult.category); // Step 3: スプレッドシートに書き込む sheet.getRange(row, 2).setValue(classResult.category); sheet.getRange(row, 3).setValue(classResult.urgency); sheet.getRange(row, 4).setValue(draftReply || "(生成失敗)"); sheet.getRange(row, 5).setValue("処理済"); processedCount++; Utilities.sleep(1000); // API レート制限回避のため1秒待機 } Logger.log(`処理完了: ${processedCount}件`); // 緊急度「高」の件数を集計してメール通知 const highUrgency = sheet.getRange(2, 3, lastRow - 1, 1) .getValues() .filter(r => r[0] === "高") .length; if (highUrgency > 0) { notifyUrgent(highUrgency); } } /** * 回答案を生成する */ function generateReply(inquiry, category) { const categoryNames = { "A": "材料問い合わせ", "B": "納期相談", "C": "新規見積もり" }; const systemPrompt = `あなたは銅・真鍮加工メーカー「石垣商店」の営業担当AIです。 カテゴリ「${categoryNames[category] || category}」の問い合わせへの返信案を作成してください。 ルール: - 丁寧で簡潔な日本語ビジネスメール - 200字以内 - 「担当者が詳細確認後、改めてご連絡します」という旨を含める - 社名「石垣商店」を名乗る`; return callClaudeSafe(inquiry, systemPrompt); } /** * 緊急度「高」の件数を担当者にメール通知 */ function notifyUrgent(count) { const TO = PropertiesService.getScriptProperties() .getProperty('MANAGER_EMAIL'); if (!TO) return; MailApp.sendEmail( TO, `【石垣商店】要対応:緊急度「高」の問い合わせが${count}件あります`, `スプレッドシートを確認して対応をお願いします。\n\n` + `確認URL: ${SpreadsheetApp.getActiveSpreadsheet().getUrl()}` ); }
EXERCISE

エージェントを動かしてみる

  1. スプレッドシートに「問い合わせ」シートを作成(または既存のシート名を変更)
  2. A2〜A4 に以下のサンプルデータを入力:
    ・「φ15mm の銅丸棒は在庫がありますか」
    ・「先月注文した真鍮板の納期を3日早めてほしい」
    ・「初めてご連絡します。銅パイプの加工について相談したい」
  3. スクリプトエディタで processInquiries を実行
  4. B〜E 列に結果が書き込まれることを確認
  5. D 列の回答案を読んで、内容が適切か評価する
所要時間:30分
Utilities.sleep(1000) はレート制限回避に重要です。大量処理時は必ず入れるよう指導してください。本番では GAS のトリガー(毎時・毎日)で自動実行するよう設定します。この設定方法は Day 3 でも使います。
Section 4 / 発表 3:30 - 4:00 / 30分

テスト・デバッグ
× 成果を共有する

🎯 ゴール

各自のエージェントをテストし、問題点を Claude でデバッグして解決できる。成果を全員で共有する。

デバッグの方法:エラーを Claude に投げる

GAS デバッグ依頼プロンプト
Google Apps Script でエラーが出ています。修正してください。 【エラーメッセージ】 (スクリプトエディタの「実行ログ」に表示されたエラーをここに貼る) 【現在のコード】 (エラーが出ているコードをここに貼る) 【やりたいこと】 Claude API を呼び出してスプレッドシートに結果を書き込みたい。 修正したコードのみを出力してください。
Live Poll — Day 2 最終アンケート
次に作りたい業務エージェントはどれですか?
QRコード
(講師設定)
スマホで
QR を読み取り投票
見積もり自動作成エージェント
在庫・発注アラートエージェント
日報・月報 自動生成エージェント
Day 3 でゼロから設計したい
📋 講師:「Day 3 は今日作ったエージェントをベースに、フォームと連携させてより実用的なアプリにします」と予告してください
第2期 Day 2 TAKEAWAYS

今日のまとめ

TAKEAWAY 01

Claude API = GAS の「脳」

GAS が手足(データ取得・書き込み・メール送信)、Claude API が脳(判断・文章生成)。この組み合わせが最強。

TAKEAWAY 02

APIキーは必ずプロパティへ

コードへのハードコーディングは絶対禁止。スクリプトプロパティに保存して、コードから取得する。

TAKEAWAY 03

出力を JSON で構造化する

Claude に JSON で返答させ、プログラムで処理しやすくする。エージェント開発の基本パターン。

TAKEAWAY 04

エラーは Claude にデバッグさせる

エラーメッセージ+コードを貼るだけ。エラー対応の7割は Claude が即解決してくれる。

Day 3 までの準備

今日作ったエージェントに実際の(または架空の)問い合わせメールを5件入力してテストしてください。
分類が間違っていた場合は、その内容をメモして Day 3 冒頭で共有してください。

Day 3 では Google フォームと連携させて「問い合わせ受付から回答まで全自動」のシステムを完成させます。