ANTIGRAVITY LABEN
記事一覧/Tips & 活用術
Tips & 活用術/2026-03-20上級

Antigravity 実践テクニック集【後編】— マルチエージェント・本番開発・収益化の上級テクニック

Antigravity Lab のプレミアム記事から厳選した上級テクニックの後編。マルチエージェント・オーケストレーション、本番品質アプリ開発(SwiftUI・Android・Edge AI)、SaaS収益化パイプラインをコード付きで解説。

Antigravity338実践テクニック2上級2マルチエージェント41本番運用17収益化23後編2premium15

取り組みの背景 — 後編で扱うトピック

前編では Antigravity の基本的な使い方を学びましました。後編は 本番環境での運用・複雑なアーキテクチャ設計・ビジネス展開 に焦点を当てます。

実際のスタートアップ・エンタープライズプロジェクトで通用する技術を、具体的なコード例とともに解説します。


マルチエージェント・オーケストレーション設計

複数のエージェントが同時に動作し、相互に協調するシステムを構築するには、明確な 設計パターン が必要です。

ルーターパターン(TypeScript code)

複数のエージェントを「ルーター」が管理し、タスク種別に応じて最適なエージェントに割り当てるパターンです。

アーキテクチャ図

Request
  ↓
Agent Router (分類)
  ├→ Frontend Agent (UI 関連)
  ├→ Backend Agent (API 関連)
  ├→ Data Agent (DB 操作)
  └→ Infra Agent (DevOps)

実装例

// lib/agent-router.ts
import type { AgentType, Task, TaskResult } from '@/types';
 
interface AgentConfig {
  name: AgentType;
  keywords: string[];
  filePatterns: RegExp[];
  maxConcurrent: number;
}
 
const AGENT_CONFIGS: AgentConfig[] = [
  {
    name: 'frontend',
    keywords: ['component', 'ui', 'page', 'styled'],
    filePatterns: [/src\/(components|app|pages)\//, /\.tsx?$/],
    maxConcurrent: 2,
  },
  {
    name: 'backend',
    keywords: ['api', 'endpoint', 'database', 'query'],
    filePatterns: [/src\/(api|server|db)\//, /route\.(ts|js)$/],
    maxConcurrent: 3,
  },
  {
    name: 'data',
    keywords: ['migration', 'schema', 'index', 'optimize'],
    filePatterns: [/migrations\//, /schema\.(sql|ts)$/],
    maxConcurrent: 1,
  },
  {
    name: 'infra',
    keywords: ['deploy', 'ci', 'github', 'docker'],
    filePatterns: [/\.github/, /dockerfile/i, /\.env/i],
    maxConcurrent: 1,
  },
];
 
export class AgentRouter {
  private activeAgents: Map<AgentType, number> = new Map();
 
  constructor() {
    AGENT_CONFIGS.forEach(config => {
      this.activeAgents.set(config.name, 0);
    });
  }
 
  routeTask(task: Task): AgentType {
    // タスク説明からキーワード抽出
    const taskLower = task.description.toLowerCase();
    const matchedAgents = AGENT_CONFIGS
      .filter(config =>
        config.keywords.some(kw => taskLower.includes(kw)) ||
        config.filePatterns.some(pattern =>
          task.affectedFiles?.some(f => pattern.test(f))
        )
      );
 
    if (matchedAgents.length === 0) {
      // デフォルトは frontend
      return 'frontend';
    }
 
    // 最も負荷が低いエージェントを選択
    let selectedAgent = matchedAgents[0];
    for (const agent of matchedAgents) {
      const current = this.activeAgents.get(agent.name) || 0;
      const selected = this.activeAgents.get(selectedAgent.name) || 0;
 
      if (current < selected) {
        selectedAgent = agent;
      }
    }
 
    return selectedAgent.name;
  }
 
  async executeTask(task: Task): Promise<TaskResult> {
    const agentType = this.routeTask(task);
    const current = this.activeAgents.get(agentType) || 0;
 
    // 接続数制限をチェック
    const config = AGENT_CONFIGS.find(c => c.name === agentType)!;
    if (current >= config.maxConcurrent) {
      throw new Error(
        `Agent ${agentType} is at max capacity (${config.maxConcurrent})`
      );
    }
 
    // 実行開始
    this.activeAgents.set(agentType, current + 1);
 
    try {
      const result = await this.sendToAgent(agentType, task);
      return result;
    } finally {
      this.activeAgents.set(agentType, current);
    }
  }
 
  private async sendToAgent(
    agentType: AgentType,
    task: Task
  ): Promise<TaskResult> {
    // 実装: Antigravity Agent API を呼び出し
    const response = await fetch('/api/agents/execute', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ agentType, task }),
    });
 
    return response.json();
  }
}

