Sockudo
Server

AI Transport providers

Stream model output from Vercel AI SDK, OpenAI, Anthropic, OpenAI-compatible APIs, and custom providers through Sockudo AI Transport.

Sockudo AI Transport is provider-neutral. Sockudo carries ordered, durable turn state; your agent chooses how to call the model and converts provider output into AI SDK UI message chunks.

The JavaScript SDK has two integration families:

IntegrationImportBest for
Vercel AI SDK transport@sockudo/ai-transport/vercelApps already using ai, streamText, Chat, useChat, Vue, React, or Svelte AI SDK UI primitives.
Direct provider adapters@sockudo/ai-transport/providersWorkers that call OpenAI, Anthropic, OpenAI-compatible HTTP/SSE endpoints, or local model servers directly.
Core codec transport@sockudo/ai-transportCustom model protocols, custom UI projections, or non-Vercel message shapes.

Credits

Sockudo AI Transport is heavily inspired by Ably AI Transport, and Ably's public AI Transport docs and SDK were the main product inspiration for this layer. The Sockudo implementation maps those ideas onto Sockudo Protocol V2, durable history, versioned messages, presence, push, and the @sockudo/client SDK in this monorepo.

Provider flow

The provider never needs to know about connection recovery, rewind, history cursors, branch trees, presence, or multi-device fanout. It streams chunks. Sockudo makes those chunks durable and observable.

Vercel AI SDK

Use Vercel AI SDK when you want provider packages, tool calling, and UI message streams to stay in the ai ecosystem.

// server/api/chat.post.ts
import { streamText } from "ai";
import { createServerTransport } from "@sockudo/ai-transport/vercel";
import { realtimeClient } from "../utils/sockudo";

export default defineEventHandler(async (event) => {
  const body = await readBody(event);

  const transport = createServerTransport({
    client: realtimeClient(),
    channelName: body.channelName,
  });

  const turn = transport.newTurn({
    turnId: body.turnId,
    invocationId: body.invocationId,
    inputEventId: body.inputEventId,
    clientId: body.clientId,
    onCancel(request) {
      return request.filter.all === true || request.turnOwners.get(body.turnId) === body.clientId;
    },
  });

  event.waitUntil?.((async () => {
    await turn.start();
    const result = streamText({
      model: "openai/gpt-5-mini",
      system: "You are a concise incident-room assistant.",
      prompt: body.messages.at(-1)?.parts?.map((part) => part.text ?? "").join("") ?? "",
      abortSignal: turn.abortSignal,
    });
    await turn.streamResponse(result.toUIMessageStream());
    await turn.end("complete");
    transport.close();
  })());

  setResponseStatus(event, 202);
});

The frontend can use the Vercel-compatible transport in React, Vue, or Svelte.

import { Chat } from "@ai-sdk/vue";
import { provideChatTransport } from "@sockudo/ai-transport/vercel/vue";

const provider = provideChatTransport({
  api: "/api/chat",
  channelName: "private-ai:user-42:sess-01J",
  client: sockudoClient,
  clientId: "user-42",
});

const chat = new Chat({
  id: "private-ai:user-42:sess-01J",
  transport: provider.chatTransport.value,
});

await chat.sendMessage({ text: "Summarize the last deploy failure." });

Direct provider support

The @sockudo/ai-transport/providers entry point supports these built-in adapters:

Provider pathFunctionNotes
OpenAI-compatible HTTP/SSEstreamOpenAICompatibleTextUses Chat Completions-compatible /chat/completions streaming.
OpenAI-compatible reusable providercreateOpenAICompatibleProviderGood for named provider registries.
OpenAI SDK Chat CompletionsstreamOpenAIChatCompletion / createOpenAISdkProviderUses a structural subset of the official OpenAI SDK.
OpenAI SDK ResponsesstreamOpenAIResponse / createOpenAISdkProvider({ mode: "responses" })Maps output text and tool argument deltas to UI chunks.
Anthropic SDK MessagesstreamAnthropicMessage / createAnthropicSdkProviderMaps text, thinking, tool use, and finish reasons.

OpenAI-compatible presets are:

NameDefault base URL
openaihttps://api.openai.com/v1
openrouterhttps://openrouter.ai/api/v1
groqhttps://api.groq.com/openai/v1
togetheraihttps://api.together.xyz/v1
fireworkshttps://api.fireworks.ai/inference/v1
deepseekhttps://api.deepseek.com
perplexityhttps://api.perplexity.ai
mistralhttps://api.mistral.ai/v1
xaihttps://api.x.ai/v1
ollamahttp://127.0.0.1:11434/v1
lmstudiohttp://127.0.0.1:1234/v1

