Docs
CodeRabbit
Cloudflare
AG Grid
SerpAPI
Netlify
OpenRouter
Neon
WorkOS
Clerk
Electric
PowerSync
Sentry
Railway
Prisma
Strapi
Unkey
CodeRabbit
Cloudflare
AG Grid
SerpAPI
Netlify
OpenRouter
Neon
WorkOS
Clerk
Electric
PowerSync
Sentry
Railway
Prisma
Strapi
Unkey
Persistence (Advanced)
Embeddings
Reranking
Evaluate
Sandboxes (Advanced)
Class References
Function References
Interface References
Type Alias References
Variable References
Transports

WebSockets

You want one connection for the whole conversation, not one request per message. Use the built-in webSocket() adapter. It opens one socket for the conversation. If a durable run drops, it reconnects automatically.

1. Connect from the client

typescript
import { useChat, webSocket } from "@tanstack/ai-react";

const connection = webSocket("/api/chat-ws");

const { messages, sendMessage } = useChat({ connection });
import { useChat, webSocket } from "@tanstack/ai-react";

const connection = webSocket("/api/chat-ws");

const { messages, sendMessage } = useChat({ connection });

2. Accept the socket on the server

On Cloudflare Workers or Durable Objects, use toWebSocketResponse:

typescript
import { chat, memoryStream, toWebSocketResponse } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";

export default {
  fetch(request: Request): Response {
    return toWebSocketResponse(request, {
      durability: (ctx) => memoryStream(ctx.request),
      onRun: ({ messages, threadId, runId }) =>
        chat({
          adapter: openaiText("gpt-5.6"),
          messages,
          threadId,
          runId,
        }),
    });
  },
};
import { chat, memoryStream, toWebSocketResponse } from "@tanstack/ai";
import { openaiText } from "@tanstack/ai-openai";

export default {
  fetch(request: Request): Response {
    return toWebSocketResponse(request, {
      durability: (ctx) => memoryStream(ctx.request),
      onRun: ({ messages, threadId, runId }) =>
        chat({
          adapter: openaiText("gpt-5.6"),
          messages,
          threadId,
          runId,
        }),
    });
  },
};

On other hosts, such as Node, accept the socket yourself. Then pass it to toWebSocketStream. See Resumable Streams: WebSockets for this setup, the wire protocol, and the reconnect details.

To use your own wire format or a server that you do not control, write a custom adapter. See Custom Transports.

Send two messages. Both replies stream over the same socket.