CLAUDE LABEN
FORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられていますFORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられています
記事一覧/API & SDK
API & SDK/2026-04-25上級

Claude API × Convex でリアクティブな AI アプリを本番構築する — データフロー設計とエージェントパターン

Convex のリアクティブデータベースと Claude API を組み合わせて、本番運用に耐えるチャット・エージェント系アプリを構築する方法をまとめました。スキーマ設計、Action/Mutation/Query の境界、ストリーミング、ツール状態管理、冷え始めの落とし穴まで、開発現場の判断軸を共有します。

Claude API115ConvexAgent SDK4TypeScript24RealtimeProduction2

プレミアム記事

Convex と Claude API を組み合わせたチャットアプリや業務エージェントを作り始めた方から、ここ数週間で似たような相談が続けて届きました。「マルチプレイヤーのチャットは気持ち良く動くのに、Claude を呼ぶと突然レイテンシが倍になる」「Action のタイムアウトで長時間処理が落ちる」「リロードすると途中まで届いたツール実行結果が消える」。いずれも、Convex のリアクティブな世界観と、Claude の非同期・ストリーミング前提のリクエストを無理に1層で混ぜてしまったときに起きる症状です。

ここで扱うのは私が本番で運用している設計を元に、Convex と Claude API を噛み合わせるための層の切り分け方、スキーマ設計、ストリーミング同期、ツール状態管理、そして見落としがちな冷え始めレイテンシ対策までをまとめます。コードは TypeScript、@anthropic-ai/sdkconvex の最新安定版(2026 年4月時点)を前提にしていますが、どのバージョンでも通用する設計原則に重点を置いています。

Convex を AI アプリの基盤に選ぶときの判断軸

Convex は「リアクティブなクエリを中心に据えた、ドキュメントベースのサーバーレスプラットフォーム」です。単なるデータベースではなく、クエリが自動で subscribe され、書き込みによる影響範囲が差分で配信される点が特徴です。この性質は、AI との対話 UI と驚くほど相性が良く、新しいメッセージが追加されるたびに UI を更新する処理を自前で書く必要がありません。

ただし、Convex にはサーバーレス特有の制約もあります。mutationquery には CPU 時間の上限があり、外部 API を呼ぶのは原則として action 経由です。Claude API のように応答に 5〜60 秒かかる呼び出しは、常に action の層で扱い、結果を mutation で書き戻すパターンが基本になります。「Mutation から fetch したい」という欲求は早めに諦めてください。この境界を曖昧にすると、後から巨大なリファクタが必要になります。

私は Convex を選ぶかどうかを、以下の観点で判断しています。クライアント側でリアルタイム同期が必要で、かつユーザー同士の協調が発生する(共同編集・マルチプレイヤーなど)なら Convex が強力です。一方、単純な単一ユーザーのチャット UI で、既に Postgres と GraphQL が動いているなら、Convex を追加する必然性は高くありません。Claude API の ストリーミング配信 を SSE でダイレクトに送る方が、レイテンシは低く保てます。

スキーマ設計 — スレッド・メッセージ・ツールコールの3層モデル

私が本番で使っているスキーマは、チャット UI とエージェント実行を両方想定しています。最小構成でも、スレッド、メッセージ、ツール実行の3テーブルに分離するのがおすすめです。これは後述する「進行中の処理を別レコードで追う」パターンに直結します。

// convex/schema.ts
import { defineSchema, defineTable } from "convex/server";
import { v } from "convex/values";
 
export default defineSchema({
  threads: defineTable({
    userId: v.string(),
    title: v.string(),
    model: v.string(), // "claude-sonnet-4-6" など
    systemPrompt: v.optional(v.string()),
    totalInputTokens: v.number(),
    totalOutputTokens: v.number(),
    archivedAt: v.optional(v.number()),
  }).index("byUser", ["userId", "archivedAt"]),
 
  messages: defineTable({
    threadId: v.id("threads"),
    role: v.union(v.literal("user"), v.literal("assistant"), v.literal("tool")),
    // ストリーミング中は contentDraft を更新し続け、確定後に content に移す
    content: v.optional(v.string()),
    contentDraft: v.optional(v.string()),
    status: v.union(
      v.literal("pending"),
      v.literal("streaming"),
      v.literal("complete"),
      v.literal("error"),
    ),
    errorMessage: v.optional(v.string()),
    inputTokens: v.optional(v.number()),
    outputTokens: v.optional(v.number()),
  }).index("byThread", ["threadId"]),
 
  toolCalls: defineTable({
    messageId: v.id("messages"),
    name: v.string(),
    input: v.any(),
    output: v.optional(v.any()),
    status: v.union(
      v.literal("pending"),
      v.literal("running"),
      v.literal("success"),
      v.literal("failure"),
    ),
    startedAt: v.number(),
    completedAt: v.optional(v.number()),
  }).index("byMessage", ["messageId"]),
});

contentDraftcontent を分けるのは、「完了前の下書き」と「確定結果」を同じフィールドで管理しないためです。クライアントが content だけを購読するようにすれば、ストリーミング中の細かい再描画で UI がちらつく問題を回避できます。逆に「タイピング中のカーソル」を表示したい場合は、別コンポーネントで contentDraft を購読させれば良い、という分離が効きます。

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

この記事の続きを読む

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

この記事で得られること
Convex + Claude API でチャット・エージェントを作り始めた人が、Action と Mutation の境界で詰まる問題を最初に解決できる
長時間実行するエージェントをサーバーレスで安定稼働させるスケジュール型ジョブと進行状況同期の実装を習得できる
コスト追跡・レート制限・スキーマ進化を含む本番運用の設計をそのままコピーして使える形で手に入る
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

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

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

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

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

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

関連記事

API & SDK2026-07-09
RAG が自信たっぷりに間違え始めたとき — 検索の取りこぼしを接地率で計測する運用メモ
Claude API の RAG で、回答は流暢なのに事実がずれ始める。多くの場合、原因は検索側で答えを含む文書を取りこぼすサイレントなリコール低下です。接地率と検索ヒット率を計測し、段階的に立て直した運用メモを、動くコードと実数値付きで残します。
API & SDK2026-07-08
MCP コネクタを申請・無人運用に回す前に、各ツールを契約テストで確かめる
手元で動いた MCP コネクタをそのまま無人ジョブに繋ぐと、応答形状の誤読や書き込みの二重発火で静かに壊れます。ツール記述・応答契約・冪等性・レイテンシを機械検証する小さなハーネスの作り方を、実測値とともにまとめました。
API & SDK2026-07-03
単価が40%下がっても、タスク単価は下がるとは限らない — Opus 4.8 から Sonnet 5 への移行損益をトークン消費プロファイルで測る
Sonnet 5 の導入価格は Opus 4.8 より約40%安ですが、ツール往復が増えるとタスク単価は逆転し得ます。消費ベクトルの記録・並走ハーネス・損益分岐ターン数の逆算までを動くTypeScriptと実測で示します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →