こちらの記事に書いた通り、2025年1月現在、Google Workspace Studioは「他のユーザーと共有したスプレッドシートなどのリソースが利用できない」など、会社のチーム資産として利用するにはちょっと不安がある作りとなっています。他の人への引き継ぎが難しかったり、必要な処理がいろいろな場所に分散(GASにあったりWorkspaceFlowsにあったり…)して追いづらくなるという問題が発生します。
そこで「Workspace Studioではシンプルなワークフローを用意するだけにして、チームで自動化したい部分はGASでコード管理すればいいんじゃないか」ということを思いつき、実際に実現できることを確認しました!
表現したいGASのコード
結論からいうと、次のようなコードでGeminiを呼び出せるテンプレートを用意しました。
function myFunction() {
const response = MyGeminiApp.call("株式会社LIFULLについてWikipediaから教えて");
console.log(response);
// -> 株式会社LIFULL(ライフル、英: LIFULL Co., Ltd.)は、東京都千代田区に本社を置く、日本の不動産テック企業です。...
}
実装方法
①スプレッドシートの準備
他人と共有していないスプレッドシートに、「Input」と「Output」という2つのシートを用意します。Inputには「Prompt」というカラムを、Outputには「Prompt」と「Response」というカラムを用意します。
②Workspace Studioを設定
Inputのシートの「Prompt」に書き込まれると、
OutputのシートにGeminiの結果が書き込まれるように設定します。
具体的な設定方法自体は簡単なので省略します。
③GASで次のコードを実装する
そして、GASで次のような MyGeminiApp を用意すれば完成です。ポーリングして、Promptの内容に一致するものがWorkspace Studioで処理が完了して書き込まれたら結果としてreturnする設計です。
用途によってLockServiceの種類を書き換えたり、時間によって回答が変わる可能性があるもの(「今日のニュースを教えて」など)が必要なら少し修正が必要だと思います。
/**
* シートを介してAIへの問い合わせと回答取得を同期的に行います。
*/
class MyGeminiService {
constructor() {
this.CONFIG = {
SHEET_INPUT: "Input",
SHEET_OUTPUT: "Output",
TIMEOUT_MS: 60000, // 60秒待機
POLLING_INTERVAL_MS: 2000 // 2秒おきにチェック
};
}
/**
* AIにメッセージを送り、回答を待ちます
* @param {string} prompt
* @return {string} response
*/
call(prompt) {
if (!prompt) throw new Error("プロンプトが入力されていません。");
// 1. InputシートのA列にプロンプトを追記
this._send(prompt);
// 2. Outputシートから回答が返るのを待機して返す
return this._receive(prompt);
}
// --- 内部メソッド ---
_send(prompt) {
const sheet = this._getOrCreateSheet(this.CONFIG.SHEET_INPUT);
const lock = LockService.getScriptLock();
// 並列実行時の上書きを防ぐためのロック(最大30秒)
if (lock.tryLock(30000)) {
try {
sheet.appendRow([prompt]); // A列(Prompt)に書き込み
SpreadsheetApp.flush();
} finally {
lock.releaseLock();
}
} else {
throw new Error("サーバーが混雑しています。時間を置いて再試行してください。");
}
}
_receive(targetPrompt) {
const sheet = this._getOrCreateSheet(this.CONFIG.SHEET_OUTPUT);
const start = Date.now();
while (Date.now() - start < this.CONFIG.TIMEOUT_MS) {
// OutputシートのA列(Prompt)から完全一致を検索
const finder = sheet.getRange("A:A").createTextFinder(targetPrompt).matchEntireCell(true);
const matches = finder.findAll();
if (matches.length > 0) {
// 同じプロンプトがある場合は、一番下(最新)の行のB列(Response)を取得
const latestRow = matches[matches.length - 1].getRow();
const response = sheet.getRange(latestRow, 2).getValue();
if (response) return response;
}
Utilities.sleep(this.CONFIG.POLLING_INTERVAL_MS);
}
throw new Error(`タイムアウト: 「${targetPrompt}」への回答が制限時間内に見つかりませんでした。`);
}
_getOrCreateSheet(name) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
return ss.getSheetByName(name) || ss.insertSheet(name);
}
}
/**
* サービスインスタンスの公開
*/
const MyGeminiApp = new MyGeminiService();
まとめ
こうすることで、自動化したい作業の中からGemini処理のみを疎結合にして、チーム運用時の不安を一定回避できると思います。
ただ、GASの用途によっては、自分のGeminiの権限で他のチームメンバーが閲覧できてしまう危険もあるなど、安易に使うとセキュリティやガバナンス上の問題が発生するはずです。そのため基本的にはAsk Geminiの設定をWeb Onlyにして権限を絞っておくべきで、必要なデータ取得はGASで処理を書いたほうが得策だと思います。
また、Learn about Google Workspace Studio limitsにあるような呼び出し回数の制限も注意する必要がありそうです。


