GEMINI LABEN
API — temperature・top_p・top_k の非推奨は、エラーではなく無言の no-op です。リクエストは 200 で通り、値だけが受け取られたうえで無視されますAUDIT — 実行時に検知する手段がないため、コードベースを静的に検索して指定を洗い出すしかありません。監査の方法が開発者フォーラムで議論になっていますCHECK — 同じプロンプトを temperature 0 と 1 で複数回投げ、出力の分散が変わらないことを実測すれば、効いていないことを自分の目で確認できますMODELS — Gemini 3.7 Flash は DeepSWE v1.1 で 65.3%、FrontierCode 1.1 Main で 43.6% を記録しています。導入価格は2026年12月31日までですSEARCH — File Search が gemini-embedding-2 によるマルチモーダル検索に対応しました。画像を書き起こさずに、そのまま埋め込んで検索できますDEPRECATION — gemini-robotics-er-1.6-preview が8月31日に停止します。残り4日で、移行先は7月30日から公開プレビューの ER 2 系ですAPI — temperature・top_p・top_k の非推奨は、エラーではなく無言の no-op です。リクエストは 200 で通り、値だけが受け取られたうえで無視されますAUDIT — 実行時に検知する手段がないため、コードベースを静的に検索して指定を洗い出すしかありません。監査の方法が開発者フォーラムで議論になっていますCHECK — 同じプロンプトを temperature 0 と 1 で複数回投げ、出力の分散が変わらないことを実測すれば、効いていないことを自分の目で確認できますMODELS — Gemini 3.7 Flash は DeepSWE v1.1 で 65.3%、FrontierCode 1.1 Main で 43.6% を記録しています。導入価格は2026年12月31日までですSEARCH — File Search が gemini-embedding-2 によるマルチモーダル検索に対応しました。画像を書き起こさずに、そのまま埋め込んで検索できますDEPRECATION — gemini-robotics-er-1.6-preview が8月31日に停止します。残り4日で、移行先は7月30日から公開プレビューの ER 2 系です
記事一覧/Workspace 連携
Workspace 連携/2026-08-27中級

Meet のメモ機能が対面の打ち合わせに対応しました。先に決めるのは Drive の受け皿です

Google Meet のメモ機能がホーム画面から起動でき、対面の打ち合わせも対象になりました。生成されたドキュメントが Drive に散らばる前に受け皿を決め、決定事項だけを Apps Script で台帳へ落とす手順をまとめます。

Gemini81Google MeetApps Script10Google Drive議事録

打ち合わせの帰り道に手元のメモを開いて、決まったことの半分しか書き取れていないと気づく。この経験を何度か繰り返してから、私は対面の場ではメモを取ることを諦めて、終わってすぐ喫茶店で思い出しながら書き起こすようになりました。

その書き起こしが、いつも一番後回しになります。個人開発で動いていると、記録係を頼める相手がいません。この作業だけが手元に溜まっていきます。

2026年8月26日の更新で、Google Meet のメモ機能がウェブとモバイルのホーム画面から直接起動できるようになりました。会議に参加していなくてもメモセッションを始められるということは、目の前に相手がいる対面の打ち合わせでも使えるということです。

ただ、この機能を単体で使い始めると、生成されたドキュメントが Drive のあちこちに積み上がります。記録が残るようになった代わりに、探せなくなるのです。先に決めておくべきなのは、記録の作り方ではなく置き場所でした。

何が出力されるのかを、先に把握しておく

メモセッションを開始すると、Gemini が会話を聞き取り、終了後に Google ドキュメントを1つ作って Drive へ保存します。1つのドキュメントの中に、性質の違う3種類の情報が同居します。

出力中身後工程での扱い
構造化された要約話題ごとに見出しが立ち、経緯が数行にまとまるそのまま読む。機械処理にも向く
アクションアイテム誰が何をするかの箇条書きタスク管理側へ転記する対象
全文の書き起こし発言をそのまま起こしたテキスト言った言わないの確認用。普段は読まない

