RORK LABEN
TOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しましたTOOLING — Rorkの開発者向けリポジトリが動き続けています。rork-xcodeが7月16日、rork-deviceが7月15日、rork-plistが7月13日に更新されましたOPUS46 — RorkでClaude Opus 4.6が稼働しています。Rork MaxはClaude Codeを土台にアプリを組み立てる設計ですSIM — ブラウザ上で動くクラウドのiOSシミュレータを備え、実機へのインストールは1クリック、App Storeへの提出は2クリックと案内されていますMAX — Rork MaxはReact Nativeではなく純粋なSwiftを出力します。iPhone・iPad・Apple Watch・Apple TV・Vision Pro、そしてiMessageまでが射程ですNATIVE — HealthKit、ARKitとLiDAR、NFC、Dynamic Island、Live Activities、Metalによる3D、Core MLのオンデバイス推論まで扱えますSEED — RorkはLeft Lane Capitalが主導する1,500万ドルのシードラウンドを実施し、Peak XVとa16z Speedrunが参加しました
記事一覧/AIモデル
AIモデル/2026-04-22上級

Rork × LiveKit: AI 音声エージェントを本番運用する通話インフラ設計ガイド

LiveKit Agents を Rork 製の React Native アプリに組み込み、低遅延な AI 音声エージェントを本番運用するまでの通話インフラ設計を解説します。

Rork515LiveKitAI音声エージェントReact Native209WebRTC4本番運用10

プレミアム記事

「音声で話せる AI アシスタントを自分のアプリに載せたい」— Rork を触り始めた方から、この相談を受ける機会が急に増えました。背景には、OpenAI Realtime API や Gemini Live API が一般開発者に開放されたこと、そして Vapi や Retell のような音声 AI プラットフォームが参入しやすくなったことがあります。

ただ、デモを動かすところまでは簡単でも、実際に App Store に出して課金まで回す段階になると、まったく別の壁が立ちはだかります。私自身、最初に組んだ音声チャットアプリは、電車でトンネルに入っただけでセッションが壊れ、ユーザーから容赦ないレビューが付きました。遅延が 1 秒を超えるとユーザーは喋るのをやめます。再接続が 3 秒遅れると、90 秒で解約されます。

この記事は、そんな「デモは動くが本番で落ちる」地点でつまずいている方のために、LiveKit Agents をバックエンドに、Rork で生成した React Native クライアントをフロントエンドにした、本番運用レベルの音声エージェントアプリの設計図を丸ごと共有する内容です。なぜ LiveKit かというと、WebRTC の実装を自前で書くと SRTP の再送処理やジッターバッファで必ず事故が起きるのですが、LiveKit Agents は Python/Node のエージェントランタイムと SFU を一体で提供していて、この事故領域を丸ごと肩代わりしてくれるからです。

第 1 章: 全体アーキテクチャの設計

まず、書き始める前にアーキテクチャ全体の責務を整理します。「とりあえず動く」で作ると、あとから課金やログ保存を足す段階で必ず破綻するので、最初に 4 層に分けて考えるのがおすすめです。

責務の 4 分割

  • モバイルクライアント(Rork 生成の React Native 層): マイク・スピーカー権限の取得、LiveKit Room への接続、UI 状態管理、通話終了時のログ送信
  • トークン発行 API(Hono + Cloudflare Workers): Supabase 認証トークンを検証し、課金状態に応じて LiveKit 用 JWT を発行します。通話時間の事前チェックもここで行う
  • LiveKit Agent(Python または Node.js): ルームに参加してユーザーの音声を受信し、Whisper → GPT/Claude → TTS のパイプラインを実行する常駐ワーカー
  • 課金・ログストア(Stripe + Supabase Postgres): 月次の通話時間上限・通話ログ・エラーイベントを保存する永続層

なぜこの分割にするか

最初は「Rork アプリから直接 OpenAI Realtime API に WebSocket を張ればいいじゃないか」と思うかもしれません。実際、私も最初はそう組みました。ただ、この構成には 3 つの致命的な問題があります。

  1. API キーの露出: クライアント側に OpenAI の API キーを埋め込むことになり、逆コンパイルされると課金が青天井になります
  2. 課金制御の不可能性: クライアントが直接外部 API を叩いている以上、「無料プランは月 10 分まで」のような制限をサーバー側で強制できません
  3. ロギングの欠落: 通話品質・エラー・ユーザー行動のログがクライアント依存になり、改善サイクルが回りません

LiveKit を挟むと、API キーをサーバーに集約でき、トークン発行時点で課金チェックができ、ルーム単位のメトリクスが標準で取れるようになります。

ディレクトリ構成

実運用している構成はこんな形です。

my-voice-app/
├── app/                    # Rork 生成の Expo Router 画面
│   ├── (tabs)/
│   │   └── voice.tsx       # 音声通話画面
│   └── _layout.tsx
├── lib/
│   ├── livekit.ts          # LiveKit クライアントラッパー
│   ├── billing.ts          # 課金状態チェック
│   └── api.ts              # トークン発行 API 呼び出し
├── server/                 # バックエンド(別リポでも可)
│   ├── token-api/          # Hono + Cloudflare Workers
│   └── agent/              # LiveKit Agent (Python)
└── app.config.ts

第 2 章: LiveKit Agent サーバーの実装

まずはバックエンドから作ります。クライアントから作ると、接続先がないまま UI だけ作ることになり、結局何も動かないまま時間を溶かすことになるからです。

必要な環境変数

LiveKit Cloud のダッシュボードで新規プロジェクトを作成すると、以下 3 つが発行されます。

  • LIVEKIT_URL: wss://your-project.livekit.cloud
  • LIVEKIT_API_KEY: APIxxxxxxxxxxxxxxxx
  • LIVEKIT_API_SECRET: シークレット