パイプラインパターン(TypeScript code)

一連の処理を ステップバイステップで実行 し、各ステップで異なるエージェントを使用するパターン。

実装例:SaaS のデプロイパイプライン

// lib/deployment-pipeline.ts
interface PipelineStep {
  name: string;
  agent: AgentType;
  dependencies: string[];
  execute: (context: PipelineContext) => Promise<void>;
}
 
interface PipelineContext {
  commitHash: string;
  environment: 'staging' | 'production';
  artifacts: Map<string, any>;
}
 
export class DeploymentPipeline {
  private steps: PipelineStep[] = [
    {
      name: 'lint',
      agent: 'frontend',
      dependencies: [],
      execute: async (ctx) => {
        console.log('Linting code...');
        // Frontend Agent が ESLint/Prettier を実行
        ctx.artifacts.set('lint-report', { status: 'pass' });
      },
    },
    {
      name: 'test',
      agent: 'frontend',
      dependencies: ['lint'],
      execute: async (ctx) => {
        console.log('Running tests...');
        // Frontend Agent が Jest テストを実行
        ctx.artifacts.set('test-coverage', { percent: 87 });
      },
    },
    {
      name: 'build-frontend',
      agent: 'frontend',
      dependencies: ['test'],
      execute: async (ctx) => {
        console.log('Building frontend...');
        // Frontend Agent が Next.js ビルド
        ctx.artifacts.set('frontend-bundle', { size: '2.3MB' });
      },
    },
    {
      name: 'build-backend',
      agent: 'backend',
      dependencies: [],
      execute: async (ctx) => {
        console.log('Building backend...');
        // Backend Agent が Node.js ビルド
        ctx.artifacts.set('backend-bundle', { size: '1.8MB' });
      },
    },
    {
      name: 'db-migration',
      agent: 'data',
      dependencies: [],
      execute: async (ctx) => {
        console.log('Running database migrations...');
        // Data Agent が DB マイグレーション実行
        ctx.artifacts.set('migration-status', { applied: 3 });
      },
    },
    {
      name: 'deploy',
      agent: 'infra',
      dependencies: [
        'build-frontend',
        'build-backend',
        'db-migration',
      ],
      execute: async (ctx) => {
        console.log('Deploying to cloud...');
        // Infra Agent が Vercel/Render にデプロイ
        ctx.artifacts.set('deploy-status', {
          url: 'https://staging.app.com',
          time: '3m 45s',
        });
      },
    },
    {
      name: 'e2e-test',
      agent: 'frontend',
      dependencies: ['deploy'],
      execute: async (ctx) => {
        console.log('Running E2E tests...');
        // Frontend Agent が Playwright で E2E テスト
        ctx.artifacts.set('e2e-result', { passed: 45, failed: 0 });
      },
    },
  ];
 
  async run(commitHash: string, environment: 'staging' | 'production') {
    const context: PipelineContext = {
      commitHash,
      environment,
      artifacts: new Map(),
    };
 
    const completed = new Set<string>();
 
    for (const step of this.steps) {
      // 依存ステップがすべて完了するまで待機
      while (!step.dependencies.every(dep => completed.has(dep))) {
        await new Promise(r => setTimeout(r, 100));
      }
 
      try {
        await step.execute(context);
        completed.add(step.name);
        console.log(`✓ ${step.name} completed by ${step.agent}`);
      } catch (error) {
        console.error(`✗ ${step.name} failed:`, error);
        throw error;
      }
    }
 
    return context;
  }
}

Agent Manager × Gemini 3.1 Pro の推論力活用

Antigravity は Google Gemini 3.1 Pro を背後で使用し、複雑な推論を実現しています。

高度な推論が必要なタスク

// アーキテクチャ設計の判断を AI に委ねる
const task = `
「既存の SQL クエリが N+1 問題で遅いという報告。
  現在のデータ量: 1000万件のユーザー・2000万件のイベント。
  アクセスパターン: 1秒間に最大 5000 QPS。
 
  最適な解決策を提案してください。
  - キャッシング戦略
  - DB インデックス
  - API 設計の見直し
  - 非正規化の検討

`;
 
