Message Timing

Display streaming performance stats — TTFT, total time, tok/s, and chunk count — as a badge with hover popover.

Badge
On hover
First token312ms
Total1.23s
Speed82.5 tok/s
Chunks47

This component is experimental. The API and displayed metrics may change in future versions. When used with the Vercel AI SDK, token counts and tok/s are estimated client-side and may be inaccurate — see Accuracy below.

Getting Started

Add message-timing

npx shadcn@latest add https://r.assistant-ui.com/message-timing.json

This adds a /components/assistant-ui/message-timing.tsx file to your project.

Use in your application

Place MessageTiming inside ActionBarPrimitive.Root in your thread.tsx. It will inherit the action bar's auto-hide behaviour and only renders after the stream completes.

/components/assistant-ui/thread.tsx
import { ActionBarPrimitive } from "@assistant-ui/react";
import { MessageTiming } from "@/components/assistant-ui/message-timing";

const AssistantActionBar: FC = () => {
  return (
    <ActionBarPrimitive.Root
      hideWhenRunning
      autohide="not-last"
    >
      <ActionBarPrimitive.Copy />
      <ActionBarPrimitive.Reload />
      <MessageTiming />
    </ActionBarPrimitive.Root>
  );
};

What It Shows

The badge displays totalStreamTime inline and reveals a popover on hover with the full breakdown:

MetricDescription
First tokenTime from request start to first text chunk (TTFT)
TotalTotal wall-clock time from start to stream end
SpeedOutput tokens per second (hidden for very short messages)
ChunksNumber of stream chunks received

Accuracy

Timing accuracy depends on how your backend is connected.

assistant-stream (accurate)

When using assistant-stream on the backend, token counts come directly from the model's usage data sent in step-finish chunks. The tokensPerSecond metric is exact whenever your backend reports outputTokens.

Vercel AI SDK (estimated)

When using the AI SDK integration (useChatRuntime), token counts are estimated client-side using a 4 characters per token approximation. This can overcount significantly for short messages.

API Reference

MessageTiming component

PropTypeDefaultDescription
classNamestringAdditional class names on the root element
side"top" | "right" | "bottom" | "left""right"Side of the tooltip relative to the badge

Renders null until totalStreamTime is available (i.e., while streaming or for user messages).

For the underlying useMessageTiming() hook, field definitions, and runtime-specific setup (LocalRuntime, ExternalStore, etc.), see the Message Timing guide.

  • Message Timing guideuseMessageTiming() hook, runtime support table, and custom timing UI
  • Thread — The action bar context that MessageTiming is typically placed inside