Skip to content
mordn
Esc
↑↓navigate↵open⌘Jpreview
On this page

Streaming

How the handler streams, bounds tool loops, maps errors, and exposes post-turn telemetry.

createChatHandler streams the model response through the Vercel AI SDK UI message protocol. The widget currently commits partial updates at a fixed 50 ms throttle.

Bound tool loops

import { stepCountIs } from 'ai';

createChatHandler({
  getUserId: getChatUserId,
  model,
  store,
  stopWhen: stepCountIs(5),
});

stopWhen accepts an AI SDK stop condition. The default is bounded; use stepCountIs(1) to prevent chaining.

Error mapping

createChatHandler({
  getUserId: getChatUserId,
  model,
  store,
  onError: (error) => isAbortError(error)
    ? 'Response stopped.'
    : 'Something went wrong. Please try again.',
});

onError controls user-facing text. Server error logging remains enabled unless logErrors: false is set. Disable it only when another sink captures the same failures.

Post-turn telemetry

onChatFinish runs after persistence. It can inspect AI SDK usage and provider metadata; its own failures are logged and swallowed.

createChatHandler({
  getUserId: getChatUserId,
  model,
  store,
  onChatFinish: async ({ ctx, usage, providerMetadata }) => {
    await analytics.track({
      userId: ctx.userId,
      conversationId: ctx.conversationId,
      usage,
      providerMetadata,
    });
  },
});

Do not save the turn again in this hook. See Streaming reliability for proxy buffering, timeouts, and deployment probes.