Skip to content

RTVI

RTVI

Audio is only half of what a client needs. A usable UI also wants transcriptions as they arrive, who is speaking right now, and when the bot is thinking. RTVI (Real-Time Voice Interface) is the JSON protocol that carries those events over the WebRTC data channel.

Because it is an open protocol with existing web, iOS and Android client SDKs, a jargo server works with clients you did not write.

Adding it

One processor, placed upstream of the output transport, which is what actually carries the messages to the client:

pipeline.New(
    t.Input(), vadProc, stt, turnsProc,
    agg.User(), llm, tts,
    rtvi.NewProcessor(),   // <- here
    t.Output(), agg.Assistant(),
)

That is the whole integration. The processor watches frames going past and translates the interesting ones into client messages.

What it does

    flowchart LR
    C(["client"]) -->|"client-ready"| P["rtvi.Processor"]
    P -->|"bot-ready"| C

    F["pipeline frames"] --> P
    P -->|"user-transcription<br/>bot-llm-text<br/>bot-started-speaking<br/>metrics …"| C

    style P fill:#dbeafe,stroke:#2563eb
  

Incoming client messages arrive as InputTransportMessageFrames; outgoing ones are pushed downstream as OutputTransportMessageUrgentFrames. Urgent, so a transcription reaches the UI ahead of queued audio instead of lagging behind the speech it describes.

The messages

Every message is {"label":"rtvi-ai","type":…,"id":…,"data":…}. The processor speaks protocol version 2.0.0.

TypeMeaning
client-readybot-readyThe handshake.
user-transcriptionWhat the user said (interim and final).
bot-transcriptionWhat the bot said.
bot-llm-text / bot-tts-textStreamed response text, per stage.
user-started-speaking / user-stopped-speakingTurn boundaries.
bot-started-speaking / bot-stopped-speakingBot speech boundaries.
bot-llm-started / bot-llm-stoppedModel is generating.
bot-tts-started / bot-tts-stoppedSpeech is being synthesized.
llm-function-call-in-progress / llm-function-call-resultTool activity.
metricsTTFB, processing time, token usage.
send-textClient sends text instead of speech.
errorSomething failed.

The constants live in processor/rtvi (rtvi.TypeUserTranscription and so on), so you do not hand-write the strings.

Clients

For the browser, use the client packages in jargo-client-react . The nextjs-voicebot example there talks to any of the examples/voice/<provider> backends:

go run ./examples/voice/openai                        # backend on :8080
NEXT_PUBLIC_JARGO_URL=http://localhost:8080 npm run dev   # client

The per-provider examples are headless: they expose the /offer endpoint and no UI, so a client is required. examples/echo and examples/voicebot serve their own minimal page and need nothing extra.

Without RTVI

The processor is optional. Leave it out and you still have working audio. You just have no event stream, so the UI cannot show live transcriptions or speaking state. Phone transports have no data channel at all, which is why examples/twiliobot omits it.

To send your own application messages instead, push an OutputTransportMessageFrame (ordered with the audio) or an OutputTransportMessageUrgentFrame (ahead of it), and read InputTransportMessageFrame for what the client sends back.