// Gemini 3.1 Pro の推論により、複合的な提案が生成される
// - Redis キャッシュ層(TTL 5 分)
// - 複合インデックス設計
// - GraphQL DataLoader による n+1 解決
// - 集約テーブルの非正規化

Browser Sub-Agent による E2E テスト自動化

Playwright + Browser Sub-Agent で、複雑な E2E テストを自動生成・実行。

// tests/e2e/checkout.spec.ts
import { test, expect } from '@playwright/test';
 
test('完全なチェックアウトフロー', async ({ page }) => {
  // Browser Sub-Agent が自動生成したテスト
 
  // Step 1: ログイン
  await page.goto('/login');
  await page.fill('input[name="email"]', 'user@example.com');
  await page.fill('input[name="password"]', 'password123');
  await page.click('button[type="submit"]');
  await page.waitForNavigation();
 
  // Step 2: 商品追加
  await page.goto('/products');
  await page.click('text=Add to Cart');
  await expect(page).toHaveURL('/cart');
 
  // Step 3: チェックアウト
  await page.click('button:has-text("Proceed to Checkout")');
 
  // Step 4: 配送情報入力
  await page.fill('input[name="address"]', '123 Main St');
  await page.select('select[name="country"]', 'US');
 
  // Step 5: 支払い
  await page.click('text=Pay with Stripe');
  // Stripe iframe でカード情報入力(自動)
 
  // Step 6: 確認
  await expect(page).toHaveURL('/order-confirmation');
  await expect(page).toContainText('Thank you for your order');
});

本番品質のアプリ開発

SwiftUI + CloudKit で iCloud 同期アプリ

iOS アプリが iCloud と自動同期する実装。

// Models/Note.swift
import Foundation
import CloudKit
 
struct Note: Identifiable {
    let id: UUID
    var title: String
    var content: String
    var modifiedDate: Date
 
    // CloudKit 連携
    var cloudKitRecord: CKRecord?
 
    func toCKRecord() -> CKRecord {
        let record = CKRecord(recordType: "Note", recordID: CKRecordID(recordName: id.uuidString))
        record["title"] = title
        record["content"] = content
        record["modifiedDate"] = modifiedDate
        return record
    }
 
    static func fromCKRecord(_ record: CKRecord) -> Note {
        return Note(
            id: UUID(uuidString: record.recordID.recordName) ?? UUID(),
            title: record["title"] as? String ?? "",
            content: record["content"] as? String ?? "",
            modifiedDate: record["modifiedDate"] as? Date ?? Date(),
            cloudKitRecord: record
        )
    }
}
// ViewModels/NoteViewModel.swift
import CloudKit
import Observation
 
@Observable
class NoteViewModel {
    var notes: [Note] = []
    var isLoading = false
 
    private let database = CKContainer.default().publicCloudDatabase
 
    @MainActor
    func fetchNotes() async {
        isLoading = true
        let predicate = NSPredicate(value: true)
        let query = CKQuery(recordType: "Note", predicate: predicate)
 
        do {
            let records = try await database.records(matching: query)
            notes = records.compactMap { Note.fromCKRecord($0) }
        } catch {
            print("Error fetching notes: \(error)")
        }
        isLoading = false
    }
 
    @MainActor
    func saveNote(_ note: Note) async {
        let record = note.toCKRecord()
 
        do {
            _ = try await database.save(record)
            if let index = notes.firstIndex(where: { $0.id == note.id }) {
                notes[index] = Note.fromCKRecord(record)
            } else {
                notes.append(Note.fromCKRecord(record))
            }
        } catch {
            print("Error saving note: \(error)")
        }
    }
}

Android Jetpack Compose + MVI アーキテクチャ

Android での最新ベストプラクティス実装。

// mvi/PostIntent.kt
sealed class PostIntent {
    data class LoadPosts(val page: Int) : PostIntent()
    data class RefreshPosts : PostIntent()
    data class DeletePost(val id: String) : PostIntent()
    data class FavoritePost(val id: String) : PostIntent()
}
// mvi/PostViewState.kt
data class PostViewState(
    val posts: List<Post> = emptyList(),
    val isLoading: Boolean = false,
    val error: String? = null,
    val selectedPost: Post? = null,
)
// mvi/PostViewModel.kt
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.*
 
