Frameworks: External chain and RTVI
March 1, 2026 · View on GitHub
This document describes the frameworks processors ported from upstream frameworks: external chain (Langchain/Strands-style backends) and the RTVI protocol.
1. External chain (Langchain / Strands)
Langchain and Strands are Python-only. In Go, external_chain calls an HTTP endpoint (e.g. a Python sidecar running Langchain or Strands) with the last user message from LLMContextFrame and streams the response back as LLMTextFrame with LLMFullResponseStartFrame / LLMFullResponseEndFrame.
Config
Add external_chain to plugins and set plugin_options["external_chain"]:
{
"plugins": ["external_chain", "..."],
"plugin_options": {
"external_chain": {
"url": "http://localhost:8765/chain",
"method": "POST",
"stream": true,
"timeout_sec": 60,
"transcript_key": "input",
"headers": { "X-Custom": "value" }
}
}
}
- url (required): HTTP endpoint. When empty, the processor no-ops (forwards frames).
- method:
POST(default) orGET. - stream: if true, response is parsed as SSE or line-delimited JSON chunks (
data: {"text":"..."}or{"content":"..."}). - timeout_sec: request timeout; default 30.
- transcript_key: JSON key for the user message in the request body; default
"input". Request body is{ "<transcript_key>": "<last user message text>" }. - headers: optional HTTP headers.
Running a Langchain/Strands sidecar
- Run your Python service that exposes an HTTP endpoint (e.g.
/chain) accepting JSON{"input": "user message"}and responding with JSON{"text": "..."}or streaming SSE. - Point
external_chain.urlat that endpoint (e.g.http://localhost:8765/chain). - Ensure the pipeline feeds
LLMContextFrameinto the chain (e.g. use an aggregator that produces context and then this processor).
2. RTVI (Real-Time Voice Interface)
RTVI is the client–server messaging protocol (bot-ready, send-text, errors, etc.). The Go implementation provides:
- RTVIProcessor (
plugins:rtvi): HandlesStartFrame(sends bot-ready),RTVIClientMessageFrame(client-ready, send-text →TranscriptionFrame), andErrorFrame(sends RTVI error). - RTVI serializer: When the WebSocket connection uses
?rtvi=1, the server uses the RTVI serializer so that client messages are parsed intoRTVIClientMessageFrameand pipeline frames are converted to RTVI server messages (bot-ready, bot-output, user-transcription, error, etc.).
Enabling RTVI
- WebSocket: Connect to
/ws?rtvi=1so the server selects the RTVI serializer. - Plugins: Include
rtviinplugins(typically first, so client messages are handled before other processors). - plugin_options (optional):
"rtvi": { "protocol_version": "1.2.0" }.
Client flow
- Client connects to
ws://host:port/ws?rtvi=1. - Server pushes
StartFrame; RTVIProcessor sends a bot-ready RTVI message. - Client sends RTVI messages, e.g. client-ready (version, about) and send-text (
{"content": "hello"}). The serializer turns these intoRTVIClientMessageFrame; RTVIProcessor turns send-text intoTranscriptionFrameand pushes it downstream (e.g. to LLM → TTS). - Pipeline output (e.g.
LLMTextFrame,TranscriptionFrame,ErrorFrame) is serialized as RTVI bot-output, user-transcription, error, etc., and sent to the client.
RTVI message types (Phase 1–2)
- Client → server:
client-ready,send-text(data:content, optionaloptions). - Server → client:
bot-ready(version, about),bot-output(text),user-transcription(text, final),error(error, fatal),bot-started-speaking,bot-stopped-speaking.
For full compatibility with RTVI clients, see the upstream RTVI protocol. Deprecated actions/config are not implemented in the initial phases.