Google Antigravity を使用して構築する

1. はじめに

Google Antigravity は、Google のエージェント IDE です。Antigravity を使ってみる Codelab では、Antigravity の基本を学ぶことができます。この Codelab では、Antigravity を使用して実際のアプリケーションを構築します。簡単なウェブ調査から、フルスタック アプリケーションとエンタープライズ クラスの単体テストの生成まで行います。

前提条件:

  • Google Antigravity がインストールされ、構成されている。
  • Google Antigravity の基本知識。Codelab の **Google Antigravity を使ってみる** を完了することをおすすめします。

2. ユースケースについて

Antigravity の基本を理解したので、実際のユースケースを見ていきましょう。Antigravity はエージェント ファーストのプラットフォームです。つまり、ほとんどの場合、エージェントに指示を出すだけで、エージェントは単独でタスクを実行し、必要に応じて権限を要求し、アーティファクトを生成して、タスクが完了したことを通知します。そのため、以下の各ユースケースで、エージェントの会話のすべての出力を生成することはできません。手順と、予想される結果の必要なスクリーンショットをいくつか共有しますが、結果は多少異なる場合があります。

対象となるユースケースは、外部サイトを使用したいくつかのタスクの自動化から、プロジェクトの単体テストケースの生成と検証、完全なウェブサイト開発まで多岐にわたります。始めましょう。

3. ニュース ハイライト

これはシンプルなユースケースですが、ウェブブラウザを使用してウェブサイトにアクセスし、情報を抽出してアクションを実行し、データをユーザーに返すことができます。

ここでは、Google ニュースのサイトにアクセスして情報を抽出します。任意のサイトで簡単に試して、どのように動作するかを確認できます。

まず、news-hightlights という名前のフォルダを作成して、最初から始めます。Antigravity で Agent Manager に切り替え、Add Workspace ボタンを使用して、新しく作成したフォルダをワークスペースとしてインポートします。

3935bb43b5112f71.png

新しくインポートした news-highlights ワークスペースで新しい会話を開始します。

840c9d014bd4b8d8.png

次の指示を入力します。 "「news.google.com にアクセスして、現在のハイライトを取得してください。」"

8513d489eea0b014.png

これにより、エージェント プロセスが開始され、ブラウザを起動する必要があることが判断されます。思考プロセスに注意して、エージェントがどのように作業を進めるかを確認してください。問題がなければ、Antigravity ブラウザが起動し、以下に示すようにサイトにアクセスします。サイトの周りの青い枠線は、エージェントがブラウザを制御し、サイトを移動して情報を取得していることを示しています。

9d594588f2ffe6bc.png

作業が完了すると、以下に示すようにアーティファクトが生成されます。

dc6cf4e7d8425df8.png

エージェントによる実行例を以下に示します。

fb7397cd2cce0682.png

左側には思考プロセスが表示されます。ポイントをスクロールして、再生やその他のデータを表示することもできます。

試してみたいこと

  • これを理解したら、Agent にアクセスしてデータを取得または要約してもらいたいウェブサイトを選択します。ダッシュボードとグラフがあるウェブサイトを選択して、いくつかの値を選択するように依頼します。
  • 次のプロンプトを試します。Visit https://docs.cloud.google.com/release-notes and get me a summary of the release notes, categorized by product.

4. Python + Flask で動的ウェブサイトを生成する

次に、完全なウェブ アプリケーションを生成します。作成するウェブ アプリケーションは、複数のスピーカーが 1 日を通して講演する 1 日の技術イベントに関する情報を提供するサイトです。

もう一度、conference-website という名前の新しいフォルダを作成します。Agent Manager で、conference-website ワークスペースをインポートして選択していることを確認します。また、エージェントが実行前に計画を立てるように、Planning モードを追加します。

次のプロンプトを入力します。

I would like to generate a website that is a 1-day technical conference informational site.

The website should have the following functionality:
        1. A home page that shows the current date, location, schedule and time table.
        2. The 1-day event is a list of 8 talks in total.
        3. Each talk has 1 or 2 max. speakers. 
        4. A talk has an ID, Title, Speakers, Category (1 or 2), Description and time of the talk.
        5. Each speaker has a First Name, Last Name and LinkedIn url.
        6. Allow for users to search by category, speaker, title.
        7. Give a lunch break of 60 minutes.
        8. Use dummy data for events and speakers, come up with a schedule, the event is about Google Cloud Technologies.
        9. Tech Stack: Python and Flask framework on server side. Front-end is basic HTML, CSS and JavaScript. 
        10. Test out the site on your own for all functionality and provide a detailed README on how to setup, run and make any further changes. 
11. Launch the web application for me to review. 

上記のプロンプトを入力して会話を開始します。

