Skip to content

Voqalize and pipecat

Pipecat sits at both ends of a Voqalize call, and at neither end is it wrapped.

In the browser it is your integration: one HTTP request of ours returns what a pipecat transport connects with, and every line after that is pipecat. Inside the voice tier it is what we build the pipeline out of — transport, voice activity detection, the speech services, the avatar processor. Between the two, its RTVI message format is what our wire carries.

The one place it is absent is your server. Installing the Python SDK pulls no pipecat at all.

Two packages do the work:

Terminal window
pnpm add @pipecat-ai/client-js @pipecat-ai/small-webrtc-transport

sessions.connect returns the connect params; client.connect(params) takes them. The handshake is that request and the one line of glue around it, and it is the entire Voqalize-specific surface in your page.

The demos add two more, and neither is required: @pipecat-ai/client-react for the hooks, and @pipecat-ai/voice-ui-kit for components. What every demo uses is declared in demos/shared/package.json.

Everything you learn here transfers. usePipecatConversation for the transcript, useUICommandHandler for inbound actions, sendClientMessage for outbound context — those are pipecat’s APIs, documented by pipecat, and they behave the same against any pipecat server.

An action from your brain and a click from your page are both RTVI messages — {id, label, type, data} — riding the peer connection’s data channel. Our wire carries them verbatim in both directions and interprets nothing about them.

The whitelist, in both directions:

Brain → pagePage → brain
server-messageclient-message
server-responsesend-text
error-responseui-event
ui-commandui-snapshot
ui-job-groupui-cancel-job-group

A type absent from that list does not cross in either direction. bot-* and llm-* are the voice tier’s own assertions about the media and the model — that speech started, that the model is thinking — and a brain must not be able to forge them. Your page can trust a bot-started-speaking because only the runtime that moved the audio can emit one.

The list is enumerated in proto/voqalize/frames/frames.proto, which is the contract of record.

pip install voqalize-agent-sdk installs websockets, protobuf, pydantic and the JWT library, and nothing else. A brain is callbacks over a socket. Pipecat runs on our side of that socket, where the audio is.

That matters when your brain is a route inside a service you already deploy: a voice integration adds no media dependency to a process that has never needed one, and nothing in your dependency tree has an opinion about audio.

The avatar is a talking head driven by RTVI rather than by a video track. AvatarProcessor sits in the pipeline between text-to-speech and the output transport and emits lipsync metadata as one custom RTVI message; the browser package renders it. It works against any pipecat pipeline, not only ours, and it is MIT-licensed.

There was one — @voqalize/client-react — and it was deprecated on 2026-08-24 with no successor. It wrapped the connect call and re-exported hooks that were already pipecat’s, which made it a second surface to learn and a release behind every pipecat version.

The class of problem it existed to hide is now handled where it belongs: the two credential paths are the same route with a different signer, and a recording asked for on a key that may not record is refused when the session is minted rather than warned about in a console.

@pipecat-ai/client-js at >=1.5.0 <2 is the floor, declared as a peer dependency in demos/shared/package.json and exercised by every demo in the repository. We track pipecat’s 1.x line and pin no upper bound below the major.

The Python side pins pipecat-ai only inside the voice tier, which you do not install.