この3つを同じ重さで扱うと破綻します。全文の書き起こしは対面30分でもかなりの分量になり、後から Gemini API に丸ごと渡すと、要約セクションに書いてある結論をもう一度探させることになります。

実務で毎回使うのは要約とアクションアイテムだけです。書き起こしは、争いになったときだけ開く保険として置いておく。この線引きを最初に引いておくと、後の自動化がずいぶん素直になります。

受け皿のフォルダを1つ作り、そこだけを見る

保存先を決めずに使い始めると、ドキュメントは自分の Drive の中に日付順で並びます。案件が2つ3つと並行し始めた時点で、どれがどの打ち合わせのものか、ファイル名だけでは判別できなくなります。

私はこの分類を、その場でやることを諦めました。採った形は単純です。受け皿のフォルダを1つだけ作り、打ち合わせが終わったらそこへ移す。それだけです。

Meetings/
  _inbox/          ← 生成されたドキュメントを一旦ここへ
  2026/
    展示準備/
    アプリ開発/

_inbox を経由させるのは、分類の判断を後回しにするためです。打ち合わせ直後は次の予定が詰まっていることが多く、その場でフォルダを選ばせると運用が続きません。移動だけなら数秒で終わります。

そして、この後に書く自動処理は _inbox だけを見ます。分類前のものを拾い、台帳へ落とし、処理済みの印をつける。分類は人が後からゆっくりやればよく、自動処理の側は分類結果に依存しません。

自動処理と人の判断を同じフォルダ構造に載せると、片方を変えたときにもう片方が壊れます。入口を1つに絞っておくと、その心配がなくなります。

決定事項だけを抜き出して台帳に落とす

ここからは Apps Script です。_inbox のドキュメントを順に開き、要約セクションだけを Gemini API に渡し、決定事項を構造化して返してもらい、スプレッドシートへ追記します。

まず設定と入口の処理です。

const CONFIG = {
  // _inbox フォルダの ID(Drive の URL 末尾)
  intakeFolderId: 'YOUR_FOLDER_ID',
  // 決定事項を溜める台帳スプレッドシートの ID
  ledgerSheetId: 'YOUR_SHEET_ID',
  // モデル ID は公式のモデル一覧で現行のものを確認してください
  model: 'gemini-3.7-flash',
};
 
function collectMeetingNotes() {
  const folder = DriveApp.getFolderById(CONFIG.intakeFolderId);
  const files = folder.getFilesByType(MimeType.GOOGLE_DOCS);
  const store = PropertiesService.getScriptProperties();
 
  while (files.hasNext()) {
    const file = files.next();
    const doneKey = 'done_' + file.getId();
    if (store.getProperty(doneKey)) continue;
 
    const section = extractSummarySection(file.getId());
    if (!section) continue;
 
    const result = askGemini(section);
    appendToLedger(file, result);
    store.setProperty(doneKey, String(Date.now()));
  }
}

処理済みの印をファイル側ではなくスクリプトプロパティに置いているのは、ドキュメントに手を加えたくないからです。打ち合わせの記録は原本のまま残しておきたく、自動処理の都合で本文にマーカーを書き込むのは避けました。フォルダを移動しても ID は変わらないため、分類後も二重取り込みは起きません。

次に、要約セクションだけを取り出す部分です。

function extractSummarySection(docId) {
  const body = DocumentApp.openById(docId).getBody();
  const total = body.getNumChildren();
  const HEADINGS = ['要約', 'まとめ', 'Summary'];
  const lines = [];
  let started = false;
 
  for (let i = 0; i < total; i++) {
    const el = body.getChild(i);
    const type = el.getType();
    if (type !== DocumentApp.ElementType.PARAGRAPH &&
        type !== DocumentApp.ElementType.LIST_ITEM) continue;
 
    const item = (type === DocumentApp.ElementType.PARAGRAPH)
      ? el.asParagraph()
      : el.asListItem();
    const text = item.getText().trim();
    const isHeading = item.getHeading() !== DocumentApp.ParagraphHeading.NORMAL;
 
    if (isHeading) {
      if (!started && HEADINGS.some(function (h) { return text.indexOf(h) === 0; })) {
        started = true;
        continue;
      }
      if (started) break;  // 次の見出しに入ったら打ち切る
      continue;
    }
    if (started && text) lines.push(text);
  }
  return lines.length ? lines.join('\n') : null;
}