エージェントがタスクを実行すると、アーティファクトの作成が開始されます。

  • タスク アーティファクト
  • 実装アーティファクト
  • チュートリアル アーティファクト

以下のタスク アーティファクトは、エージェントに与えられたタスクに基づいて、エージェントが実行すべきタスクの最初のシーケンスです。実行時のスクリーンショットの例を以下に示します。

c95d82e1c040698f.png

[実装計画] アーティファクトをクリックします。スクリーンショットの例を以下に示します。

632169a236bc62cc.png

最後に、[チュートリアル] アーティファクトがあります。以下に示すように、エージェントが行ったすべての操作が含まれています。

e3f6152d6f54d4f9.png

サーバーが起動し、URL が提供されました。URL をクリックすると、アプリケーションが表示されます。スクリーンショットの例を以下に示します。

abf879f2ce53d055.png

[**エディタ**] に切り替えると、Python Flask アプリケーションが生成されるフォルダが表示されます。また、右側に Agent mode のタグが表示され、そこから会話を続けることもできます。

b0fea8aa65c3a1c5.png

イベントに講演を追加するとします。エディタとエージェント パネルで、「Add two more talks to the schedule」などの指示を入力します。

これにより、エージェントは要件を分析し、タスクと実装計画を更新し、更新された機能も検証します。会話の例を以下に示します。

ba8455e6f68973e9.png

必要に応じて、Agent Manager に戻ることができます。このプロセスでは、Agent Manager からエディタに切り替え、必要に応じて変更を加えるなどのプロセスを理解できます。

試してみたいこと

  • アプリケーションに追加する機能を追加します。エージェントに詳細を提供し、タスクリスト、実装計画の順に変更してタスクを実行する方法を確認します。
  • エージェントにアプリケーションの README または詳細なドキュメントを生成するように依頼します。

5. シンプルな生産性向上アプリを生成する

シンプルなポモドーロ タイマー ウェブ アプリケーションを生成します。

pomodoro-timer フォルダを作成します。Agent Manager で、pomodoro-timer ワークスペースをインポートして選択していることを確認します。次のプロンプトで始めましょう。

Create a productivity app that features a Pomodoro timer. Give a calm and aesthetic look to the application.

タスクリストと実装計画を作成し、それらを実行する方法を確認します。フローに注意してください。確認を求めるメッセージが表示される場合があります。実行例を以下に示します。

5be0a668e5a67d85.png

この場合、Antigravity ブラウザも起動し、独自のテストを実行して、テストが成功したことを確認します。生成されたものの 1 つに、検証の動画を含むメディア アーティファクト があります。これは、テスト内容を確認するのに最適な方法です。スタイルが適用されなかったため、スタイルの変更を提案したところ、変更できました。

完成したアプリは次のようになり、非常に優れています。

c9ab6bca97a51a8c.png

アプリケーションにタイマーの画像を追加してみましょう。必要な操作は、以下に示すようにフォローアップ指示を出すだけです。

Add an image to the application that displays a timer.

これにより、エージェントはタスク アーティファクトに新しいタスクを追加しました。

498dd946d4e9ae55.png

タスクを実行すると、画像が生成されました。

c291da9bdb37ff96.png

最終的に、アプリにはリクエストした画像が表示されました。

de8f418ba8e4600d.png

試してみたいこと

  • アプリケーションの砂時計アイコンの背景が透明ではありません。エージェントに透明にするように指示してみてください。
  • 生成するアプリケーションのバリエーションをいくつか試してみてください。スタイルや画像を試したり、変更をリクエストしたりします。

6. 単体テスト、モックスタブを生成してテストを検証する

ここで試す最後のユースケースは、既存の特定のコードファイルの単体テストを生成し、エージェントにテストを実行して検証してもらうことです。

このため、以下に示すように、1 つの Python ファイルを含むワークスペースを用意します。

from typing import Dict

# --- Custom Exceptions ---
class InventoryShortageError(Exception):
    """Raised when there is not enough item stock."""
    pass

class PaymentFailedError(Exception):
    """Raised when the payment gateway rejects the transaction."""
    pass

class InvalidOrderError(Exception):
    """Raised when the order violates business rules."""
    pass

# --- External Service Interfaces (To be Mocked) ---
class InventoryService:
    def get_stock(self, product_id: str) -> int:
        """Connects to DB to check stock."""
        raise NotImplementedError("Real connection required")

    def decrement_stock(self, product_id: str, quantity: int):
        """Connects to DB to reduce stock."""
        raise NotImplementedError("Real connection required")

class PaymentGateway:
    def charge(self, amount: float, currency: str) -> bool:
        """Connects to Stripe/PayPal."""
        raise NotImplementedError("Real connection required")