class PostViewModel(
    private val postRepository: PostRepository
) : ViewModel() {
 
    private val intentFlow = MutableSharedFlow<PostIntent>()
 
    val viewState: StateFlow<PostViewState> = intentFlow
        .scan(PostViewState()) { state, intent ->
            when (intent) {
                is PostIntent.LoadPosts -> {
                    state.copy(isLoading = true)
                }
                is PostIntent.RefreshPosts -> {
                    state.copy(isLoading = true)
                }
                is PostIntent.DeletePost -> {
                    state.copy(
                        posts = state.posts.filter { it.id != intent.id }
                    )
                }
                is PostIntent.FavoritePost -> {
                    state.copy(
                        posts = state.posts.map { post ->
                            if (post.id == intent.id) {
                                post.copy(isFavorite = !post.isFavorite)
                            } else post
                        }
                    )
                }
            }
        }
        .stateIn(
            viewModelScope,
            SharingStarted.WhileSubscribed(5000),
            PostViewState()
        )
 
    fun sendIntent(intent: PostIntent) {
        viewModelScope.launch {
            intentFlow.emit(intent)
        }
    }
}
// ui/PostScreen.kt
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
 
@Composable
fun PostScreen(viewModel: PostViewModel) {
    val state by viewModel.viewState.collectAsState()
 
    LaunchedEffect(Unit) {
        viewModel.sendIntent(PostIntent.LoadPosts(1))
    }
 
    when {
        state.isLoading -> {
            CircularProgressIndicator()
        }
        state.error != null -> {
            Text("Error: ${state.error}")
        }
        else -> {
            LazyColumn {
                items(state.posts.size) { index ->
                    PostItem(
                        post = state.posts[index],
                        onDelete = {
                            viewModel.sendIntent(PostIntent.DeletePost(state.posts[index].id))
                        },
                        onFavorite = {
                            viewModel.sendIntent(PostIntent.FavoritePost(state.posts[index].id))
                        }
                    )
                }
            }
        }
    }
}

Cloudflare Workers AI でエッジ AI アプリ

低レイテンシー AI を実現する Cloudflare Workers 統合。

// src/index.ts (Cloudflare Worker)
import { Hono } from 'hono';
 
const app = new Hono();
 
interface AIRequest {
  prompt: string;
  maxTokens?: number;
}
 
app.post('/api/ai/generate', async (c) => {
  const { prompt, maxTokens = 100 } = await c.req.json<AIRequest>();
 
  // @ts-ignore - Cloudflare Workers AI API
  const response = await c.env.AI.run('@cf/mistral/mistral-7b-instruct-v0.1', {
    prompt,
    max_tokens: maxTokens,
  });
 
  return c.json({
    prompt,
    generated: response.response,
    model: '@cf/mistral/mistral-7b-instruct-v0.1',
  });
});
 
app.post('/api/ai/classify', async (c) => {
  const { text } = await c.req.json();
 
  // 感情分析
  const sentiment = await c.env.AI.run('@cf/huggingface/distilbert-sst-2-en', {
    text,
  });
 
  return c.json({
    text,
    sentiment: sentiment.result,
  });
});
 
export default app;

カスタム MCP サーバーの構築

独自のツールを Antigravity で使用するには、カスタム MCP サーバーを構築します。

TypeScript で自作 MCP サーバー

// mcp-server/src/index.ts
import Anthropic from '@anthropic-ai/sdk';
 
interface Tool {
  name: string;
  description: string;
  inputSchema: {
    type: string;
    properties: Record<string, any>;
    required: string[];
  };
}
 
interface Resource {
  uri: string;
  name: string;
  mimeType: string;
  description: string;
}
 
class CustomMCPServer {
  private tools: Tool[] = [
    {
      name: 'fetch_analytics',
      description: 'Fetch analytics data from your company dashboard',
      inputSchema: {
        type: 'object',
        properties: {
          metric: {
            type: 'string',
            description: 'Metric name: revenue, users, retention',
          },
          period: {
            type: 'string',
            description: 'Time period: daily, weekly, monthly',
          },
        },
        required: ['metric', 'period'],
      },
    },
    {
      name: 'list_deployments',
      description: 'List recent cloud deployments',
      inputSchema: {
        type: 'object',
        properties: {
          environment: {
            type: 'string',
            enum: ['staging', 'production'],
          },
          limit: {
            type: 'number',
            description: 'Number of deployments to return',
          },
        },
        required: ['environment'],
      },
    },
  ];
 
