assistant-api reads them through the custom-stt transformer and maps audio packets and provider responses with DSL rules.
Provider identifier: custom-stt
Where it is configured
1
Create the provider credential
In the Rapida dashboard, open Integrations > Models, choose Custom STT, and create a credential.
The backend also accepts snake case keys:
api_compatibility and base_url.2
Select Custom STT on the assistant
Open the assistant voice settings and select Custom STT as the speech-to-text provider.
3
Fill the STT arguments
Set the audio format, query parameters, request rules, and response rules. The argument reference below maps to the UI fields and the transformer option keys.
STT arguments
The UI stores these keys with themicrophone. metadata prefix, but the transformer reads the option keys shown below. The current UI exposes the audio and DSL fields; listen.model and listen.language are optional API/import metadata keys that request rules and query parameters can read when present.
Query parameters
Uselisten.query_params when your provider expects configuration in the URL.
Supported variables:
Request rules
Request rules are evaluated for normalized packets produced by Rapida.
Supported outbound frame types are
binary, json, and text.
packet.audio.bytes is raw audio bytes for binary frames. Use packet.audio.base64 when the provider expects audio inside a JSON payload.Binary audio stream
JSON audio payload
HTTP transcription request
Use this shape withapiCompatibility = http_v1 when your provider accepts a JSON POST after each completed speech segment.
For
http_v1, the first matching audio rule must use send.frame = json. WebSocket STT can use binary, json, or text outbound frames.Response rules
Response rules parse provider WebSocket frames or HTTP response bodies into Rapida transcript packets. Supported inbound frame types:
Supported emit keys:
STT DSL design
Custom STT uses a JSON-template DSL with three sections: query parameters, request rules, and response rules. The DSL is intentionally small. It does not run scripts, call functions, concatenate strings, perform regex matching, or read environment variables.STT frame support
Inbound parsing rules:
- WebSocket message type
2is treated asbinary, but STT response rules do not support binary response frames. - Non-binary messages are parsed as JSON when they contain exactly one valid JSON value.
- Non-JSON messages are treated as
text. - For STT, JSON string primitives and non-object JSON values are treated as
text; JSON response rules operate on JSON objects.
STT operators
Every operator object must contain only that operator and its required field.
Unsupported STT operators:
$decodeis not supported for STT.$frame: "binary"and$frame: "json"are not supported for STT emit rules.
Cast behavior
JSON path behavior
$path uses dot-separated paths.
- Keys containing a literal dot are not addressable.
- Request rules can only read from
configandpacket. - Response rules can use
$pathonly with JSON response frames. - A missing path in
when.pathmeans the rule does not match. - A missing path in
emitorsend.bodyis an error.
Query parameter rules
listen.query_params must be a flat JSON object. Each value must resolve to a primitive value: string, number, boolean, or null. Nested objects and arrays are rejected unless the object is a DSL expression.
baseUrl. Existing query parameters in baseUrl are preserved unless the same key is rendered by listen.query_params.
Request rule shape
listen.request_rules is an ordered JSON array. For websocket_v1, every matching rule is sent, so one packet can produce multiple WebSocket messages. For http_v1, the first matching audio rule provides the JSON POST body.
Body validation depends on
send.frame:
STT request scope
The request scope is the data available to$path in request rules.
packet.audio exists only for audio packets.
Response rule shape
listen.response_rules is an ordered JSON array. The first matching rule is evaluated; later rules are skipped for that response.
Match behavior:
STT emit keys
Plain text transcript response
Use this for providers that return transcript chunks as raw text frames.Nested JSON transcript response
Start, audio, and interrupt recipe
Use this pattern when the provider expects a session-start message, binary audio frames, and a flush message on interruption.Runtime behavior
- The URL is built from
baseUrlandlisten.query_params. - Headers are copied from the credential and are not templated.
- Audio is resampled from Rapida’s internal audio format to
listen.audio.encodingandlisten.audio.sample_ratebefore request rules are evaluated. - For
websocket_v1,turn_changeandaudiopackets open the WebSocket connection if needed. - For
http_v1, Rapida buffers audio while the user is speaking and sends one HTTP POST when the STT end packet arrives. interruptrules are sent only by the WebSocket transport when a connection is already active.- If no response rule matches an inbound frame, the frame is ignored.
- If a response emits
error, Rapida emits an STT error packet. - If a response emits non-empty
script, Rapida emits a transcript packet and conversation event.
Current STT limits
- No regex, contains, starts-with, greater-than, or compound match conditions.
- No string interpolation or concatenation.
- No fallback values inside expressions.
- No dynamic headers or dynamic URL path segments.
- No
$decode. - No binary response handling for STT.
- No
$frame: "json"selector in emit rules.
Backend mapping
assistant-api resolves custom-stt in api/assistant-api/internal/transformer/transformer.go, then dispatches by credential compatibility:
Both STT implementations validate:
baseUrlis present in the credential.listen.audio.encodingis not empty.listen.audio.sample_rateis positive.listen.request_rulescontains at least oneaudiopacket rule.listen.response_rulescontains at least one rule.
http_v1 also requires the first matching audio request rule to emit a json frame because the transport sends an HTTP POST body.
Custom TTS
Configure WebSocket text-to-speech.
STT overview
Transformer interface and supported providers.