G-gen の奥田です。当記事は、2026年3月19日に開催された Agentic AI Summit 2026 Spring で筆者と弊社の今野が登壇したセッション「Gemini Enterprise と ADK で実現する業務特化型エージェント開発の最前線 — ユーザー認証連携における Google Workspace 操作の実装方法と事例を公開」のレポートです。
- セッションの概要
- なぜ AI エージェントにユーザー認証が必要なのか
- デモ : 議事録カレンダー登録エージェント
- なぜ ADK を選んだのか
- コードの実装
- 開発中に遭遇した落とし穴
- Gemini Enterprise へのデプロイ
- 参考リンク

セッションの概要
当セッションでは、AI エージェントが Google Workspace のサービスを操作する際に不可欠なユーザー認証連携をテーマに、実装方法と事例を紹介しました。
セッション前半では、AI エージェントにおける認証の重要性を具体的なシナリオで解説し、議事録から Google Calendar にイベントを自動登録するエージェントのライブデモを行いました。後半では、Gemini Enterprise、Agent Development Kit(以下、ADK)、Agent Engine を組み合わせたアーキテクチャと、OAuth 2.0 連携の実装ステップを紹介しました。
- 参考 : Gemini Enterprise
- 参考 : Agent Development Kit(ADK)
- 参考 : Agent Engine
- 参考 : OAuth 2.0
Agentic AI Summit 2026 Spring での実績は以下のとおりです。
| 合計 | オンライン | オフライン | CSAT | |
|---|---|---|---|---|
| G-gen セッション | 741 名 | 556 名 | 185 名 | 3.9 |
なぜ AI エージェントにユーザー認証が必要なのか
サービスアカウントのリスク
AI エージェントを業務で利用する場合、「エージェントが誰として外部サービスにアクセスするのか」が重要な設計課題です。
たとえば、社員 A さんが AI エージェントに「来週の火曜日に会議を入れて」と依頼したとします。エージェントは A さんの代わりに Google Calendar を操作する必要があります。このとき、システム共通のサービスアカウントに権限を一括付与して動かすと、エージェントは A さんだけでなく B さんや他の組織の C さんのカレンダーにもアクセスできてしまいます。
技術的には動作しますが、業務での利用には適しません。AI エージェントは人間と違い、バックグラウンドで大量のデータに触れることができます。だからこそ「誰として動いているのか」を明確に設計することが不可欠です。

OAuth 2.0 によるユーザー認証連携
この課題の解決策が OAuth 2.0 を使ったユーザー認証連携です。
仕組みはシンプルです。ユーザーが一度ログインして権限を許可すると、エージェントはそのユーザーのアクセストークンを使って API を呼び出します。エージェントはそのユーザーの権限の範囲内でしか動作しません。
A さんの AI エージェントが行った操作は「A さんが自分の権限で実行した」という記録です。コンプライアンスの観点でも重要なポイントです。

デモ : 議事録カレンダー登録エージェント
デモの概要
セッションでは、議事録や ToDo メモからタスクを抽出し、Google Calendar にイベントを自動登録するエージェントのライブデモを行いました。
デモの流れは以下のとおりです。
- Gemini Enterprise 上でエージェントを起動し、OAuth 認証を完了する
- 直近のカレンダー予定を確認する
- 日時とタイトルを入力してイベントを追加する
- 約 6,300 文字の架空の議事録(ポータルサイトプロジェクト)をエージェントに渡す
- エージェントが議事録から 9 個の ToDo を抽出し、カレンダーに一括登録する
- 不要なプライベートの予定を削除する
デモで約 6,300 文字の議事録を使用したのは、Gemini の従来の強みである大規模コンテキストウィンドウを利用するためです。長文の議事録であっても分割せずに一度で処理できることを示す狙いがありました。
エージェントは 9 個のタスクを抽出しましたが、そのうち 2 つは会議のアイスブレイク時に話題に上がったプライベートな内容(入学式の話)でした。エージェントがこれらを業務タスクと同列に扱ってカレンダーに登録しました。
デモ後半では「プライベートの予定を削除」と入力するだけで、エージェントが自律的に予定の性質を判断し、該当するイベントのみを削除しました。これは、エージェントが文脈を理解し、カレンダーの内容を自律的に評価した実践的な事例です。
このエージェントの導入効果として、議事録 1 件あたりのカレンダー登録作業を手動10分から自動で1分程度に短縮できます。タスクの抜け漏れを防ぐ実用的なエージェントです。