  private resources: Resource[] = [
    {
      uri: 'internal://company/design-system',
      name: 'Design System',
      mimeType: 'text/markdown',
      description: 'Company design system guidelines and components',
    },
    {
      uri: 'internal://company/api-spec',
      name: 'API Specification',
      mimeType: 'application/json',
      description: 'OpenAPI specification for company APIs',
    },
  ];
 
  async listTools(): Promise<Tool[]> {
    return this.tools;
  }
 
  async listResources(): Promise<Resource[]> {
    return this.resources;
  }
 
  async callTool(
    toolName: string,
    params: Record<string, string | number>
  ): Promise<string> {
    switch (toolName) {
      case 'fetch_analytics':
        return this.fetchAnalytics(params);
      case 'list_deployments':
        return this.listDeployments(params);
      default:
        throw new Error(`Unknown tool: ${toolName}`);
    }
  }
 
  private async fetchAnalytics(params: Record<string, string | number>) {
    const { metric, period } = params;
 
    // 実装: 分析ダッシュボード API 呼び出し
    const response = await fetch('https://analytics.company.com/api/metrics', {
      method: 'POST',
      headers: { Authorization: `Bearer ${process.env.ANALYTICS_API_KEY}` },
      body: JSON.stringify({ metric, period }),
    });
 
    const data = await response.json();
    return JSON.stringify(data);
  }
 
  private async listDeployments(params: Record<string, string | number>) {
    const { environment, limit = 10 } = params;
 
    // 実装: デプロイ履歴 API 呼び出し
    const response = await fetch(
      `https://deploy.company.com/api/deployments?env=${environment}&limit=${limit}`,
      {
        headers: { Authorization: `Bearer ${process.env.DEPLOY_API_KEY}` },
      }
    );
 
    const data = await response.json();
    return JSON.stringify(data);
  }
}
 
// サーバー起動
const server = new CustomMCPServer();
 
// REST API エンドポイント
import express from 'express';
const app = express();
 
app.post('/mcp/tools', async (req, res) => {
  res.json({ tools: await server.listTools() });
});
 
app.post('/mcp/resources', async (req, res) => {
  res.json({ resources: await server.listResources() });
});
 
app.post('/mcp/call', async (req, res) => {
  try {
    const { tool, params } = req.body;
    const result = await server.callTool(tool, params);
    res.json({ result });
  } catch (error) {
    res.status(400).json({ error: (error as Error).message });
  }
});
 
app.listen(3001, () => {
  console.log('MCP Server listening on port 3001');
});

ツール定義とリソース公開

// mcp-server/tools/database-tool.ts
export const databaseTool = {
  name: 'query_database',
  description: 'Execute read-only SQL queries on the company database',
  inputSchema: {
    type: 'object',
    properties: {
      query: {
        type: 'string',
        description: 'SQL SELECT query (read-only)',
      },
      limit: {
        type: 'number',
        description: 'Max rows to return (default: 1000)',
      },
    },
    required: ['query'],
  },
};
 
export async function executeQuery(
  query: string,
  limit: number = 1000
): Promise<Record<string, any>[]> {
  // 実装: SQL 実行エンジン
  const client = new pg.Client({
    connectionString: process.env.DATABASE_URL,
  });
 
  try {
    const result = await client.query(`${query} LIMIT ${limit}`);
    return result.rows;
  } finally {
    await client.end();
  }
}

SaaS 収益化パイプライン

Antigravity × Stripe でフルスタック SaaS

// app/api/stripe/create-subscription.ts
import Stripe from 'stripe';
import { supabaseAdmin } from '@/lib/supabase';
 
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);
 
export async function POST(req: Request) {
  const { userId, priceId } = await req.json();
 
  // 1. Stripe で顧客取得またはクリエイト
  const { data: user } = await supabaseAdmin
    .from('users')
    .select('stripe_customer_id, email')
    .eq('id', userId)
    .single();
 
  let customerId = user?.stripe_customer_id;
 
  if (!customerId) {
    const customer = await stripe.customers.create({
      email: user.email,
      metadata: { userId },
    });
    customerId = customer.id;
 
    await supabaseAdmin
      .from('users')
      .update({ stripe_customer_id: customerId })
      .eq('id', userId);
  }
 
  // 2. Subscription 作成
  const subscription = await stripe.subscriptions.create({
    customer: customerId,
    items: [{ price: priceId }],
    payment_behavior: 'default_incomplete',
    expand: ['latest_invoice.payment_intent'],
  });
 
  // 3. Supabase に記録
  await supabaseAdmin
    .from('subscriptions')
    .insert({
      user_id: userId,
      stripe_subscription_id: subscription.id,
      status: subscription.status,
      current_period_end: new Date(subscription.current_period_end * 1000),
    });
 
  return new Response(JSON.stringify(subscription), {
    status: 200,
    headers: { 'Content-Type': 'application/json' },
  });
}

YouTube チュートリアル動画の自動制作

Antigravity が YouTube スクリプト・カット指示を自動生成。

// scripts/generate-tutorial.ts
import { Anthropic } from '@anthropic-ai/sdk';
 
const client = new Anthropic();
 
async function generateYouTubeTutorial(topic: string): Promise<string> {
  const message = await client.messages.create({
    model: 'claude-3-5-sonnet-20241022',
    max_tokens: 4000,
    messages: [
      {
        role: 'user',
        content: `
YouTube チュートリアル動画のスクリプトを生成してください。
 
トピック: ${topic}
対象者: 初心者~中級者
動画長: 10 分
 
出力形式:
[Scene 1]
時間: 0:00-0:30
ナレーション: ...
ビジュアル: ...
 
[Scene 2]
...
`,
      },
    ],
  });
 
  return message.content[0].type === 'text' ? message.content[0].text : '';
}
 
// 実行例
const script = await generateYouTubeTutorial(
  'Antigravity でのマルチエージェント開発'
);
console.log(script);

Kindle 技術書の効率的な執筆

// scripts/generate-ebook.ts
interface EbookChapter {
  title: string;
  sections: {
    heading: string;
    content: string;
  }[];
}
 
async function generateEbookChapter(chapterTopic: string): Promise<EbookChapter> {
  const response = await fetch('/api/ai/generate', {
    method: 'POST',
    body: JSON.stringify({
      prompt: `
Kindle 技術書の章を執筆してください。
 
チャプター: ${chapterTopic}
スタイル: テクニカル、実践的、コード例含む
長さ: 3000-4000 語
 
セクション構成:
1. 概要
2. 基本概念
3. 実装例(コード付き)
4. ベストプラクティス
5. よくある質問
`,
    }),
  });
 
  const data = (await response.json()) as { generated: string };
 
  // Markdown パース & 構造化
  return parseMarkdownToChapter(data.generated);
}
 
function parseMarkdownToChapter(markdown: string): EbookChapter {
  // 実装: Markdown → 構造化データ変換
  return {
    title: 'Chapter Title',
    sections: [],
  };
}

まとめ — 関連プレミアム記事一覧

後編では、Antigravity による本番環境レベルの開発技術 を習得しました。

次に学べるプレミアム記事シリーズ

  • 「マルチエージェント・システム設計パターン集」
  • 「本番 iOS/Android アプリの運用テクニック」
  • 「AI × 自動化で SaaS を高速成長させる方法」
  • 「Antigravity による Kindle ベストセラー執筆」

Antigravity Lab プレミアム会員になり、AI 駆動開発の最前線を体験してください。

個人開発12年の現場で実感したこと

線引きするときの3つの判断軸

  • 失敗時の影響が金銭やユーザー体験にどれだけ波及するか
  • 復旧オペレーションが明文化されているか
  • 観測ログから人間が再現できる粒度に整っているか
シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

Tips & 活用術2026-03-20
Antigravity 開発ベストプラクティス総集編 — 28本のプレミアム記事から厳選した実践テクニック集
Antigravity Lab の全プレミアム記事から厳選したベストプラクティスを1記事に凝縮。マルチエージェント設計、本番品質アプリ開発、デザイン→コード変換、統合ワークフローの実践テクニック集。
Tips & 活用術2026-06-22
保存するエージェントログから秘密を消す — 投入前のリダクション層を設計する
無人で走るエージェントのログを残し始めると、いつかトークンやAPIキーが平文で記録されます。ローテートしても、流出したログは消えません。書き込みの直前で秘密を確実に落とすリダクション層を、正規表現だけに頼らず既知の秘密を登録して消す方式まで含めて、動くPython実装と運用の所感つきで設計します。
Tips & 活用術2026-05-05
Antigravity × モバイル収益設計の全体像:AdMob・IAP・サブスクリプションを組み合わせた個人開発者の収益最大化フレームワーク
AdMob・アプリ内購入・サブスクリプションを一元化したモバイル収益戦略の設計書。Antigravity を使って収益ダッシュボードから価格 A/B テストまで自動化する、個人開発者向けの実装ガイドです。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →