Voice UI Kit

usePipecatConversation

Hook that derives a clean, ordered conversation stream from RTVI events.

Overview

usePipecatConversation provides access to conversation state managed by the ConversationProvider. The provider is automatically included when using PipecatAppBase and handles all Pipecat RTVI events to produce a clean message list suitable for rendering a chat transcript. It handles streaming text, placeholder messages, finalization, and merging of consecutive messages from the same role.

Setup

The ConversationProvider is automatically included when you use PipecatAppBase, so no additional setup is required:

import { PipecatAppBase, usePipecatConversation } from "@pipecat-ai/voice-ui-kit";

export default function App() {
  return (
    <PipecatAppBase
      transportType="smallwebrtc"
      connectParams={{ webrtcUrl: "/api/offer" }}
    >
      <YourApp />
    </PipecatAppBase>
  );
}

Usage

Basic

import { usePipecatConversation } from "@pipecat-ai/voice-ui-kit";

export function ConversationList() {
  const { messages } = usePipecatConversation();
  return (
    <ul>
      {messages.map((m, i) => (
        <li key={i}>
          <strong>{m.role}:</strong> {typeof m.content === "string" ? m.content : "[component]"}
        </li>
      ))}
    </ul>
  );
}

With callback

const { messages } = usePipecatConversation({
  onMessageAdded: (message) => console.log("New message:", message),
});

Full example

import React, { useEffect, useRef } from "react";
import { usePipecatConversation } from "@pipecat-ai/voice-ui-kit";

export function ConversationExample() {
  const { messages } = usePipecatConversation();
  const endRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    endRef.current?.scrollIntoView({ behavior: "smooth" });
  }, [messages]);

  return (
    <div style={{ height: 300, overflow: "auto", fontFamily: "monospace", fontSize: 12 }}>
      {messages.map((m, i) => (
        <div key={i}>
          <strong>[{m.role}]</strong> {typeof m.content === "string" ? m.content : "[component]"}
          <span style={{ opacity: 0.6, marginLeft: 8 }}>
            {new Date(m.createdAt).toLocaleTimeString()}
          </span>
        </div>
      ))}
      <div ref={endRef} />
    </div>
  );
}

Injecting messages

You can inject messages directly via the hook, or by using ConsoleTemplate callbacks.

import React from "react";
import { usePipecatConversation } from "@pipecat-ai/voice-ui-kit";

export function InjectViaHook() {
  const { injectMessage } = usePipecatConversation();
  return (
    <button
      onClick={() =>
        injectMessage({ role: "system", content: "Hello from the system" })
      }
    >
      Inject message
    </button>
  );
}