# --- Main Business Logic ---
class Order:
    def __init__(self, 
                 inventory_service: InventoryService, 
                 payment_gateway: PaymentGateway,
                 customer_email: str,
                 is_vip: bool = False):
        
        self.inventory = inventory_service
        self.payment = payment_gateway
        self.customer_email = customer_email
        self.is_vip = is_vip
        self.items: Dict[str, Dict] = {} # {product_id: {'price': float, 'qty': int}}
        self.is_paid = False
        self.status = "DRAFT"

    def add_item(self, product_id: str, price: float, quantity: int = 1):
        """Adds items to the cart. Rejects invalid prices or quantities."""
        if price < 0:
            raise ValueError("Price cannot be negative")
        if quantity <= 0:
            raise ValueError("Quantity must be greater than zero")

        if product_id in self.items:
            self.items[product_id]['qty'] += quantity
        else:
            self.items[product_id] = {'price': price, 'qty': quantity}

    def remove_item(self, product_id: str):
        """Removes an item entirely from the cart."""
        if product_id in self.items:
            del self.items[product_id]

    @property
    def total_price(self) -> float:
        """Calculates raw total before discounts."""
        return sum(item['price'] * item['qty'] for item in self.items.values())

    def apply_discount(self) -> float:
        """
        Applies business logic:
        1. VIPs get flat 20% off.
        2. Regulars get 10% off if total > 100.
        3. No discount otherwise.
        """
        total = self.total_price
        
        if self.is_vip:
            return round(total * 0.8, 2)
        elif total > 100:
            return round(total * 0.9, 2)
        
        return round(total, 2)

    def checkout(self):
        """
        Orchestrates the checkout process:
        1. Validates cart is not empty.
        2. Checks stock for all items.
        3. Calculates final price.
        4. Charges payment.
        5. Updates inventory.
        """
        if not self.items:
            raise InvalidOrderError("Cannot checkout an empty cart")

        # 1. Check Inventory Logic
        for product_id, data in self.items.items():
            available_stock = self.inventory.get_stock(product_id)
            if available_stock < data['qty']:
                raise InventoryShortageError(f"Not enough stock for {product_id}")

        # 2. Calculate Final Price
        final_amount = self.apply_discount()

        # 3. Process Payment
        try:
            success = self.payment.charge(final_amount, "USD")
            if not success:
                raise PaymentFailedError("Transaction declined by gateway")
        except Exception as e:
            # Catching generic network errors from the gateway
            raise PaymentFailedError(f"Payment gateway error: {str(e)}")

        # 4. Decrement Stock (Only occurs if payment succeeded)
        for product_id, data in self.items.items():
            self.inventory.decrement_stock(product_id, data['qty'])

        self.is_paid = True
        self.status = "COMPLETED"
        
        return {"status": "success", "charged_amount": final_amount}

上記の Python ファイルがローカルの新しいフォルダにあり、Antigravity でワークスペースとして読み込まれていることを確認します。

これはシンプルな注文サービスで、checkout 関数に次の主な機能があります。

  1. カートが空でないことを検証します。
  2. すべてのアイテムの在庫を確認します。
  3. 最終価格を計算します。
  4. 支払いを請求します。
  5. 在庫を更新します。

エージェントに、単体テストケースの生成、モック実装の提供、テストの実行を割り当てて、テストが成功することを確認します。

特定のワークスペース フォルダを開くと、@ 記号を使用してファイルを参照できるようになりました。たとえば、次のようにします。

8368856e51a7561a.png

このファイルの内容の説明が表示されます。

b69c217d3372d802.png

プロンプトを使用して、よりわかりやすい可視化を生成するように依頼できます。

Can you visually show this class for better understanding

da5bd701323818d4.png

次のステップでは、単体テストを生成し、エージェントにテストを依頼します。次のプロンプトを入力します。

generate unit tests for this module and test it out with mock implementations.

次のタスク アーティファクトが生成され、タスクが実行されました。

21425379db336dc6.png

実行されたテストの詳細も確認できます。

48f3320cd76b5cd8.png

生成されたファイルの 1 つに、テストファイルもあります。スクリーンショットを以下に示します。

f962061f115c040f.png

試してみたいこと

独自のコードを使用して、機能の追加からコードの一部のリファクタリングまで、エージェントにどのような操作を依頼できるかを確認します。

7. 完了

完了Google Antigravity を使用して、次のことを行いました。

  • ウェブを自律的に調査する。
  • フルスタック ウェブ アプリケーションを構築して反復処理する。
  • アセットを生成して、UI の美しさを改善する。
  • モックを使用して複雑な単体テストを作成して検証する。

これで、Antigravity を使用して、独自のプロジェクトで重い処理を行うことができます。

リファレンス ドキュメント