Google Workspace への応用
今回のデモでは Google Calendar を題材にしましたが、同じ OAuth 2.0 連携の仕組みを使うことで、Google Workspace の各サービスにも応用できます。
Gmail では、エージェントがユーザー本人としてメールボックスに下書きを作成したり、宛先・件名・本文を含むメールを送信できます。たとえばミーティングの議事録をまとめて関係者にフォローアップメールを自動送信するといった使い方が可能です。
Google ドキュメントや Google スライドでは、箇条書きや構成案を渡すだけでドキュメントやスライドの雛型を作成できます。ユーザーはブラッシュアップやクリエイティブな作業に集中できます。
Google ドライブでは、ユーザー自身がアクセス権を持つファイルだけを検索できるため、他者のファイルに触れるリスクがありません。社内ドキュメントをナレッジベースとして RAG 構成と組み合わせる使い方が効果的です。
共通するポイントは、すべての操作がユーザー本人の権限の範囲内で動作することです。

なぜ ADK を選んだのか
エージェント開発のフレームワークには LangChain や CrewAI など複数の選択肢があります。今回 ADK を採用した理由は大きく2つです。
1つ目は、Google Cloud のエコシステムで完結させたかったことです。フロントエンドの Gemini Enterprise、実行基盤の Agent Engine、そして開発フレームワークの ADK をすべて Google Cloud のサービスで統一することで、認証トークンの受け渡しやデプロイがマネージドサービス間でシームレスに連携します。前述のとおり、tool_context.state を通じた OAuth トークンの自動受け渡しは、この統一されたエコシステムがあってこそ実現できる仕組みです。
2つ目は、ADK と OAuth 2.0 を組み合わせた実装事例がまだ少なかったことです。ADK 自体の利用例は増えていますが、Gemini Enterprise の OAuth 連携と組み合わせて Google Workspace を操作するパターンは、2026年4月現在でも公開事例が限られています。今回のセッションとデモを通じて、この実装パターンを広く共有したいという意図がありました。
コードの実装
構成図とソースコードのディレクトリ構成
構成図は以下です。

ソースコードは GitHub で公開しています。
リポジトリのディレクトリ構成は以下です。
. ├── __init__.py ├── agent.py # エージェント定義 ├── tools.py # ツール関数(Calendar API 操作) ├── config.py # 設定値の管理 ├── requirements.txt # 依存パッケージ ├── .env_example # 環境変数のサンプル ├── .gitignore └── README.md
エージェントの定義
以下は ADK でエージェントを定義する agent.py の全体です。49 行でエージェントの定義が完結しています。
# agent.py from google.adk.agents.llm_agent import Agent from . import tools from google.adk.models.lite_llm import LiteLlm root_agent = Agent( name="calendar_agent", model=LiteLlm( "vertex_ai/gemini-3-flash-preview", vertex_location="global" ), description="議事録を解析して Google Calendar にイベントを登録するエージェント", instruction="""あなたは議事録からTodoを抽出して Google Calendar に登録するアシスタントです。 以下の手順で作業してください。 1. ユーザーから議事録を受け取る。 - ファイルパスが渡された場合は read_todo_file ツールでファイルを読み込む。 2. テキスト内容を解析し、議事録からTodoとそれに関係する情報を抽出する: - 日付・時刻(今年は2026年。月/日 の形式なら 2026年として解釈する) - イベントタイトル - 説明(あれば) - 終日イベントかどうか 3. 抽出した各イベントについて create_calendar_event ツールを呼び出して登録する。 - 日時は ISO 8601 形式にする(例: 2026-02-20T14:00:00) - 終日イベントの場合は日付のみ(例: 2026-03-01)、end_datetime は翌日にする - 時間の指定がない場合は終日イベントとして扱う - 終了時刻の指定がない場合は開始から1時間後を終了時刻とする - タイムゾーンは Asia/Tokyo 4. Todo テキストに参加者(メールアドレス)の記載があれば attendees に指定する。 ユーザーが参加者を指定した場合は、そのメールアドレスを追加する。 5. 登録結果をユーザーに報告する。 注意事項: - すべての日時は日本時間 (JST, Asia/Tokyo) を基準とする。 時刻の指定がある場合は日本時間として解釈すること。 - テキストは自由形式。「2/20 14:00 美容院」のようなフォーマットもあれば、 文章形式の場合もある。柔軟に解析すること。 - 日付が曖昧な場合は確認を求める。 """, tools=[ tools.read_todo_file, tools.create_calendar_event, tools.list_calendar_events, tools.update_calendar_event, tools.delete_calendar_event, ], )
Agent クラスの model に LiteLlm で gemini-3-flash-preview(2026年4月現在)を指定しています。instruction にはシステムプロンプトとして議事録の解析手順を記述し、tools に呼び出し可能なツール関数を登録しています。
ADK では LiteLlm を使うことで Gemini 以外のモデル(Claude、GPT など)にも切り替えられます。
- 参考 : ADK LiteLLm ドキュメント
認証トークンの取得とカレンダー API の呼び出し
今回の構成で最も注目すべきポイントは、Gemini Enterprise・ADK・Agent Engine の3つのサービスが連携してユーザーの認証トークンをシームレスに受け渡す仕組みです。
通常、OAuth 2.0 を使ったアプリケーション開発では、トークンの取得・保存・リフレッシュ・有効期限の管理といった複雑な認証フローを開発者自身が実装する必要があります。しかし、Google Cloud のエコシステムではこの課題が解消されています。ユーザーが Gemini Enterprise 上で OAuth 認証を完了すると、取得されたアクセストークンは Agent Engine のセッションに自動で保存されます。ADK のツール関数では、引数として渡される ToolContext の state からそのトークンをわずか1行で取得できます。
この「Gemini Enterprise(認証 UI)→ Agent Engine(トークン管理)→ ADK(トークン利用)」という一連の流れが、Google Cloud のマネージドサービス間で自動的に実現される点が、このエコシステムの大きなメリットです。

以下の get_calendar_service 関数がその実装の核心です。
from google.oauth2.credentials import Credentials from googleapiclient.discovery import build from google.adk.tools import ToolContext def get_calendar_service(tool_context: ToolContext): """ Agent Engine 環境で Google Calendar サービスを認証・生成します。 """ # 1. 環境変数から管理画面で設定した ID を取得 auth_id = os.getenv("AUTH_ID") # 2. トークンの取得を試みる access_token = tool_context.state.get(auth_id) if not access_token: access_token = tool_context.state.get("authentication") # 3. トークンが見つからない場合 if not access_token: raise ValueError( "認証トークンが取得できませんでした。" "チャット画面で Google ログインを完了させているか確認してください。" ) # 4. 取得したトークンでカレンダーサービスを構築 creds = Credentials(token=access_token) return build("calendar", "v3", credentials=creds)
ポイントは tool_context.state.get(auth_id) のわずか1行です。この1行の背後では、以下の処理が Google Cloud のマネージドサービスによって自動的に行われています。
- Gemini Enterprise がユーザーに OAuth 同意画面を表示し、認可コードを取得する
- Agent Engine が認可コードをアクセストークンに交換し、セッションの
stateに保存する - ADK のツール関数が
ToolContext経由でそのトークンを取得する
開発者が実装するのは tool_context.state.get(auth_id) でトークンを取り出し、Credentials に渡す部分だけです。トークンの取得フロー、リフレッシュ、有効期限の管理はすべてマネージドサービス側が担います。
認証フローの実装が、Google Cloud のマネージドサービス連携により数行のコードに集約されています。

以下は、メインのツール関数である create_calendar_event です。
def create_calendar_event( summary: str, start_datetime: str, end_datetime: str, tool_context: ToolContext, description: str = "", timezone: str = "Asia/Tokyo", attendees: list[str] | None = None, ) -> dict: """Google Calendar にイベントを作成する。""" service = get_calendar_service(tool_context) s_dt = start_datetime.strip() e_dt = end_datetime.strip() # 終日イベントかどうかの判定 is_all_day = ("T" not in s_dt) and (":" not in s_dt) if is_all_day: s_dt = s_dt.replace("/", "-") e_dt = e_dt.replace("/", "-") event_body = { "summary": summary, "description": description, "start": {"date": s_dt}, "end": {"date": e_dt}, } else: if " " in s_dt: s_dt = s_dt.replace(" ", "T") if " " in e_dt: e_dt = e_dt.replace(" ", "T") event_body = { "summary": summary, "description": description, "start": {"dateTime": s_dt, "timeZone": timezone}, "end": {"dateTime": e_dt, "timeZone": timezone}, } if attendees: event_body["attendees"] = [{"email": email} for email in attendees] event = service.events().insert(calendarId="primary", body=event_body).execute() return { "status": "success", "event_id": event["id"], "summary": event["summary"], "html_link": event["htmlLink"], }
get_calendar_service(tool_context) を呼び出すことで、ログイン中のユーザーの権限で Google Calendar API を操作しています。終日イベントと時間指定イベントを date と dateTime で区別し、attendees パラメータで参加者の追加にも対応しています。
開発中に遭遇した落とし穴
ADK の State オブジェクト
開発中、認証トークンの中身を確認しようとした際に以下のエラーに遭遇しました。
# やりたかったこと:state の中身を一覧表示したい print(tool_context.state.keys())
上記の様に入力すると、以下の結果になります。
AttributeError: 'State' object has no attribute 'keys'
ADK の State オブジェクトは、標準の Python 辞書(dict)ではなく、Python の MutableMapping プロトコルにも準拠していません。辞書のように値の取得や代入はできますが、.keys() や .items() といった標準的なメソッドは持っていません。これはバグではなく、会話状態の差分追跡を確実に行うための意図的な設計です。
注意すべき点として、ADK には以下2つの state が存在します。
session.statetool_context.state(context.state)
session.state は標準の Python 辞書(dict)であるため .keys() や .items() が通常どおり使えます。
一方、ツール関数の引数として渡されるtool_context.state は前述の State オブジェクトであり、これらのメソッドは使えません。
session.state.keys() は正常に動作するのに tool_context.state.keys() ではエラーになるため、両者を混同するとデバッグ時に混乱を招きます。
ツール関数内では tool_context.state を使うため、.get() メソッドで安全に値を取り出す必要があります。
# 正しい方法:.get() で安全に取得
access_token = tool_context.state.get(auth_id)
操作は .get() や直接代入(tool_context.state[key] = value)に留めることが推奨されます。ADK を使ったエージェント開発を始める方は、この仕様を事前に把握しておくとデバッグ時間を節約できます。
LiteLLM のセキュリティに関する注意
LiteLLM v1.82.7 / v1.82.8 は、サプライチェーン攻撃(TeamPCP)により侵害されました(2026年3月24日)。本デモの GitHub リポジトリのサンプルコードでは v1.83.0(攻撃後の正規リリース、2026年3月31日公開)にピン留めしています。
詳細は以下を参照してください。
Gemini Enterprise へのデプロイ
作成したエージェントを Agent Engine にデプロイした後、Gemini Enterprise のコンソールからエージェントを追加できます。画面からの操作のみでデプロイが完了します。
ユーザーごと、またはグループごとにエージェントの利用権限を管理することも可能です。組織全体への安全な展開が実現できます。


参考リンク
- 参考 : Agentic AI Summit 2026 Spring
- 参考 : 登壇資料
- 参考 : G-gen-Tech-Blog/agentic-ai-summit-2026-spring-session-report(ソースコード)
以下の動画でセッションの実演をご覧いただけます。
奥田 梨紗(記事一覧)
クラウドソリューション部データインテリジェンス課
Google Cloudの可能性に惹かれ、2024年4月G-genにジョイン。
Google Cloud Partner Top Engineer 2025&2026
