はじめに
この記事は、NRI xPalette Advent Calendar 2025の23日目です!
皆さんは年始に目標を立てていますか?
私は毎年1月に100個の目標を立てることにしているのですが、12月時点で未達成の目標が60個もあることが分かりました。![]()
心安らかに年越しを迎えるために、
「目標の手助けをしてくれる4種類のWebサービス」
を、GoogleのAIエージェント「Antigravity」の力を借りて爆速で開発し、無事いくつかの目標を達成することが出来ました。
今回はその開発の記録や、使用したAWSアーキテクチャ、構成の改善点についてご紹介します。
Antigravityとは
AntigravityはGoogleが開発した、AIエージェント統合型の開発環境です。
Antigravityは「エージェントファースト」のプラットフォームとして設計されており、複雑なエンジニアリングタスクの計画、実行、検証、反復処理を自律的に行ってくれます。
今回はモデルにGemini 3 Pro(High)を使用して開発を行いました。
インストールや使い方についてはGoogle公式のAntigravityスタートガイドをご参照ください。
サービス概要と役割分担
実際に作成したサービス概要と、Antigravityとの役割分担について記載します。
人間が担当した部分
10個の目標を達成するために開発するサービスをざっくりと考えます。
このイメージをもとに、Antigravityには、とりあえずその時点で頭の中にあるありったけの要件を伝えます。
例えば、画像右上の「肉じゃがレシピを英語でマスターするゲーム」について伝えた要件は以下になります。
肉じゃがのレシピを英語で覚えるためのゲームを作ってください。以下の要件を満たしてください。
- 最初に肉じゃがのレシピを表示する。レシピは何ステップかに分けられている
- 覚えたら画面をクリックして次に進む
- ユーザーが肉じゃがのレシピを英語で話すと、猫のシェフがレシピをもとに正しいかどうかを判定する
- 判定ロジックではBedrockが正しいかどうか判定する
- 合っていたら次のステップに進める
- 全てのステップを間違いなく言えたらクリア、おいしそうな肉じゃがが表示される
- 3回間違えたらゲームオーバーで焦げた肉じゃがが表示される
このように、人間側は「どんなサービスを作りたいか」「どんなAWSサービスを取り入れたいか」の大まかなイメージを提案しました。
Antigravityが担当した部分
人間側の要件概要を受け取り、Antigravityは以下の順番で作業を進めてくれます。
なお、ハルシネーションによる予期せぬ実行や破壊的変更を防ぐため、Antigravityのコマンド実行権限(ターミナルコマンドの実行をどこまでAntigravityに任せるか)はOffで実行しました。
Antigravityでは以下の3つのコマンド実行権限を選択できます。
-
Off:ターミナルコマンドを自動実行しない(ただし、許可リストにあるコマンドは自動実行できる) -
Auto:ターミナルコマンドを自動実行するかエージェントが判断する -
Turbo常にターミナルコマンドを自動実行する(ただし、拒否リストにあるコマンドは自動実行しない)
詳細は Google Antigravityの概要-10.エージェントの保護 をご参照ください。
-
計画フェーズ (Planning)
人間から受け取った漠然としたアイデアを、実行可能なタスクと技術設計に落とし込むフェーズです。このフェーズでは、以下の2つの成果物を作成してくれます。-
task.md(タスクリスト)
やるべきことをリスト化し、進捗状況(未着手/進行中/完了)を管理する -
implementation_plan.md(実装計画書)
「どのAWSサービスを使うか」「データ構造はどうするか」などを提案する
-
-
設計・構築フェーズ (Architecture & Build)
計画に基づき、実際のコードとインフラを作成するフェーズです。- インフラコード
CloudFormationの作成 - アプリケーションコード
html, css, javascriptなどのソースコード本体 - 構築手順書
各サービスを構築する手順書
(例)AWS Cognito x Google Calendar 連携部分の構築手順書
# AWS Cognito x Google Calendar 連携 構築手順書 AWSコンソールとGoogle Cloudコンソールを使って、手動で環境を構築するための詳細ガイドです。 ## 前提 * AWSアカウントとGoogleアカウントを持っていること。 * Frontendのコード ([index.html](file:///C:/Users/xxxx/.gemini/antigravity/scratch/index.html), [script.js](file:///C:/Users/xxxx/.gemini/antigravity/scratch/script.js)) が手元にあること。 --- ## Step 1: Google Cloud Platform (GCP) の設定 1. **プロジェクト作成**: * [Google Cloud Console](https://console.cloud.google.com/) で新しいプロジェクトを作成。 2. **APIの有効化**: * メニュー「APIとサービス」>「ライブラリ」を選択。 * "Google Calendar API" を検索して「有効にする」。 3. **OAuth同意画面の作成**: * メニュー「APIとサービス」>「OAuth同意画面」。 * User Type: **「外部 (External)」** を選択して作成。 * アプリ名: `Neko Game` など入力。ユーザーサポートメール: 自分のメール。 * **スコープ**: 「スコープを追加または削除」から `.../auth/calendar.events` (Google Calendar API) を追加。 * **テストユーザー**: 自分のGoogleメールアドレスを追加。 4. **OAuthクライアントIDの作成**: * メニュー「認証情報」>「認証情報を作成」>「OAuthクライアントID」。 * アプリケーションの種類: **「ウェブアプリケーション」**。 * 名前: `Cognito Client`。 * **承認済みのリダイレクトURI**: 一旦空欄で「作成」。 * **※重要**: 表示される **「クライアントID」** と **「クライアントシークレット」** をメモする。 --- ## Step 2: AWS Cognito の設定 1. **ユーザープールの作成**: * AWSコンソール > Cognito > 「ユーザープールを作成」。 * **Step 1**: 「フェデレーテッドアイデンティティプロバイダー」> **「Google」** にチェック。 * **Step 2 (セキュリティ)**: デフォルトのまま「次へ」。 * **Step 3 (サインアップ)**: デフォルトのまま「次へ」。 * **Step 4 (Eメール)**: 「CognitoでEメールを送信」を選択して「次へ」。 * **Step 5 (統合)**: * プール名: `NekoNikujagaPool`。 * **ホストされたUI**: 「CognitoのホストされたUIを使用」にチェック。 * **ドメイン**: 「Cognitoドメインを使用する」> 任意のプレフィックスを入力 (例: `neko-app-1234`)。 * **アプリクライアント**: 名前 `NekoWebClient`、**「クライアントシークレットを生成」にチェック**。 * **許可されているコールバックURL**: 仮で `http://localhost:3000` と入力。 * 「ユーザープールを作成」。 2. **Google連携の設定 (IdP)**: * 作成したプールを開く > 「サインインエクスペリエンス」タブ。 * 「フェデレーテッド...」の「Google」をクリック。 * GCPでメモした **クライアントID** と **クライアントシークレット** を入力。 * **承認されたスコープ**: `profile email openid https://www.googleapis.com/auth/calendar.events` * 「変更を保存」。 3. **アプリクライアントの詳細設定**: * 「アプリケーションの統合」タブ > 下部の「アプリクライアントと分析」> クライアント名をクリック。 * 「ホストされたUI」セクションの「編集」をクリック。 * **OAuth 2.0 権限タイプ**: **「暗黙的な付与 (Implicit grant)」** を選択。 * **OpenID Connect スコープ**: `email`, `openid`, `profile` を選択。 * 「変更を保存」。 --- ## Step 3: GCP側のリダイレクト設定 (戻り作業) 1. AWS Cognitoの「アプリケーションの統合」タブで **「Cognitoドメイン」** をコピー (例: `https://neko-app.auth...`)。 2. GCPコンソールに戻る > 「認証情報」 > 作成したクライアントIDを編集。 3. **承認済みのリダイレクトURI** に以下を追加: * `https://<Cognitoドメイン>/oauth2/idpresponse` 4. 「保存」。 --- ## Step 4: バックエンド (Lambda & API Gateway) の設定 1. **Lambda関数の作成**: * AWSコンソール > Lambda > 「関数の作成」。 * 関数名: `neko-calendar-worker`。 * ランタイム: `Python 3.12`。 * コード: 別途用意した lambda_cognito_calendar.pyの内容を貼り付け > 「Deploy」。 2. **API Gatewayの作成**: * AWSコンソール > API Gateway > 既存のAPIを選択 (または新規作成)。 * 「リソースの作成」: `/calendar`。 * 「メソッドの作成」: `POST` > 統合タイプ「Lambda関数」 > `neko-calendar-worker` を選択。 * **CORSの有効化**: リソースを選択して「CORSの有効化」。 3. **Cognitoオーソライザーの設定 (重要)**: * API Gatewayメニューの「認可 (Authorizers)」を選択。 * 「オーソライザーの作成」: * 名前: `CognitoAuth` * タイプ: Cognito * Cognitoユーザープール: `NekoNikujagaPool` を選択。 * トークンのソース: `Authorization` * リソースに戻り、`POST` メソッドの「メソッドリクエスト」をクリック。 * **「認可」** の設定を `CognitoAuth` に変更。 * **APIのデプロイ**: 「APIをデプロイ」を実行。 --- ## Step 5: フロントエンドの更新 1. script.js の冒頭の設定値を更新: * `COGNITO_DOMAIN`: AWS Cognitoのドメイン。 * `CLIENT_ID`: AWS CognitoのアプリクライアントID。 * `REDIRECT_URI`: `http://localhost:3000` (またはCloudFrontのURL)。 * `API_URL`: デプロイしたAPI GatewayのURL。 2. **※本番公開時の注意**: * CloudFrontで公開する場合、Cognitoの「コールバックURL」と script.js の `REDIRECT_URI` をCloudFrontのURLに変更してください。 以上で構築完了です。ボタンを押してログイン~カレンダー登録ができるか確認してください。 - インフラコード
-
検証フェーズ (Verification)
作成したアプリケーションが正しく動作するかを確認するフェーズです。- デモ動画 / スクリーンショット
ブラウザを実際に操作し、動作している様子を記録する
※詳細は以下で記載するAntigravityを活用して便利だった機能:Browser Agentによる修正をご参照ください。 - walkthrough.md (検証レポート)
テストした部分、テストの結果、バグ修正の履歴などを記録する
- デモ動画 / スクリーンショット
-
ドキュメント化フェーズ (Documentation)
開発終了後にシステム構成を理解し、運用するためのドキュメントを作成するフェーズです。
※1~3の成果物はデフォルトで作成されますが、以下の2ドキュメントは指示を出して作成してもらったものとなります。-
GAME_CONSTRUCTION_MANUAL.md
環境構築、デプロイ手順、設定変更の方法などをまとめたマニュアル -
ARCHITECTURE.md
システムの全体像、データの流れ、コンポーネント間の関係を図解したもの
-
Antigravityを活用して便利だった機能:Browser Agentによる修正
AntigravityにはBrowser Agentという機能があり、独立したChrome環境でクリックや入力によるブラウザの精密な制御、DOMや画像認識を通じたページ状態の解析、操作プロセスの動画記録などを自律的に遂行してくれます。
ボタンが反応しない、次の画面に遷移しない、等の不具合が発生した場合には、Antigravityに「実際にサービスを動かしてどこがおかしいか修正して」と指示し、出力してもらった修正レポートを見ながら対応を行いました。
例えば、以下のようなボタンを押すと数字が増えるアプリについて、「デモンストレーションを撮って」と指示すると、アプリを開く→アプリを動かす→デモ動画(下記のもの)を撮影し保存する、までの一連の作業を自動で行ってくれます。
※クリック速度は人の手で行うよりは遅めです。
また、このアプリについて「画面のincrementボタンを押しても数字が増えない」というバグが発生した際には、Antigravity自身がアプリの操作を行い、不具合の検出や証跡の取得、原因分析と修正を行ってくれます。
さらに、それらを以下のようにレポートとしてまとめてくれます。
修正レポートの例
Browser Agent デモレポート: アプリの自律的修正 (Self-Healing App)
「バグ修正と動作検証」のデモンストレーション結果報告書です。エージェントがWebアプリケーションの不具合を自律的に発見し、ソースコードを修正、その後動作確認を行いました。
1. フェーズ 1: 診断 (不具合の検出)
目的: 「Broken Counter」アプリの動作テスト。 アクション: エージェントがアプリにアクセスし、「Increment」ボタンをクリック。 観測結果: カウンターの数字が 0 のまま変化しませんでした。調査の結果、JavaScriptのエラー(null参照)によりボタンクリックが機能していないことが判明しました。
診断時のスクリーンショット: カウントアップ失敗
証拠画像: 操作後もアプリの状態(数字)が変わっていません。
2. フェーズ 2: 修正 (Repair)
原因分析:
script.js
ファイル内で、イベントリスナーをID btn-increase の要素に追加しようとしていましたが、実際のHTMLボタンのIDは btn-increment でした。IDの不一致が原因です。
修正内容: JavaScriptを修正し、正しい要素IDをターゲットにするように変更しました。
/* C:\Users\xxxx\.gemini\antigravity\scratch\buggy_demo\script.js */
// 修正前 (BEFORE)
const button = document.getElementById('btn-increase'); // 存在しないIDのため null が返る
// 修正後 (AFTER)
const button = document.getElementById('btn-increment'); // 正しいボタンを取得
3. フェーズ 3: 検証 (成功確認)
目的: 修正が正しく機能するか確認。 アクション: アプリをリロードし、再度「Increment」ボタンをクリック。 観測結果: カウンターが正常に 1 に更新されました。
検証時のスクリーンショット: カウントアップ成功
証拠画像: カウンターが正常に 1 になりました。
結論
アプリケーションのロジックは修正され、正常動作が確認されました。エージェントは「UIの不具合を目視で確認」し、「ローカルのコードを編集して修正」し、「修正結果を視覚的に検証」する一連のプロセスを完了しました。
このように、Antigravityは要件の整理から構築、検証、運用手順書の作成まで一貫して担当してくれます。
Antigravityとの共同作業により、最終的に4種類のWebサービスが完成しました。
以下ではそれぞれのサービスの詳しい構成について記載していきます。
肉じゃがシミュレーション
「和食を一品マスターする」、「簡単な英会話を習得する」という2つの目標を同時に達成するためのサービスです。
遊び方としては、
- 肉じゃがのレシピ(7ステップ)が英語で流れるので、覚える
- 肉じゃがのレシピを英語で話す
- 全部言えたらクリア!
という非常にシンプルな作りになっています。
ゲーム開始前に表示されるレシピはブラウザ側で見本の音声も流してくれる仕様となっています。
構成
構成の特徴として、バックエンドにBedrockを導入し、ユーザーが正しいレシピを正しい英語で言えているかどうかを判定させています。
モデルは比較的低予算で試すことのできるClaude 3 Haikuを使用しました。
サービス全体の処理の流れは以下になります。
0. 音声認識 (Frontend)
-
ユーザーが発話した内容を、ブラウザの Web Speech API が認識し、テキストデータ(
transcript)に変換するWeb Speech APIは、ブラウザだけで音声認識(文字起こし)や音声合成ができる標準機能です。
2012年にGoogleの開発者が中心となって提案し、W3C (World Wide Web Consortium) というWeb技術の標準化団体によって策定されました。
アプリやゲームなどでマイクを使った音声入力やテキストの読み上げを行いたい場合に利用されます。
詳細はMDN Web Docsをご確認ください。
Googleのデモページ(Chromeのみ対応)でデモを行うこともできます。
::
-
判定リクエスト送信 (Frontend)
-
script.jsが、transcript、レシピの種類、ステップID(ユーザーが発話した内容が肉じゃがレシピの中の何番目のSTEPなのかを特定するためのID)を以下のJSON形式で API Gateway に送信 (POST) する
{ "transcript": "Add the onions!", "recipe_id": "nikujaga", "step_id": 1 } -
-
Lambda起動 (Backend)
- リクエストを受け取った API Gateway が、バックエンドのLambda関数を起動する
-
プロンプト構築 (Backend)
- Lambdaは
recipe_id,step_idをキーにしてDynamoDBから「正解のセリフ」や「必須キーワード」を取得する - さらに、Bedrock Prompt Managementから「あなたは料理の先生です...」というプロンプトのテンプレートを取り出す
- これらと
transcriptを組み合わせて、AIへの指示(最終的なプロンプト)を作成し、Bedrockに渡す
- Lambdaは
-
AIによる判定と結果返却 (Backend → Frontend)
- Bedrockが内容を評価し、判定結果のJSONを生成する
- 結果は Lambda → API Gateway を経由してブラウザに戻され、画面に「YES!!」といったメッセージが表示される
{ "is_correct": true, "score": 95, "reason": "玉ねぎという単語が入っており完璧です" }
モヒートレシピの暗記
「カクテルのレシピを一つ覚える」という目標を達成するために実装した機能です。
こちらも遊び方としては至ってシンプルで、
- 表示されているモヒートのレシピを覚え、全て覚えたら「レシピを覚えた!」ボタンを押す
- 5つの空欄に、モヒートに使う材料と分量を全て記入する
- 全部入力できたらクリア!
という作りです。
構成
本ゲームはCloud Front+S3の構成でWebサイトをホストしており、SPA(シングルページアプリケーション)としてクライアントサイド主体で動作する構成をとっています。
サーバー側への通信は、ページ描画に必要なHTMLやJavaScriptなどの静的ファイルの取得時のみに限定され、正誤判定などのゲームロジックは全てブラウザ上で実行されます。
これにより、回答のたびにサーバーへ問い合わせる必要がなくなり、ユーザーの操作に対して高速にレスポンスすることが可能になっています。
シングルページアプリケーション(SPA)は、 最初に1枚のHTMLページだけを読み込み、その後はページ遷移を行わずにJavaScript APIを通じて必要な部分だけを書き換えるWebアプリの仕組みです。
オフラインでも使用可能、高速なレスポンスが可能、等の利点があります。
処理の流れは以下になります。
-
URLアクセス (Frontend)
- ユーザーがゲームのURL(CloudFrontのURL)にアクセスする
-
データ取得 (Frontend)
- S3に格納されている
index.html(DOM構造の定義とリソースのエントリーポイント),script.js(ビジネスロジックとDOM操作の実行)をCloudFront経由でブラウザに返す
- S3に格納されている
-
回答操作 (Frontend)
- ユーザーは材料を入力する。正誤判定は
script.js内に記載された判定ロジックと正解データを用いて行う
- ユーザーは材料を入力する。正誤判定は
チョコレート検定一問一答
「チョコレート検定を受験する」という目標達成のために、チョコレート検定の問題にひたすら答えていく無限クイズゲームです。
遊び方としては以下になります。
- チョコレートに関する4択問題が出題されるので正解を選ぶ
- 正解したら次の問題に行くので、ひたすら解く
繰り返し解くことで確実に記憶に定着させることを狙いとするため、クリア条件は設けず、ひたすら問題を解きます。
構成
処理の流れとしては以下のようになります。
-
クイズデータの取得 (画面ロード時)
-
script.jsがinitQuiz()関数を実行し、API Gateway に対してGETリクエストを送信する
-
-
データ取得 (Backend)
- API Gateway が Lambda関数を起動し、LambdaがDynamoDBからクイズ一覧を取得したのちデータをJSON形式 で返す
-
出題開始 (Frontend)
- ブラウザがJSONデータを受け取り、内部の変数 (
quizQueue) に保存し、最初の問題を画面に表示する
- ブラウザがJSONデータを受け取り、内部の変数 (
-
回答操作 (Frontend)
- ユーザーが選択肢ボタンをクリックすると、
script.jsが、正解かどうかを即座に判定する(正解データは既にブラウザにロード済みのため、都度サーバー通信は発生しない)
正解なら「Correct!」、不正解なら「Wrong!」と表示し、次の問題へ進む
- ユーザーが選択肢ボタンをクリックすると、
2026年のGoogleカレンダーに予定をランダムに登録
今年中の達成が難しい目標は思い切って来年に回しちゃいましょう!
2026年のGoogleカレンダーの土日のどこかに予定をランダムに登録しておくためのサービスです。
使い方としては以下になります。
- Googleログインを行う
- ログイン後、予定の横にある「カレンダーに登録する」ボタンを押す
- 2026年の土日から1日がランダムに選ばれ、Googleカレンダーに予定が登録される
構成
処理の流れとしては以下になります。
-
ユーザー認証 (Frontend)
- ユーザーが「Googleでログイン」ボタンをクリックし、Cognitoを経由してGoogleアカウント情報を入力する
認証成功後、CognitoがCognito JWTを発行してブラウザに返し、同時にGoogleから取得したOAuth 2.0 トークンをCognito内部のユーザー属性(custom:google_access_token)に保存する
- ユーザーが「Googleでログイン」ボタンをクリックし、Cognitoを経由してGoogleアカウント情報を入力する
-
カレンダー登録リクエスト (Frontend)
- ブラウザが、予定データ(日付・タイトル)と、取得した Cognito JWT を載せて、API Gateway に送信 (
POST) する
Header: Authorization: Bearer {Cognito Token} Body: { date: "2026-05-02", title: "10万歩歩く" } - ブラウザが、予定データ(日付・タイトル)と、取得した Cognito JWT を載せて、API Gateway に送信 (
-
認証と認可 (API Gateway)
- API Gateway(Cognito Authorizer)がCognito JWTの署名を検証し、有効なユーザーである場合のみ、後続のLambda関数を実行する
-
Google API実行 (Backend)
- Lambdaが、リクエストに含まれるCognito JWTを使ってCognitoの
GetUserを実行し、ユーザー属性からOAuth 2.0トークン(custom:google_access_token)を取り出す
GetUserは、ユーザーのアクセストークンを元に、そのユーザーの登録情報(属性、設定値など)を取得するCognitoの標準機能です。
今回は、Cognitoに保存されているcustom:google_access_tokenをLambdaが取り出すために使用しています。
GetUserの詳細は AWSの公式ドキュメントをご参照ください。- 取り出したOAuth 2.0トークンを用いてGoogle Calendar APIを呼び出し、予定を作成する(※自動リフレッシュ機能はないため、トークン期限切れ時はユーザーに再ログインを求める)
- Lambdaが、リクエストに含まれるCognito JWTを使ってCognitoの
構成を確認すると、今回は2種類のトークンが存在することが分かります。
- Cognito JWT:Cognitoがブラウザに与えるトークン。ブラウザの身分証明書のようなもの。リクエスト送信時にブラウザはCognito JWTをAPI Gatewayに提示し、API GatewayはCognitoにこのトークンが本物かを確認しに行く。本物だったらリクエストを通す。
- OAuth 2.0アクセストークン:GoogleがCognitoに与えるトークン。このトークンを使ってLambdaがGoogleカレンダーにアクセスし、予定登録を行う。
OAuth 2.0アクセストークンの詳細については、Google Identity-OAuth 2.0 を使用して Google API にアクセスする をご参照ください。
開発期間とかかった費用
開発期間について、4つのサービスは20時間程度で完成しました。
費用について、Antigravity、各AWSサービスは無料枠の範囲で使用したため、料金は発生しませんでした。
※Gemini 3 Pro (High)のレートリミット制限に引っ掛かり、途中でGoogle AI Pro(月額2,900円)に加入しましたが、今回は初回利用のため1か月の無料枠を使うことができました。
目標は達成できたのか
各ゲームで遊びまくることで、無事美味しい肉じゃがとモヒートを作ることが出来ました!
また、Googleカレンダーへの予定登録もばっちりです。これで来年は予定を必ず達成できることでしょう。
チョコレート検定は公式問題集の問題15問を完全に解けるようになりました!
来年の試験に向けて引き続き勉強を続けたいと思います。
さらに、記事の執筆中にAWS Certified Data Engineer - Associateを取得することが出来ました!
要件に適した構成を検討しながらサービスを作ったり、記事を書いて仕様や各AWSサービスの理解を深めたことが合格に繋がりました。
これで安心して年を越すことが出来そうです!
まとめ
Antigravityの力を借りてわずか1日程度で4つのWebサービスを作成し、今年の目標を幾つか達成することが出来ました。
今年も残り僅かですが、皆さんも是非Antigravityと一緒に今年やり残したことを達成してみてはいかがでしょうか。