Local providers such as Ollama and LM Studio may omit apiKey when the local server does not require one.

OpenAI-compatible HTTP example

import {
  createOpenAICompatibleProvider,
  runDirectLlmTurn,
} from "@sockudo/ai-transport/providers";

const provider = createOpenAICompatibleProvider({
  provider: "groq",
  apiKey: process.env.GROQ_API_KEY,
  model: "llama-3.3-70b-versatile",
});

await runDirectLlmTurn(turn, provider, {
  prompt: "Write a remediation plan for a Redis fanout incident.",
  maxOutputTokens: 800,
});

OpenAI SDK examples

import OpenAI from "openai";
import {
  createOpenAISdkProvider,
  runDirectLlmTurn,
} from "@sockudo/ai-transport/providers";

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

const chatProvider = createOpenAISdkProvider({
  client: openai,
  mode: "chat",
  model: "gpt-4.1-mini",
});

await runDirectLlmTurn(turn, chatProvider, {
  messages: [
    { role: "system", content: "Answer as a production engineer." },
    { role: "user", content: "Why did reconnect recovery fail?" },
  ],
});
const responsesProvider = createOpenAISdkProvider({
  client: openai,
  mode: "responses",
  model: "gpt-5-mini",
});

await runDirectLlmTurn(turn, responsesProvider, {
  prompt: "Explain the latest channel history page in plain English.",
  body: {
    reasoning: { effort: "low" },
  },
});

Anthropic SDK example

import Anthropic from "@anthropic-ai/sdk";
import {
  createAnthropicSdkProvider,
  runDirectLlmTurn,
} from "@sockudo/ai-transport/providers";

const anthropic = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });

const provider = createAnthropicSdkProvider({
  client: anthropic,
  model: "claude-sonnet-4-5",
  system: "Be concise and include risk levels.",
});

await runDirectLlmTurn(turn, provider, {
  prompt: "Audit this failed push notification delivery chain.",
});

Provider registry

Use a registry when the UI lets a user or tenant select a model provider.

import {
  createAnthropicSdkProvider,
  createDirectLlmProviderRegistry,
  createOpenAICompatibleProvider,
} from "@sockudo/ai-transport/providers";

const providers = createDirectLlmProviderRegistry({
  groq: createOpenAICompatibleProvider({
    provider: "groq",
    apiKey: process.env.GROQ_API_KEY,
    model: "llama-3.3-70b-versatile",
  }),
  local: createOpenAICompatibleProvider({
    provider: "ollama",
    model: "llama3.2",
  }),
  anthropic: createAnthropicSdkProvider({
    client: anthropic,
    model: "claude-sonnet-4-5",
  }),
});

const stream = await providers.streamText("local", {
  prompt: "Return a JSON incident summary.",
});

Custom provider

Any provider that returns ReadableStream<VercelOutput> can participate.

import type { DirectLlmProvider } from "@sockudo/ai-transport/providers";

const provider: DirectLlmProvider = {
  async streamText(request) {
    const words = (request.prompt ?? "").split(/\s+/);

    return new ReadableStream({
      start(controller) {
        controller.enqueue({ type: "start" });
        controller.enqueue({ type: "text-start", id: "answer" });
        for (const word of words) {
          controller.enqueue({ type: "text-delta", id: "answer", delta: `${word} ` });
        }
        controller.enqueue({ type: "text-end", id: "answer" });
        controller.enqueue({ type: "finish", finishReason: "stop" });
        controller.close();
      },
    });
  },
};

Tool calling and human approval

Tool calls are just streamed UI message chunks. The transport persists every tool-input delta and the final tool state, so a user can approve from another tab or after a reconnect.

Choosing an integration

You haveUse
Vercel AI SDK streamText already wired@sockudo/ai-transport/vercel
A provider with OpenAI-compatible SSEcreateOpenAICompatibleProvider
Official OpenAI SDKcreateOpenAISdkProvider
Official Anthropic SDKcreateAnthropicSdkProvider
A custom internal model gatewayDirectLlmProvider
A non-Vercel UI modelCore codec API from @sockudo/ai-transport

Keep provider API keys server-side. Browser clients should only receive Sockudo public app keys, private/presence auth responses, and short-lived Protocol V2 capability tokens.

On this page