見出しの文字列で区間を切っているだけの、素朴な処理です。それでも全文を渡すのに比べると、投げるトークン量が桁で変わります。見出しの語は環境によって変わりますので、実際のドキュメントを一度開いて、先頭の見出しが何と書かれているかを確認してから HEADINGS を調整してください。

該当する見出しが見つからなければ null を返し、呼び出し側はそのファイルを飛ばします。想定外の形のドキュメントを無理に処理して、中途半端な行を台帳に混ぜるより、素通りさせて後で気づくほうが安全だと考えています。

API 呼び出しは、返ってくる形を先に決める

決定事項を後から機械で扱うなら、自由文で返してもらう理由がありません。responseSchema で形を固定します。

function askGemini(sectionText) {
  const apiKey = PropertiesService.getScriptProperties().getProperty('GEMINI_API_KEY');
  const endpoint = 'https://generativelanguage.googleapis.com/v1beta/models/' +
    CONFIG.model + ':generateContent';
 
  const payload = {
    contents: [{
      role: 'user',
      parts: [{ text: buildPrompt(sectionText) }]
    }],
    generationConfig: {
      responseMimeType: 'application/json',
      responseSchema: {
        type: 'object',
        properties: {
          decisions: { type: 'array', items: { type: 'string' } },
          owners: { type: 'array', items: { type: 'string' } },
          due: { type: 'string' }
        },
        required: ['decisions']
      }
    }
  };
 
  const res = UrlFetchApp.fetch(endpoint, {
    method: 'post',
    contentType: 'application/json',
    headers: { 'x-goog-api-key': apiKey },
    payload: JSON.stringify(payload),
    muteHttpExceptions: true
  });
 
  const code = res.getResponseCode();
  if (code !== 200) {
    throw new Error('Gemini API ' + code + ': ' + res.getContentText());
  }
  const body = JSON.parse(res.getContentText());
  return JSON.parse(body.candidates[0].content.parts[0].text);
}
 
function buildPrompt(sectionText) {
  return [
    '次は打ち合わせの要約です。決まったことだけを抜き出してください。',
    '検討中の案、保留になった話題、感想は含めないでください。',
    'owners には decisions と同じ順で担当者名を入れ、不明な場合は空文字にしてください。',
    '---',
    sectionText
  ].join('\n');
}

generationConfigtemperature を書いていないのは、書き忘れではありません。2026年8月の時点で temperaturetop_ptop_k は非推奨になりました。出力の揺れをこれらで抑えていた実装は、いずれ書き直しが必要になります。今から書くコードにわざわざ入れる理由はありませんでした。

揺れを抑える役目は、スキーマとプロンプトの制約側に移しています。「検討中の案を含めない」と明示的に書いておくのは、要約の中で結論と検討が隣り合って書かれているとき、両方を決定事項として拾ってしまうことがあったためです。

最後に台帳へ書き込みます。

function appendToLedger(file, result) {
  const sheet = SpreadsheetApp.openById(CONFIG.ledgerSheetId).getSheets()[0];
  const decisions = result.decisions || [];
  const owners = result.owners || [];
  if (!decisions.length) return;
 
  const rows = decisions.map(function (text, i) {
    return [
      Utilities.formatDate(file.getDateCreated(), 'Asia/Tokyo', 'yyyy-MM-dd'),
      file.getName(),
      text,
      owners[i] || '',
      result.due || '',
      file.getUrl()
    ];
  });
 
  sheet.getRange(sheet.getLastRow() + 1, 1, rows.length, rows[0].length)
       .setValues(rows);
}

