◉RORK LABEN
●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…
記事一覧/開発ツール
⬡ 開発ツール/2026-03-29中級

AIエージェント × モバイルアプリ設計 — 「全部AIにやらせない」関心の分離アーキテクチャ

モバイルアプリにAIエージェントを組み込むとき、すべてをAIに任せず決定論的タスクを分離する設計パターンを解説します。どこにAIを使いどこに使わないかの線引き、RorkでのECアプリのアーキテクチャ例、オフラインファースト設計、コスト削減効果まで扱います。

ai-agentmobile-apparchitecture6rork59separation-of-concernsreact-native12

取り組みの背景 — モバイルアプリでのAI統合は「全部任せる」が正解ではない

Rork をはじめとするAIアプリ開発ツールの進化により、モバイルアプリにAI機能を組み込むハードルは大きく下がりました。しかし「AIにすべてを任せる」設計は、モバイル環境特有の制約と相性が悪いケースがあります。

IDCは「企業は決定論的とエージェント的アプローチの両方を単一フレームワークで支援するプラットフォームを求めている」と指摘しています。また Gartner は「Agentic AIプロジェクトの40%以上が2027年末までにキャンセルまたは大幅縮小される」と予測しています。

モバイルアプリにおけるAI設計の3つの課題

課題1: ネットワーク依存とレイテンシ

モバイルアプリはデスクトップと異なり、ネットワーク接続が不安定な環境で使われます。すべての処理をAI API(クラウド上のLLM)に依存すると、地下鉄や山間部でアプリが動作しなくなります。

課題2: トークンコストとバッテリー消費

LLM APIの呼び出しはトークン数に応じた課金が発生します。また、頻繁なAPI通信はバッテリー消費を増大させます。ユーザー操作のたびにAI APIを呼ぶ設計は、コストとUXの両面で非効率です。

課題3: 応答の一貫性

フォームバリデーション、数値計算、日付処理のような決定論的タスクにAIを使うと、同じ入力に対して異なる結果を返す可能性があります。ユーザーにとって「昨日と今日で入力チェックの結果が変わる」体験は混乱の原因です。

関心の分離: どこにAIを使い、どこに使わないか

AIエージェントに任せるべきタスク

  • 自然言語の理解: ユーザーの曖昧な指示やフリーテキスト入力の解釈
  • コンテンツ生成: テキスト・画像・レコメンデーションの生成
  • 対話型インターフェース: チャットボット、音声アシスタント
  • パーソナライゼーション: ユーザーの嗜好に基づく動的なUI調整
  • 異常検知: 通常パターンから逸脱した入力やログの検出

決定論的ツールに委譲すべきタスク

  • フォームバリデーション: メールアドレス形式、電話番号、日付のチェック
  • 数値計算: 合計金額、税計算、割引率の算出
  • データ変換: 通貨換算、単位変換、日時フォーマット
  • ローカルストレージ操作: キャッシュ管理、オフラインデータ永続化
  • ナビゲーションロジック: 画面遷移、ディープリンクのルーティング
  • 認証フロー: ログイン、トークン管理、セッション制御

実践例: Rork で作るECアプリのアーキテクチャ

ECアプリを例に、AIと決定論的ツールを適切に分離した設計を考えてみましょう。

レイヤー構成

[UIレイヤー]
    ├── 商品検索(AI: 自然言語検索 + ローカル: フィルター/ソート)
    ├── 商品詳細(ローカル: データ表示 + AI: レビュー要約)
    ├── カート(ローカル: 金額計算・在庫チェック)
    ├── チャットサポート(AI: 対話・問題解決)
    └── 決済(ローカル: Stripe SDK・バリデーション)

[ビジネスロジックレイヤー]
    ├── 価格計算エンジン(決定論的)
    ├── 在庫管理(決定論的)
    ├── レコメンデーション(AI)
    └── 不正検知(AI)

[データレイヤー]
    ├── ローカルDB(SQLite / AsyncStorage)
    ├── リモートAPI(REST / GraphQL)
    └── AI API(Claude / Gemini)

実装例: 商品検索の分離設計

// React Native / Expo での実装例
 
// 1. AIによる自然言語検索(ネットワーク必要)
async function aiSearch(query: string): Promise<Product[]> {
  // "赤いワンピースで1万円以下のもの" のような自然言語を処理
  const response = await fetch("/api/ai-search", {
    method: "POST",
    body: JSON.stringify({ query })
  });
  return response.json();
}
 
// 2. ローカルフィルター(オフライン対応・決定論的)
function localFilter(
  products: Product[],
  filters: { minPrice?: number; maxPrice?: number; category?: string }
): Product[] {
  return products.filter(p => {
    if (filters.minPrice && p.price < filters.minPrice) return false;
    if (filters.maxPrice && p.price > filters.maxPrice) return false;
    if (filters.category && p.category !== filters.category) return false;
    return true;
  });
}
 
// 3. ローカルソート(決定論的・高速)
function localSort(
  products: Product[],
  sortBy: "price_asc" | "price_desc" | "rating" | "newest"
): Product[] {
  const sorted = [...products];
  switch (sortBy) {
    case "price_asc":
      return sorted.sort((a, b) => a.price - b.price);
    case "price_desc":
      return sorted.sort((a, b) => b.price - a.price);
    case "rating":
      return sorted.sort((a, b) => b.rating - a.rating);
    case "newest":
      return sorted.sort((a, b) =>
        new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
      );
  }
}
 
// 統合: AIで検索 → ローカルでフィルター&ソート
async function searchProducts(
  query: string,
  filters: FilterOptions,
  sortBy: SortOption
) {
  // AI検索はネットワークが必要な場合のみ
  const results = navigator.onLine
    ? await aiSearch(query)
    : await localFallbackSearch(query); // オフライン時はローカル検索
 
  // フィルターとソートは常にローカルで実行(高速・決定論的)
  const filtered = localFilter(results, filters);
  return localSort(filtered, sortBy);
}

実装例: カート金額計算(決定論的)

// カート金額の計算は絶対にAIに任せない
// 同じ入力で同じ結果を返すことが必須
 
interface CartItem {
  productId: string;
  name: string;
  price: number;
  quantity: number;
  taxRate: number;
}
 
function calculateCartTotal(items: CartItem[]) {
  const subtotal = items.reduce(
    (sum, item) => sum + item.price * item.quantity, 0
  );
 
  const tax = items.reduce(
    (sum, item) => sum + Math.floor(item.price * item.quantity * item.taxRate),
    0
  );
 
  const total = subtotal + tax;
 
  return { subtotal, tax, total };
}
 
// 使用例
const cart: CartItem[] = [
  { productId: "001", name: "Tシャツ", price: 2980, quantity: 2, taxRate: 0.1 },
  { productId: "002", name: "パンツ", price: 4980, quantity: 1, taxRate: 0.1 }
];
 
const result = calculateCartTotal(cart);
console.log(`小計: ¥${result.subtotal} / 税: ¥${result.tax} / 合計: ¥${result.total}`);
// 出力: 小計: ¥10940 / 税: ¥1094 / 合計: ¥12034

オフラインファースト設計の重要性

モバイルアプリではオフライン対応が重要です。関心の分離により、決定論的タスクをローカルに配置すれば、ネットワーク不通時もコア機能が動作します。

  • カート操作: ローカルストレージで完結
  • 閲覧履歴: ローカルDBに保存
  • フォーム入力: バリデーションはローカル、送信はオンライン復帰後
  • AI機能: ネットワーク復帰後に非同期で実行

この設計であれば、地下鉄の中でも商品の閲覧やカート操作は問題なく行えます。

コスト削減の効果

AIエージェントに全処理を任せた場合と、関心の分離を適用した場合のコスト比較を考えてみましょう。

全処理をAI APIに依存した場合(月間10万ユーザー想定):

  • 商品検索: 10万回 × トークン消費
  • フィルタリング: 30万回 × トークン消費
  • カート計算: 20万回 × トークン消費
  • レコメンデーション: 10万回 × トークン消費

関心の分離を適用した場合:

  • 商品検索(AI): 10万回 × トークン消費
  • フィルタリング(ローカル): 0円
  • カート計算(ローカル): 0円
  • レコメンデーション(AI): 10万回 × トークン消費

API呼び出し回数が約70%削減され、コストとレイテンシが大幅に改善します。

まとめ

モバイルアプリにおけるAIエージェント設計は、「すべてをAIに任せる」よりも「AIが最も効果を発揮する領域に集中させ、残りは決定論的ツールに委譲する」アプローチが効果的です。ネットワーク依存の軽減、コスト削減、応答の一貫性という3つの面で、関心の分離はモバイルアプリの品質を確実に向上させます。

Rork でアプリを構築する際は、「この処理は本当にAIでなければ解決できないか?」を自問する習慣を持つと、よりバランスの取れたアーキテクチャに近づけるでしょう。モバイルアプリの設計パターンをさらに深く

シェア

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

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

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

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

関連記事

⬡ 開発ツール2026-05-20
iOS の 0x8badf00d ウォッチドッグ強制終了に Rork アプリが落ちるときの対処
Rork で作った iOS アプリが起動直後に消える。クラッシュログに 0x8badf00d。Apple のウォッチドッグが React Native の重い初期化を切ったときの正しい直し方を、私の運用中アプリで実際に効いた手順で説明します。
⬡ 開発ツール2026-04-24
Rork アプリのバイナリサイズが 150MB を超えた時に切り分ける 5 つの要因と実践的な削減手順
Rork で生成したアプリが 180MB まで膨らみ、App Store Connect の警告で止まった経験から、原因を 5 要素に分解して 69MB まで落とすまでの手順を、実測値と失敗した箇所も含めて共有します。
⬡ 開発ツール2026-10-15
EXPO_PUBLIC_ の値が、開発では読めて本番だけ undefined になる書き方を、変換結果で見分けます
API の URL が開発中は読めるのに、ビルドした途端に undefined になる。原因は process.env の書き方でした。babel-preset-expo の変換結果を開発・本番で並べ、置き換わる書き方と残ってしまう書き方を表にしました。