Event Protocol
AI Chat control events are sent through the TiRTC command channel. All payloads are UTF-8 JSON-RPC 2.0 messages, and the AI Chat command word is:
#define TIRTC_AI_SIGNALING 0x2100Note
This command word 0x2100 belongs to the developer application reserved range (0x2000 ~ 0xffff) and is not an internal SDK reserved command. You may change this value according to your project needs, as long as the device and application server agree on it and it does not conflict with TiRTC internal commands (which are under 0x2000).
Message Types
| Type | Signal | Description |
|---|---|---|
| Request | Has an id field | The sender expects a success or error response, such as start_session. |
| Notification | Has no id field | One-way event, such as caption or interrupt. |
Use a string value for id. JSON-RPC responses from the platform do not include method; match them with the original request by id.
Common request:
{
"jsonrpc": "2.0",
"id": "req-001",
"method": "start_session",
"params": {}
}Common success response:
{
"jsonrpc": "2.0",
"id": "req-001",
"result": {}
}Common error response:
{
"jsonrpc": "2.0",
"id": "req-001",
"error": {
"code": -32602,
"message": "Invalid params"
}
}Event Summary
| method | Direction | Type | Description |
|---|---|---|---|
start_session | Device -> Platform | Request | Starts an AI Chat session after TiRTC is connected. |
caption | Platform -> Device | Notification | Sends ASR or TTS captions. |
round_start | Platform -> Device | Notification | Marks the start of one response audio round. |
round_end | Platform -> Device | Notification | Marks the end of one response audio round. |
interrupt | Device -> Platform | Notification | Interrupts the current platform response. |
submit_speech | Device -> Platform | Notification | Manually submits the current uplink speech. |
update_config | Device -> Platform | Request | Updates runtime session context. Currently only extra_params is supported. |
device_action | Platform -> Device | Request | Requests the device to execute a declared capability. |
end_session | Both | Notification | Ends the current session. |
start_session
Direction: device -> Tange platform
The device must send start_session after the TiRTC connection is ready. The platform creates the session, loads device and role configuration, and returns the session ID and audio formats.
{
"jsonrpc": "2.0",
"id": "start-session-001",
"method": "start_session",
"params": {
"device_id": "DEMO_DEVICE_01",
"role_id": "role_xxx",
"input_audio": {
"codec": "opus",
"sample_rate": 16000,
"channels": 1
},
"output_audio": {
"codec": "opus",
"sample_rate": 16000,
"channels": 1
}
}
}Required fields:
| Field | Required | Description |
|---|---|---|
device_id | Yes | Device ID. |
role_id | Yes | Role ID from role configuration or device-role binding. |
input_audio | No | Uplink audio format. Uses platform defaults (usually pcm) when omitted. We highly recommend passing this explicitly to ensure the server and device have a consistent understanding and avoid compatibility issues. |
output_audio | No | Downlink audio format. Uses platform defaults (usually pcm) when omitted. We highly recommend passing this explicitly to ensure the server and device have a consistent understanding and avoid compatibility issues. |
Both input_audio and output_audio contain:
| Field | Type | Description |
|---|---|---|
codec | string | Audio codec. |
sample_rate | int | Sample rate in Hz. |
channels | int | Number of channels. |
Supported Audio Formats
| codec | Supported sample rates (Hz) | Supported channels |
|---|---|---|
opus | 16000 | 1 |
pcm | 16000, 8000 | 1 |
g711a | 16000, 8000 | 1 |
amr | 8000 (NB), 16000 (WB) | 1 |
Notes:
- The platform ASR / LLM / TTS pipeline runs at 16 kHz mono internally. Uplink audio that does not match the internal format is resampled on the platform side.
- The actual session formats are defined by the
input_audioandoutput_audiofields in thestart_sessionsuccess response. The device must send and decode audio according to those values. - Unsupported codec, sample rate, or channel combinations return a JSON-RPC error with
messageset toInvalid audio format.
Success response:
{
"jsonrpc": "2.0",
"id": "start-session-001",
"result": {
"session_id": "aivoice-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"input_audio": {
"codec": "opus",
"sample_rate": 16000,
"channels": 1
},
"output_audio": {
"codec": "opus",
"sample_rate": 16000,
"channels": 1
}
}
}caption
Direction: Tange platform -> device
caption sends ASR or TTS text.
{
"jsonrpc": "2.0",
"method": "caption",
"params": {
"text": "Hello, how can I help?",
"caption_type": 1,
"is_final": true,
"mode": 0,
"utterance_id": 1001,
"seq_num": 3,
"begin_time_ms": 120,
"end_time_ms": 1680
}
}params fields:
| Field | Always present | Description |
|---|---|---|
text | Yes | Caption text. |
caption_type | Yes | Caption source: 0 for ASR user caption, 1 for TTS reply caption. |
is_final | Yes | Whether this is the final caption for the utterance. |
mode | Yes | Delivery mode: 0 for full text, 1 for incremental text. |
utterance_id | Yes | Utterance ID; captions from the same utterance share the same ID. |
seq_num | Yes | Sequence number for ordering within the same utterance. |
begin_time_ms | No | Caption segment start time in milliseconds; may be absent or 0. |
end_time_ms | No | Caption segment end time in milliseconds; may be absent or 0. |
Use caption_type + utterance_id as the caption group key. When mode=1, append text; when mode=0, replace the current text. Mark the group final when is_final=true.
round_start and round_end
Direction: Tange platform -> device
round_start marks the start of one response audio round:
{
"jsonrpc": "2.0",
"method": "round_start"
}round_end marks the end:
{
"jsonrpc": "2.0",
"method": "round_end"
}Use these events for UI state and playback state, but play audio according to the actual downlink audio stream.
interrupt
Direction: device -> Tange platform
{
"jsonrpc": "2.0",
"method": "interrupt"
}The historical spelling interupt is also accepted by the platform and has the same effect as interrupt. New integrations should use interrupt.
After sending interrupt, the device should immediately stop playing buffered audio from the old response.
submit_speech
Direction: device -> Tange platform
submit_speech manually submits the current uplink speech. Typical scenarios include push-to-talk release, half-duplex talk, UI confirmation, or local device-side VAD deciding that the user has finished an utterance.
{
"jsonrpc": "2.0",
"method": "submit_speech"
}Notes:
- After
submit_speechis sent, the platform treats the currently received uplink speech as submitted and continues the ASR / LLM / TTS flow. submit_speechdoes not interrupt the current platform response. Useinterruptwhen the device needs to stop an in-progress response.- If the device relies only on cloud VAD to detect the end of speech, this event is usually not required.
update_config
Direction: device -> Tange platform
update_config updates small pieces of runtime context during an active session. Currently only extra_params is supported. It is intended for information such as location or business state that may change during the session. It does not update static settings such as welcome text, voice, or system prompt.
Request:
{
"jsonrpc": "2.0",
"id": "update-config-001",
"method": "update_config",
"params": {
"extra_params": {
"latitude": 39.9800718,
"longitude": 116.309314
}
}
}Success response:
{
"jsonrpc": "2.0",
"id": "update-config-001",
"result": {
"success": true,
"message": "更新配置成功"
}
}Error response:
{
"jsonrpc": "2.0",
"id": "update-config-001",
"error": {
"code": -32602,
"message": "update_config only supports extra_params, got \"voice\""
}
}Notes:
- The response is a JSON-RPC response and does not include
method: "config_updated". - Match the response to the
update_configrequest byid. - Any field other than
extra_paramsis rejected.
device_action
Direction: Tange platform -> device
When device capabilities are declared in the role configuration, the platform may send device_action to request the device to perform an action. This message is a JSON-RPC Request. The device must keep the id and return a response with the same id.
Request from platform:
{
"jsonrpc": "2.0",
"id": "device-action-001",
"method": "device_action",
"params": {
"action": "set_light",
"data": {
"power": "on"
}
}
}Success response from device:
{
"jsonrpc": "2.0",
"id": "device-action-001",
"result": {
"ok": true,
"data": {
"power": "on"
}
}
}Error response from device:
{
"jsonrpc": "2.0",
"id": "device-action-001",
"error": {
"code": -32000,
"message": "device is busy"
}
}end_session
Direction: both
end_session ends the current AI Chat session. It may be sent by the device or by the platform when the session should close.
Device to platform:
{
"jsonrpc": "2.0",
"method": "end_session"
}Platform to device:
{
"jsonrpc": "2.0",
"method": "end_session"
}After sending or receiving end_session, stop capture, stop playback, and release local session state. The cleanup flow should be idempotent.
Device Receive Example
#include <stdint.h>
#include <string.h>
#include "tiRTC.h"
#define TIRTC_AI_SIGNALING 0x2100
static void on_command(tirtc_conn_t hconn, uint32_t cmdw,
const void *data, uint32_t len)
{
(void)hconn;
if (cmdw != TIRTC_AI_SIGNALING || data == NULL || len == 0) {
return;
}
/* data is a UTF-8 JSON-RPC string.
* In production code, parse method / params with a JSON library,
* then dispatch to caption, round_start, round_end, interrupt,
* submit_speech, device_action, end_session, and other handlers. */
}Self-Check List
- Use the
0x2100command word. - Ensure every payload is valid UTF-8 JSON.
- Send
start_sessionwith anid, and handle both success and error responses. - Pass a valid
role_id. - Handle incremental and full
captionmodes. - Handle
round_start/round_endstate changes. - Implement immediate local playback stop for
interrupt. - If manual speech submission is needed, implement
submit_speech. - If runtime config updates are needed, match the
update_configJSON-RPC response byid. - If device capability calls are needed, handle
device_actionrequests and responses byid. - Make
end_sessioncleanup idempotent.