行ごとに元ドキュメントの URL を持たせているのが、地味ですが効きます。台帳の一行を見て「本当にそう決まったのか」と迷ったとき、その場から原本へ飛べます。要約は要約でしかなく、判断の根拠は常に原本側にあるという前提を、データ構造で表しておきたかったのです。

実行は時間主導型トリガーで1日1回にしています。打ち合わせの直後に即座に台帳へ載る必要はなく、翌朝までに揃っていれば十分でした。トリガーの本数が増えてきたら、Apps Script の時間主導型トリガーが静かに枯渇する で扱った一本化の考え方が役に立ちます。権限まわりは Apps Script × Gemini 自動化の権限を最小に保つ のスコープ設計に合わせて、appsscript.json に必要なものだけを明示してください。

対面で回す前に、人に伝えることを決めておく

技術的な準備よりも、こちらのほうが重要かもしれません。

オンライン会議であれば、記録が取られていることは画面上の表示で全員に伝わります。対面の打ち合わせでは、机の上に置かれた端末が何をしているのか、相手からは見えません。

私自身は、始める前にひとこと断ることを自分のルールにしました。「後で議事録を起こすのが追いつかないので、メモ機能を使わせてください」と伝えると、たいていは快く受け入れてもらえます。断られたときは素直に手で書きます。

あわせて、次の3つを自分の中で決めておくと迷いません。

  • 共有範囲: 生成されたドキュメントを相手にも渡すのか、自分の手控えとして持つだけなのか
  • 保持期間: 全文の書き起こしをいつまで残すか。決定事項が台帳に移った後は、原本を一定期間で整理する
  • 除外する場面: 雑談混じりの会食や、まだ公にできない相談ごとでは使わない

記録が残ることは、相手にとって必ずしも歓迎される話ではありません。便利さを理由に、その感覚を飛び越えないようにしています。

次の一歩

まずは _inbox フォルダを1つ作って、次の打ち合わせでメモ機能を回してみてください。自動化はその後で構いません。生成されたドキュメントを一度自分の目で読み、要約の見出しがどう立つかを確認してからでないと、extractSummarySection の調整ができないためです。

なお、Workspace 側の新機能をどこまで自動化に取り込むかという線引きについては、Sheets canvas へ移せるのは入口までで、実行境界は Apps Script に残ります で、実行の責任をどちらに残すかという観点から詳しく整理しています。

対面の記録は、これまで一番手が回らない場所でした。そこに手が届くようになったこと自体は、素直にありがたく思っています。お読みいただきありがとうございました。

シェア

お読みいただきありがとうございます

Gemini Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

Workspace 連携2026-08-26
Sheets canvas へ移せるのは入口までで、実行境界は Apps Script に残ります
Sheets canvas の登場で、内製した Apps Script のどこまでを手放せるのかを実行境界という物差しで仕分けしました。移す処理と残す処理の判定基準、棚卸しを機械化する分類スクリプトまでをまとめています。
Workspace 連携2026-07-15
表を渡したはずが、行と列の対応が消えていた — Docs の構造を保ったまま Gemini に渡す抽出層
Apps Script の getBody().getText() は Docs の表を段落の並びに潰します。42行×5列の運用台帳での取り違え実測と、要素ツリーを歩いて構造を残す抽出層の実装、その受け入れテストまでを記録しました。
Workspace 連携2026-07-13
夜間バッチの完了を待つポーリングを畳む — Apps Script の doPost を Gemini の合図受けにする設計
Gemini の Batch や長時間オペレーションの完了を Apps Script の時間主導トリガーで5分おきに問い合わせると、UrlFetch の呼び出しと待ち時間が静かに積み上がります。Webhook を doPost で受け、合図として扱ってから権威確認と冪等適用に落とす設計を組み立てます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →