この記事でやること

Google Antigravity の Agent Manager を活用して、SwiftUIで立ち上げたプロジェクトにタブ付きニュース画面を追加してみます。Obsidian に機能仕様を書き、その仕様を Agent Manager 側で“役割ごとのタスク”に分解して、複数エージェントに並列でやってもらうというワークフローです。

前提:追加機能

ContentViewに タブ付きニュース画面 を追加します。目指す画面は次のようなものです。

  • 画面上部にカテゴリタブ(例:All / Tech / Business / Entertainment)
  • 選択中のタブに応じて、ニュースの見出しカードが縦に並ぶ

記事はダミーデータでも構わないので、まずはレイアウトと状態管理の骨格を作ることを目標とします。

Obsidianで機能仕様を書く

機能追加のために、次のようなノートを用意しました。

Featureノート:機能の目的とスコープをまとめる

# [Feature] タブ付きニューストップ画面の追加
## 目的
- SplashView の次に表示されるメイン画面として、ニュースアプリのようなタブ付きトップ画面を追加する
## ユースケース
- アプリ起動直後に、最近のニュースをざっと眺めたい
- カテゴリごとにニュースを切り替えて読みたい
## スコープ(今回やること)
- ダミー記事でよいので、タブ付きの ContentView を実装する
- 詳細画面への遷移はまだ作らない
- デザインは仮でOK。まずはレイアウトと状態管理を固める

このノートは「この機能が何のためにあるか」「今回はどこまでやるか」という方針を共有するためのものです。

UIノート:タブ構成とカードUIを言語化する

# [UI] ContentView タブ構成&カードデザイン
## タブ構成
- All: すべての記事
- Tech: テック系ニュース
- Business: ビジネス・経済系ニュース
- Entertainment: エンタメ系ニュース
## カードUI
- 表示項目
  - タイトル(2行まで)
  - サイト名
  - 投稿日時(YYYY/MM/DD HH:mm)
- レイアウト
  - 左: サムネイル(今回はプレースホルダ画像でOK)
  - 右: タイトル / サイト名 / 日付を縦に並べる
## 画面構成
- 上部: アプリ名 + 今日の日付
- 中段: タブ
- 下部: タブに対応する記事一覧(スクロール)

UI ノートでは、画面の構成要素とレイアウトを文章で具体的に記述しています。

Taskノート:タスク単位まで分解する

# [Tasks] ContentView 追加タスク(Agent用)
## 役割A: 情報設計(データモデル・ダミーデータ)
- enum NewsTab を定義する(all / tech / business / entertainment)
- struct Article を定義する(id, title, source, category, publishedAt)
- タブごとにダミー記事を返す Provider or Repository を用意する
## 役割B: UI構築(SwiftUI)
- [UI]ノートを前提に、タブ付きの ContentView を実装する
- 上部のヘッダー(アプリ名 + 日付)
- タブと記事リストのレイアウト
## 役割C: 状態管理
- ObservableObject の ViewModel を作成する
- 選択中タブの状態を @Published で管理する
- タブ変更時に表示される記事リストを切り替える

Task ノートは Agent Manager で複数のエージェントに仕事を割り振るための仕様書です。役割ごとにやるべきことを箇条書きにしています。

Antigravity Agent Managerでタスクを並列実行する

Obsidian で仕様とタスクをまとめたら、いよいよ Antigravity 側の出番です。Agent Manager では先ほどの役割A/B/Cに対応するエージェントを 3 体用意し、それぞれに必要なノートを入力として渡します。入力と出力結果載せてますが、一部省略してます。

役割A:情報設計エージェント

役割Aのエージェントには、「NewsTab と Article モデルを定義し、タブごとにダミーデータを返す Provider を実装してほしい」と依頼します。プロンプト例は次のようになります。

以下の Obsidian ノートの内容を前提に、
タブ付きニュース画面用のデータモデルとダミーデータを設計してください。

  • タブ構成やカードUIは [UI]ノートを参照
  • 役割Aのタスクは [Tasks]ノートを参照

enum NewsTab(all / tech / business / entertainment)、struct Article(id, title, source, category, publishedAt)、そしてタブごとにダミー記事を返す Provider を Swift で実装してください。

この依頼に対して、エージェントからは次のようなモデル定義が返ってきます。

enum NewsTab: CaseIterable {
    case all
    case tech
    case business
    case entertainment
}

struct Article: Identifiable {
    let id: UUID = UUID()
    let title: String
    let source: String
    let category: NewsTab
    let publishedAt: Date
}

protocol ArticleProvider {
    func articles(for tab: NewsTab) -> [Article]
}

final class DummyArticleProvider: ArticleProvider {
    func articles(for tab: NewsTab) -> [Article] {
        // タブごとにダミー記事を返す処理
    }
}

役割B:UIエージェント

UI エージェントには UI ノートを渡し、ContentView の SwiftUI コードを作ってもらいます。

struct ContentView: View {
    @State private var selectedTab: NewsTab = .all
    let provider: ArticleProvider

    var body: some View {
        VStack {
            header
            tabs
            articleList
        }
        .padding()
    }

    private var header: some View {
        VStack(alignment: .leading, spacing: 4) {
            Text("PersonalNews")
                .font(.title)
                .bold()
            Text(Date(), style: .date)
                .font(.subheadline)
                .foregroundStyle(.secondary)
        }
    }

    // tabs と articleList は省略…
}

上部ヘッダー、タブ、リストといった構造がUIノートに沿って実装されていることが分かります。

役割C:状態管理エージェント

状態管理エージェントには ViewModel 周りを任せます。選択中タブに応じて記事リストが変わるように ObservableObject を実装します。

final class ContentViewModel: ObservableObject {
    @Published var selectedTab: NewsTab = .all
    @Published private(set) var articles: [Article] = []

    private let provider: ArticleProvider

    init(provider: ArticleProvider) {
        self.provider = provider
        loadArticles()
    }

    func select(tab: NewsTab) {
        selectedTab = tab
        loadArticles()
    }

    private func loadArticles() {
        articles = provider.articles(for: selectedTab)
    }
}

この ViewModel を ContentView に注入するようにすれば、タブを切り替えたときに自動で記事リストが切り替わるようになります。

実装結果

何もなかった画面にニュースアプリの画面を作成できました。若干仕様と違う箇所もありますが、概ね問題なしです。

まとめ

今回は、SplashView しかなかった SwiftUI プロジェクトにタブ付きニュース画面を追加する例を通じて、

  • Obsidian で機能仕様を整理する
  • Agent Manager でタスクを役割別に分解し、複数エージェントに並列で依頼する

という開発フローを紹介しました。

WorkspaceごとにAIエージェントを走らせて、クライアントとサーバーの実装を同時に行うこともできますね。

他にも優秀な機能が多いので、今後も Google Antigravity を活用して気付きがあれば発信していこうと思います。