さらに、AI プロバイダー側のキーも必要です。今回は OpenAI を使う前提で進めます。

# .env.agent
LIVEKIT_URL=wss://your-project.livekit.cloud
LIVEKIT_API_KEY=APIxxxxxxxxxxxxxxxx
LIVEKIT_API_SECRET=your-secret
OPENAI_API_KEY=YOUR_OPENAI_API_KEY

エージェント本体(Python)

LiveKit Agents の Python SDK を使うと、VAD(音声区間検出)→ STT → LLM → TTS のパイプラインが数十行で書けます。下記は「フレンドリーな日本語アシスタント」として振る舞わせる最小実装です。

# server/agent/main.py
import asyncio
import logging
from livekit.agents import AutoSubscribe, JobContext, WorkerOptions, cli, llm
from livekit.agents.voice_assistant import VoiceAssistant
from livekit.plugins import openai, silero
 
logger = logging.getLogger("voice-agent")
 
async def entrypoint(ctx: JobContext):
    # 初期プロンプト: エージェントの人格・禁止事項を定義する
    initial_ctx = llm.ChatContext().append(
        role="system",
        text=(
            "あなたは日本語で応答するフレンドリーなアシスタントです。"
            "返答は 1 〜 2 文に収め、句読点で間を取ってください。"
            "医療・法律・投資の個別助言はせず、専門家への相談を促してください。"
        ),
    )
 
    # ユーザーの音声トラックのみ購読する(コスト削減のため映像はスキップ)
    await ctx.connect(auto_subscribe=AutoSubscribe.AUDIO_ONLY)
 
    assistant = VoiceAssistant(
        vad=silero.VAD.load(),
        stt=openai.STT(model="whisper-1", language="ja"),
        llm=openai.LLM(model="gpt-4o-mini"),
        tts=openai.TTS(voice="nova"),
        chat_ctx=initial_ctx,
    )
    assistant.start(ctx.room)
 
    # 接続直後の挨拶
    await asyncio.sleep(0.5)
    await assistant.say("こんにちは、何かお手伝いできることはありますか?", allow_interruptions=True)
 
if __name__ == "__main__":
    cli.run_app(WorkerOptions(entrypoint_fnc=entrypoint))

実行すると、ワーカープロセスが LiveKit Cloud に常駐し、ルームに人間が参加するたびに自動で呼び出されます。期待する出力はログに以下のように表示されます。

voice-agent - INFO - worker started, id=AW_xxxxxxx
voice-agent - INFO - accepting job, room=voice-user-123
voice-agent - INFO - agent connected to room

なぜ VoiceAssistant を使うか

自分で STT → LLM → TTS を繋ぐと、「ユーザーが話している途中で LLM を走らせてしまう」「TTS 中にユーザーが割り込んだら止める」といった制御を全部書く羽目になります。VoiceAssistant クラスはこの割り込み制御を内部で実装済みで、allow_interruptions=True を付けると自然な会話のやり取りが実現できます。

私は最初 LangChain のエージェントを直結しようとして、「返答が終わってからしか次の発話を受けない」状態に陥り、ユーザーからクレームの嵐でした。VoiceAssistant を経由するだけでこの問題は消えます。

デプロイ先の選定

エージェントは常駐プロセスなので、Cloudflare Workers には乗りません。推奨は以下の 3 択です。

  • Fly.io: Python コンテナをそのままデプロイでき、$5/月 から。個人開発ならこれ
  • LiveKit Cloud Agents(有料オプション): サーバー運用不要。ただし月額コストは高め
  • Railway / Render: Fly.io と同等の使い勝手

私は Fly.io で fly launch --dockerfile で立ち上げ、fly scale count 2 で冗長化しています。1 エージェントあたりの同時通話は 10 〜 20 まで捌けるので、MRR が伸びたら台数を増やせば良いだけです。

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

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
音声 AI エージェントを試作したものの、遅延・切断・再接続で詰まっていた方が、本番で使える安定したインフラ構成をそのまま移植できるようになります
LiveKit Agents のサーバー側、Rork で生成したクライアント側、課金・権限の 3 層を、コピー&ペーストで動く形で手に入れられます
月額課金で通話時間を制限する実装と、離脱率を下げる再接続 UX の型を身につけ、自分のアプリの MRR を伸ばす土台が作れます
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

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

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

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

関連記事

AI モデル2026-06-19
Rork Max に月 $200 を払う前に、Expo でどこまで届くかを3階層で見極める
ウィジェットや Live Activities が欲しくなると Rork Max が視野に入りますが、その多くは標準 Rork の Expo 構成でも届きます。機能ごとに「Expo で届く・自作モジュールで届く・Max が現実解」の3階層に分け、課金前に実機で見極める手順を整理しました。
AI モデル2026-06-14
Rork(Expo)製アプリから Apple Foundation Models を呼ぶ — オンデバイスAIをネイティブモジュールで橋渡しする
Rork が生成する Expo(React Native)アプリから iOS のオンデバイスAI、Apple Foundation Models を呼ぶには、Swift 側のネイティブモジュールを挟む必要があります。Expo Modules API で橋渡しを書き、未対応端末ではクラウドへ逃がす構成を実装します。
AI モデル2026-06-13
オンデバイスAIを一次経路にして、重い処理だけクラウドへ逃がす推論ルーターをRorkアプリに組む
Rork(Expo)で生成したアプリに、オンデバイス→Private Cloud Compute→外部API(Claude/Gemini)の順で推論を流す段階フォールバック型ルーターを実装します。予算管理・タイムアウト・キャッシュ・画像入力の振り分けまで、動くTypeScriptで解説します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →