---
title: "Vercel AI SDKの使い方｜AI SDK 7でNext.jsチャットとLangChain連携を実装"
url: "https://www.issoh.co.jp/tech/details/9551/"
published: 2025-10-28
updated: 2026-10-31
categories: ["LLM・RAG"]
publisher: "株式会社一創"
---

# Vercel AI SDKの使い方｜AI SDK 7でNext.jsチャットとLangChain連携を実装

Vercel AI SDK（npmパッケージ名は `ai`）は、LLMの呼び出しからチャット画面へのストリーミングまでをTypeScriptでつなぐツールキットです。2026年10月31日時点の最新は **AI SDK 7（7.0.159）**で、Node.js 22以上・ESM専用になりました。7月時点の解説で定番だった `result.toUIMessageStreamResponse()` や `stepCountIs` は、v7では非推奨または別名扱いです。

この記事では、インストール、テキスト生成、Next.jsのチャット画面、ツール呼び出し、`@ai-sdk/langchain` を使ったLangChain・LangGraphとの連携を、v7の書き方で順に示します。コード例はNode.js 26.5.0とTypeScript 7.0.2で型検査し、生成部分はAPIキーなしのモックモデルで実行して出力を確かめています。v6の新機能（ToolLoopAgentの登場など）を詳しく知りたい場合は[Vercel AI SDK v6とは？新機能（ToolLoopAgent・needsApproval）とv7との違い・移行【2026】](/tech/details/10402/)を参照してください。

## まとめ｜AI SDK 7で押さえる要点

- **最新はAI SDK 7（7.0.159）**。`npm install ai` でv7が入り、Node.js 22以上・ESM専用。v6を使い続けるなら `ai@ai-v6` のdist-tagで固定する。
- Next.jsのルートハンドラは `toUIMessageStream({ stream: result.stream })` を `createUIMessageStreamResponse` に渡す。結果オブジェクトの `toUIMessageStreamResponse()` はv7で非推奨（動作はする）。
- システムプロンプトは `instructions` に書く。`messages` に `role: 'system'` を混ぜると `InvalidPromptError` で止まる。
- `generateText` は `stopWhen` を省くと1ステップで止まる。最初の応答がツール呼び出しだけだと `text` は空文字になるので、`isStepCount(n)` を指定する。
- LangChain・LangGraphの出力は `@ai-sdk/langchain` の `toUIMessageStream` で `useChat` に流せる。`streamMode` に `'messages'` を入れないと本文が1文字も届かない。

## AI SDK 7の現行バージョンと対応パッケージ

### バージョン履歴と各パッケージの対応

AI SDKは本体の `ai` と、UIフック（`@ai-sdk/react`）・プロバイダ（`@ai-sdk/openai` など）・アダプタ（`@ai-sdk/langchain`）が別パッケージです。メジャー版ごとに組み合わせる版が決まっており、npmにはその組み合わせがdist-tagとして登録されています。

| 本体 ai   | 初版の公開日     | @ai-sdk/react | @ai-sdk/openai | @ai-sdk/langchain | dist-tag |
| ------- | ---------- | ------------- | -------------- | ----------------- | -------- |
| 7.0.159 | 2026-06-25 | 4.0.163       | 4.0.106        | 3.0.159           | latest   |
| 6.0.320 | 2025-12-22 | 3.0.323       | 3.0.135        | 2.0.328           | ai-v6    |
| 5.0.283 | 2025-07-31 | 2.0.286       | 2.0.139        | 1.0.283           | ai-v5    |

版番号は2026年10月31日に `npm view` で取得した値です。v6系も10月30日に6.0.320が出ており、保守は続いています。v7で変わった主な点は、[公式の移行ガイド（Migrate AI SDK 6.x to 7.0）](https://ai-sdk.dev/docs/migration-guides/migration-guide-7-0)によると、Node.js 22未満のサポート終了、CommonJSの廃止、`system`→`instructions` などの改称、ツール承認の設定場所の移動です。

### インストール済みバージョンの確認とv6系の固定

手元のプロジェクトに入っている版は `npm ls` で、公開済みの最新版は `npm view` で確認できます。既存のv6アプリを今すぐ移行できない場合は、関連パッケージをまとめて `ai-v6` タグで入れれば、組み合わせの食い違いを避けられます。

```
# 入っている版
npm ls ai @ai-sdk/react @ai-sdk/langchain

# 公開済みの最新版とdist-tag
npm view ai dist-tags

# v6系に固定する（本体・UI・プロバイダ・アダプタを同じタグで）
npm install ai@ai-v6 @ai-sdk/react@ai-v6 @ai-sdk/openai@ai-v6 @ai-sdk/langchain@ai-v6
```

## インストールとプロバイダの設定

### 必要なパッケージと環境変数

Next.jsでチャットを作る最小構成は、本体・Reactフック・プロバイダ・スキーマ定義用のzodの4つです。AI SDK 7は `"engines": { "node": ">=22" }` を宣言しているため、Node.js 20以前の環境では先にランタイムを上げます。

```
npm install ai @ai-sdk/react @ai-sdk/openai zod
```

```
# .env.local
OPENAI_API_KEY=sk-xxxxxxxx
```

### プロバイダの切り替えとモデルIDの指定

モデルは `model` 引数に渡すだけなので、プロバイダを替えても呼び出し側は変わりません。`@ai-sdk/openai` 4.0.106の型定義に載っているOpenAIの新しいモデルIDは `gpt-6-astra`・`gpt-6.1-sol` などです。公式のNext.jsクイックスタートは、Vercel AI Gateway経由で `'anthropic/claude-sonnet-5.5'` のような文字列だけでモデルを指定する書き方を採っています（環境変数は `AI_GATEWAY_API_KEY`）。

```
// lib/model.ts
import { openai } from '@ai-sdk/openai';

export const model = openai('gpt-6-astra');
// AI Gatewayを使う場合は文字列で指定: 'anthropic/claude-sonnet-5.5'
```

## テキストを生成する｜generateText・streamText・Output.object

### まとめて受け取る generateText

応答を一度に受け取るなら `generateText` です。v7ではシステムプロンプトの引数名が `system` から `instructions` に変わりました。モックモデルで実行すると、`instructions` の内容はプロバイダへ `role: 'system'` のメッセージとして渡っていました。

```
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';

const { text } = await generateText({
  model: openai('gpt-6-astra'),
  instructions: '回答は3行以内で',
  prompt: 'TypeScriptを採用する理由を説明して',
});

console.log(text);
```

過去の会話履歴を `messages` で渡すとき、その中に `{ role: 'system' }` が残っていると、v7は `AI_InvalidPromptError: Invalid prompt: System messages are not allowed in the prompt or messages fields.` を投げます。DBに保存したv6時代の履歴を読み込むアプリで起きやすいエラーです。信頼できる履歴に限り `allowSystemInMessages: true` で旧挙動に戻せますが、ユーザーが編集できる履歴に付けるとシステムプロンプトを書き換えられるため、公式も推奨していません。

### 逐次表示する streamText

生成途中のトークンから順に表示するなら `streamText` を使います。`textStream` は非同期イテラブルなので `for await` で読めます。v7では全イベントを流す `fullStream` が `stream` に改称され、`fullStream` は非推奨になりました。

```
import { streamText } from 'ai';
import { openai } from '@ai-sdk/openai';

const result = streamText({
  model: openai('gpt-6-astra'),
  prompt: '自己紹介文を書いて',
});

for await (const delta of result.textStream) {
  process.stdout.write(delta);
}
```

日本語の表示を滑らかにする `smoothStream` の分割設定は、[Smooth Text Streamingとは？AI SDK smoothStreamの使い方と日本語の分割設定](/tech/details/8440/)で扱っています。

### 構造化データで受け取る Output.object

JSONを型付きで受け取る用途の `generateObject` はv6で非推奨になり、`generateText` の `output` 引数に `Output.object` を渡す形へ移りました。結果は `result.output` に入ります。

```
import { generateText, Output } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';

const { output } = await generateText({
  model: openai('gpt-6-astra'),
  output: Output.object({
    schema: z.object({
      title: z.string(),
      tags: z.array(z.string()),
    }),
  }),
  prompt: 'この記事のタイトルとタグ候補を生成して',
});

console.log(output.title, output.tags);
```

## Next.jsでチャット画面を作る｜ルートハンドラとuseChat

### ルートハンドラでのUIメッセージストリーム返却

App Routerのルートハンドラで `streamText` を呼び、その `stream` を `toUIMessageStream` で変換して返します。v7の移行ガイドは、結果オブジェクトのメソッドだった `toUIMessageStreamResponse()` などを非推奨とし、次のメジャー版で削除すると明記しています。v7の間は警告付きで動きますが、新しく書くコードを関数版にしておけば、このメソッド削除に伴う修正は不要になります。

```
// app/api/chat/route.ts
import {
  streamText,
  convertToModelMessages,
  toUIMessageStream,
  createUIMessageStreamResponse,
  type UIMessage,
} from 'ai';
import { openai } from '@ai-sdk/openai';

export async function POST(req: Request) {
  const { messages }: { messages: UIMessage[] } = await req.json();

  const result = streamText({
    model: openai('gpt-6-astra'),
    instructions: 'あなたは社内ヘルプデスクの担当者です。',
    messages: await convertToModelMessages(messages),
  });

  return createUIMessageStreamResponse({
    stream: toUIMessageStream({ stream: result.stream }),
  });
}
```

`convertToModelMessages` はPromiseを返すので `await` が要ります。このルートが返す中身を確かめるため、モックモデルに「こん」「にちは」の2断片を返させたところ、レスポンスは `content-type: text/event-stream` と `x-vercel-ai-ui-message-stream: v1` を持つSSEで、本文は次の順に流れました。

```
data: {"type":"start"}
data: {"type":"start-step"}
data: {"type":"text-start","id":"t1"}
data: {"type":"text-delta","id":"t1","delta":"こん"}
data: {"type":"text-delta","id":"t1","delta":"にちは"}
data: {"type":"text-end","id":"t1"}
data: {"type":"finish-step"}
data: {"type":"finish","finishReason":"stop"}
data: [DONE]
```

レスポンスヘッダには `x-accel-buffering: no` も付きます。nginxを前段に置く構成で表示が一括になる場合は、この値がプロキシに届いているかを先に疑います。

### useChatによる送信と描画

`useChat` は `@ai-sdk/react` から読み込みます。送信先は `DefaultChatTransport` で指定し、送信は `sendMessage({ text })` です。メッセージ本文は `message.content` ではなく `message.parts` 配列に入るため、`type === 'text'` の要素を描画します。

```
// app/page.tsx
'use client';
import { useChat } from '@ai-sdk/react';
import { DefaultChatTransport } from 'ai';
import { useState } from 'react';

export default function Chat() {
  const [input, setInput] = useState('');
  const { messages, sendMessage, status, stop } = useChat({
    transport: new DefaultChatTransport({ api: '/api/chat' }),
  });

  return (
    <div>
      {messages.map((m) => (
        <div key={m.id}>
          <strong>{m.role}: </strong>
          {m.parts.map((part, i) =>
            part.type === 'text' ? <span key={i}>{part.text}</span> : null,
          )}
        </div>
      ))}

      <form
        onSubmit={(e) => {
          e.preventDefault();
          if (!input.trim()) return;
          sendMessage({ text: input });
          setInput('');
        }}
      >
        <input value={input} onChange={(e) => setInput(e.target.value)} />
        <button type="submit" disabled={status === 'submitted' || status === 'streaming'}>送信</button>
        {status === 'streaming' && (
          <button type="button" onClick={() => stop()}>停止</button>
        )}
      </form>
    </div>
  );
}
```

`status` は `'submitted'`（送信直後）→`'streaming'`（受信中）→`'ready'` と変わり、失敗時は `'error'` になります。ボタンを無効にするのは送信中と受信中だけにしておくと、`'error'` のあとも画面から送り直せます。毎ターンHTTPを張り直さずに1本の接続で会話を続けたい場合は、[公式のTransportのページ](https://ai-sdk.dev/docs/ai-sdk-ui/transport)にある `WebSocketChatTransport` を使えます。ただしサーバー側もWebSocketのフレームを受けて返す実装に替える必要があり、上の `route.ts` のままでは動きません。

### Svelte・Vue・Angularで使う場合

UI部分はフレームワークごとに別パッケージです。Reactは `useChat` フック、Svelteは `@ai-sdk/svelte`（5.0.159）の `Chat` クラス、Vueは `@ai-sdk/vue`（4.0.159）、Angularは `@ai-sdk/angular`（3.0.159）を使います。Vueはv7で `Chat` クラスが非推奨になり、`useChat` コンポーザブルへ移りました。サーバー側のルートは共通なので、上の `route.ts` の書き方はそのまま使えます。

## ツール呼び出しとエージェントを組む｜tool・isStepCount・ToolLoopAgent

### toolの定義とisStepCountによるループ上限

ツールは `tool()` で定義し、入力の型は `inputSchema` にzodで書きます（v4までの `parameters` ではありません）。ツール実行→結果を踏まえた再推論のループは `stopWhen` で上限を決めます。v7で `stepCountIs` は `isStepCount` に改称されました。7.0.159では `stepCountIs` も同じ関数の別名として残っていますが、移行ガイドは改称として扱っています。

```
import { generateText, tool, isStepCount } from 'ai';
import { openai } from '@ai-sdk/openai';
import { z } from 'zod';

export const weatherTool = tool({
  description: '指定した都市の現在の天気を返す',
  inputSchema: z.object({
    city: z.string().describe('都市名（例: 東京）'),
  }),
  execute: async ({ city }) => {
    // 実際は外部APIを呼ぶ。ここではダミー値
    return { city, tempC: 21, condition: 'くもり' };
  },
});

const result = await generateText({
  model: openai('gpt-6-astra'),
  tools: { weather: weatherTool },
  stopWhen: isStepCount(5),
  prompt: '東京と大阪、暖かいのはどっち？',
});

console.log(result.text, result.steps.length);
```

1回目にツール呼び出しだけ、2回目に文章を返すモックで試すと、`stopWhen: isStepCount(5)` ありでは2ステップで「東京は21度です」が返りました。`stopWhen` を省くと既定値の `isStepCount(1)` で止まり、ツールは実行されても `result.text` は空文字でした。モデルが同じ応答の中で文章も返した場合は、その文章は `text` に残ります。ループの止め方は[公式のLoop Control](https://ai-sdk.dev/docs/agents/loop-control)に条件の組み合わせ方が載っています。

### ToolLoopAgentとツール承認（toolApproval）

同じ設定を複数のルートで使い回すなら `ToolLoopAgent` にまとめます。こちらは `stopWhen` を省いたときの既定が `isStepCount(20)` で、上のモックでも指定なしで2ステップ目まで進みました。

```
import { ToolLoopAgent, isStepCount } from 'ai';
import { openai } from '@ai-sdk/openai';
import { weatherTool } from './weather-tool';

const agent = new ToolLoopAgent({
  model: openai('gpt-6-astra'),
  instructions: 'あなたは天気アシスタント。ツールで調べてから答える。',
  tools: { weather: weatherTool },
  stopWhen: isStepCount(5),
  toolApproval: { weather: 'user-approval' },
});

const { text } = await agent.generate({ prompt: '東京の天気は？' });
```

削除や送金のように人の確認を挟みたいツールは、v7では `tool()` 側の `needsApproval`（非推奨）ではなく、呼び出し側の `toolApproval` に書きます。値は `'user-approval'`・`'approved'`・`'denied'`・`'not-applicable'` の4種類です。`'user-approval'` を付けたモックでは、ツールは実行されず、結果に `tool-approval-request` が入って `finishReason` が `tool-calls` で止まりました。画面側では `useChat` の `addToolApprovalResponse` で承認・却下を返します（[公式のTool Approvals](https://ai-sdk.dev/docs/agents/tool-approvals)）。承認フローの設計そのものは[ヒューマンインザループ（HITL）とは？意味・HOTLとの違い・承認の実装と導入判断](/tech/details/11415/)で詳しく扱っています。

## LangChainとVercel AI SDKを併用する｜@ai-sdk/langchain

### LangChain・LangGraphとAI SDKの役割分担

LangChainとAI SDKは競合というより担当範囲が違います。LangChain・LangGraphはエージェントの分岐・状態・RAGの組み立てが中心で、画面側にもLangGraph用の `useStream` フックを用意しています。AI SDKはモデル呼び出しと `useChat`・UIメッセージストリームが中心です。この章では、LangChain側でロジックを書き、画面はAI SDKの `useChat` にそろえる組み合わせを扱います。

| やりたいこと                       | 向いている側                                 |
| ---------------------------- | -------------------------------------- |
| 1〜数ステップのツール呼び出し付きチャット        | AI SDKだけ                               |
| 分岐・再試行・中断再開のあるワークフロー         | LangGraph＋AI SDKのUI                    |
| 既存のLangChain資産（RAG・チェーン）の画面化 | LangChain＋@ai-sdk/langchain            |
| Pythonで書いたLangGraphをブラウザから呼ぶ | LangSmith Deployment＋@ai-sdk/langchain |

判断の目安は、エージェントの状態を会話をまたいで保存・再開する必要があるかです。必要ならLangGraphのチェックポイントに任せ、不要なら依存を増やさずAI SDKだけで書く方が保守しやすくなります。LangChainとLangGraphの分担は[LangChainとLangGraphの違いと使い分け｜v1.0以降の関係をコードで確認【2026年10月】](/tech/details/4059/)を、JavaScript版LangChainの基本は[LangChain.jsとは？npm導入からcreateAgent・構造化出力・会話メモリまで【v1.5対応】](/tech/details/3590/)を参照してください。

### LangChainエージェントとuseChatのストリーム連携

連携用の `@ai-sdk/langchain`（3.0.159）は、`@langchain/core` 1.0以上と `@langchain/langgraph` 0.2以上をpeer依存に持ちます。`toBaseMessages` で `useChat` のメッセージをLangChainの形式に変え、エージェントのストリームを `toUIMessageStream` でAI SDKの形式に戻します（[公式のLangChainアダプタ](https://ai-sdk.dev/providers/adapters/langchain)）。クライアント側は前章の `page.tsx` の送信先を `/api/langchain` に変えるだけです。

```
npm install @ai-sdk/langchain @langchain/core langchain @langchain/openai
```

```
// app/api/langchain/route.ts
import { createAgent, tool } from 'langchain';
import { ChatOpenAI } from '@langchain/openai';
import { toBaseMessages, toUIMessageStream } from '@ai-sdk/langchain';
import { createUIMessageStreamResponse, type UIMessage } from 'ai';
import { z } from 'zod';

const searchDocs = tool(
  async ({ query }) => `検索デモです（実検索は行っていません）: ${query}`,
  {
    name: 'search_docs',
    description: '社内文書を検索する',
    schema: z.object({ query: z.string() }),
  },
);

const agent = createAgent({
  model: new ChatOpenAI({ model: 'gpt-6-astra' }),
  tools: [searchDocs],
});

export async function POST(req: Request) {
  const { messages }: { messages: UIMessage[] } = await req.json();

  const stream = await agent.stream(
    { messages: await toBaseMessages(messages) },
    { streamMode: ['values', 'messages'] },
  );

  return createUIMessageStreamResponse({
    stream: toUIMessageStream(stream),
  });
}
```

このコードはlangchain 1.6.0・@langchain/openai 1.8.0の型定義で型検査を通しています。ツール実行の進み具合も画面に出したい場合は `streamMode` に `'tools'` を、ツール内で `config.writer()` を使って独自データを送る場合は `'custom'` を足します。

### LangGraphのstreamMode別に見た本文イベントの有無

`toUIMessageStream` はLangGraphのストリームを自動判別しますが、本文のトークンを取り出すのは `messages` モードの出力からです。トークン単位でストリーミングできるフェイクモデル（`FakeListChatModel`）を1ノードのStateGraphに置き、`streamMode` だけを変えてUIメッセージストリームを比べた結果が次の表です。

| streamMode               | 流れたイベント                   | 画面の本文 |
| ------------------------ | ------------------------- | ----- |
| `['values', 'messages']` | start〜text-delta×5〜finish | 表示される |
| `['messages']`           | start〜text-delta×5〜finish | 表示される |
| `['values']`             | start・finishのみ            | 空     |
| `['updates']`            | start・finishのみ            | 空     |

`values` だけでもエラーは出ず、ステータス200で正常終了します。そのため「つながっているのに何も表示されない」という症状になり、原因に気づきにくくなります。[LangGraphのストリーミングの説明](https://docs.langchain.com/oss/javascript/langgraph/streaming)でも、`values` と `updates` は状態の、`messages` はLLM出力をトークン単位で流すモードと区別されています。もう1つの落とし穴として、ストリーミングに対応しないモデル（LangChainのテスト用 `fakeModel` など）をノードに置くと、`messages` を指定していても本文のイベントは出ませんでした。テストでUIまで確かめるときは、トークンを流すフェイクを選びます。

### デプロイ済みLangGraphへのブラウザ直接接続

LangGraphをLangSmith Deployment（旧LangGraph Platform）や `langgraph dev` のローカルサーバーで動かしている場合は、Next.js側にルートハンドラを書かずに `LangSmithDeploymentTransport` を `useChat` に渡せます。`graphId` の既定値は `'agent'` です。

```
'use client';
import { useChat } from '@ai-sdk/react';
import { LangSmithDeploymentTransport } from '@ai-sdk/langchain';
import { useMemo } from 'react';

export default function LangGraphChat() {
  const transport = useMemo(
    () => new LangSmithDeploymentTransport({ url: 'http://localhost:2024' }),
    [],
  );
  const { messages, sendMessage } = useChat({ transport });
  // 描画は前章のpage.tsxと同じ
}
```

本番のデプロイ先に `apiKey` を渡すと、キーがブラウザに配られる点に注意が必要です。公開サイトではこの方式を避け、ルートハンドラ経由でサーバー側からキーを付けます。デプロイ環境と料金は[LangGraph Platform（旧LangGraph Cloud）とは？現LangSmith Deploymentのデプロイ手順と料金【2026年10月】](/tech/details/6175/)にまとめています。

### 旧LangChainAdapterからの移行

ai v3・v4の解説によく出てくる `LangChainAdapter.toDataStreamResponse()` は、本体の `ai` から削除されています。古いサンプルを動かす場合は、次のように `@ai-sdk/langchain` へ置き換えます。

```
// 旧: ai v3・v4（現在の ai には存在しない）
import { LangChainAdapter } from 'ai';
return LangChainAdapter.toDataStreamResponse(await chain.stream(input));

// 新: @ai-sdk/langchain
import { toUIMessageStream } from '@ai-sdk/langchain';
import { createUIMessageStreamResponse } from 'ai';
return createUIMessageStreamResponse({
  stream: toUIMessageStream(await chain.stream(input)),
});
```

## 古いサンプルが動かないときの確認点

検索で見つかる解説の多くはv4〜v6の書き方です。v7で動かないとき、または非推奨の警告が出るときは、次の対応表で置き換え先を確かめます。

| 古い書き方                                | AI SDK 7の書き方                                      | v7での扱い    |
| ------------------------------------ | ------------------------------------------------- | --------- |
| `result.toUIMessageStreamResponse()` | `toUIMessageStream＋createUIMessageStreamResponse` | 非推奨       |
| `stepCountIs(n)`                     | `isStepCount(n)`                                  | 改称（別名で残存） |
| `system: '...'`                      | `instructions: '...'`                             | 改称        |
| `tool({ needsApproval })`            | `toolApproval`（呼び出し側）                             | 非推奨       |
| `result.fullStream`                  | `result.stream`                                   | 非推奨       |
| `onFinish` ／ `onStepFinish`          | `onEnd` ／ `onStepEnd`                             | 改称        |
| `require('ai')`                      | import 文（ESM）                                     | 廃止        |

改称の多くは公式のcodemodで自動置換できます。プロジェクトのルートで `npx @ai-sdk/codemod v7` を実行し、残った箇所を手で直す流れが移行ガイドの推奨です。`generateObject` の非推奨化と `convertToModelMessages` の非同期化はv5→v6で入った変更なので、v6から上げる場合は対象外です。

社内のチャットボットや業務エージェントをAI SDKやLangGraphで作る場合の設計・実装は、[生成AI開発・AI受託開発](/service/ai/development/)で支援しています。

## よくある質問

### Vercel AI SDKの最新バージョンは？

2026年10月31日時点で7.0.159です。AI SDK 7の初版7.0.0は2026年6月25日に公開されました。v6系は6.0.320が `ai-v6` タグで提供されています。最新版は `npm view ai dist-tags` で確認できます。

### LangChainとVercel AI SDKは併用できますか？

できます。`@ai-sdk/langchain` の `toBaseMessages` と `toUIMessageStream` で、LangChain・LangGraphのエージェントをAI SDKの `useChat` にそのままつなげます。LangGraphから流すときは `streamMode` に `'messages'` を含めます。

### toUIMessageStreamResponseはもう使えませんか？

AI SDK 7でも動きますが、`streamText` の結果オブジェクトのメソッドとしては非推奨で、次のメジャー版で削除予定です。新しく書くなら `createUIMessageStreamResponse({ stream: toUIMessageStream({ stream: result.stream }) })` を使います。

### ツールを渡したのに応答テキストが空になるのはなぜ？

`generateText` と `streamText` の `stopWhen` の既定値が `isStepCount(1)` だからです。最初の応答がツール呼び出しだけだった場合、ツールを実行した時点でループが終わり、結果を踏まえて文章を書くステップまで進みません。`stopWhen: isStepCount(5)` のように上限を指定します。

### LangChainAdapterが見つからないのはなぜ？

本体の `ai` パッケージから削除されたためです。現在は `@ai-sdk/langchain` の `toUIMessageStream` と、`ai` の `createUIMessageStreamResponse` を組み合わせます。

## 関連記事

- [Vercel AI SDK v6とは？新機能（ToolLoopAgent・needsApproval）とv7との違い・移行【2026】](/tech/details/10402/)
- [LangChainとLangGraphの違いと使い分け｜v1.0以降の関係をコードで確認【2026年10月】](/tech/details/4059/)
- [LangChain.jsとは？npm導入からcreateAgent・構造化出力・会話メモリまで【v1.5対応】](/tech/details/3590/)
- [Smooth Text Streamingとは？AI SDK smoothStreamの使い方と日本語の分割設定](/tech/details/8440/)
- [LangGraphのTool Calling実装｜ToolNode・create\_agent・エラー処理とループ上限【2026年10月】](/tech/details/5428/)

---

出典: [Vercel AI SDKの使い方｜AI SDK 7でNext.jsチャットとLangChain連携を実装](<https://www.issoh.co.jp/tech/details/9551/>)（株式会社一創）
