主题
B. WebSocket 协议参考
JoyInside WebSocket 语音通道的完整速查:建连、对话模式、轮次时序、消息结构、音频参数、错误码、全场景事件对照。
B.1 通用消息结构
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| mid | string | 是 | 消息唯一标识(UUID) |
| contentType | string | 是 | EVENT / AUDIO / TEXT / PONG / ACTIVITY |
| content | object | 是 | 事件数据载体 |
| code | number | 下行 | 200 成功 |
| msg | string | 下行 | 状态描述 |
| requestId | string | 下行 | 请求唯一标识 |
| roundId | string | 下行 | 轮次标识(排查主键,见 4.6 roundId) |
| t | long | 下行 | 服务端处理时间戳(毫秒) |
B.2 错误码速查
错误码完整定义(getToken 1001-1006 / WS 建连 40100-40104 / HTTP 400/408 / 其他)见 10.7 错误码速查表,排查时以该表为权威源。
⚠ WS 建连 40100-40104 不返回设备端,设备只看连接被关闭。排查结合服务端日志与 roundId,详见 4.1 鉴权 与 10.1 建联失败。
B.3 事件协议明细(按功能维度聚合)
本节展开每个事件的完整 JSON 协议结构 + 字段说明,按功能维度聚合上下行事件。
B.3.1 建连后(CFG_BOT_EVENT)
建连成功后,服务端主动下发默认语音对话配置(音色、TTS 音频格式、设备型号)。无业务上行事件。
| 方向 | 事件 |
|---|---|
| 下行 | CFG_BOT_EVENT |
默认配置不一定满足业务需求,收到后需发
CLIENT_VOICE_CHAT_UPDATE覆盖(见 B.3.2)。
下行:默认语音对话配置(CFG_BOT_EVENT)
建联成功后服务端下发默认配置。
外层结构:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| code | int | 下行必选 | 响应状态码,200 表示成功 |
| msg | string | 下行必选 | 状态描述信息 |
| requestId | string | 下行必选 | 请求唯一标识符 |
| mid | string | 是 | 消息唯一标识 |
| t | long | 下行必选 | 服务端处理时间戳(毫秒) |
| contentType | string | 是 | 固定 EVENT |
| content | object | 是 | 识别结果数据 |
| content.eventType | string | 是 | 固定 CFG_BOT_EVENT |
| content.eventData | object | 是 | 默认语音对话配置(见下表) |
| content.roundId | string | 下行必选 | 消息轮次 index |
eventData 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| timbre | object | 是 | 输出音色配置 |
| timbre.voiceName | string | 是 | 音色名称 |
| timbre.voiceSpeed | float | 是 | 语速 |
| tts | object | 是 | 输出音频配置 |
| tts.aue | string | 是 | 音频编码(pcm/opus/mp3) |
| tts.bit | int | 是 | 位深 |
| tts.channels | int | 是 | 通道数 |
| tts.sr | string | 是 | 采样率 |
| deviceModel | string | 否 | 设备型号 |
| deviceId | string | 否 | 设备 ID |
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Event success",
"requestId": "a4595acb-de6c-4ac9-92b2-8fa59a7f91f7",
"mid": null,
"contentType": "EVENT",
"content": {
"roundId": "",
"eventType": "CFG_BOT_EVENT",
"eventData": {
"timbre": {
"voiceName": "小犀",
"voiceSpeed": 1.0
},
"tts": {
"aue": "pcm",
"bit": 16,
"channels": 1,
"sr": "16000"
},
"deviceModel": "UNKNOWN",
"deviceId": "UNKNOWN"
}
},
"t": 1749117478297
}B.3.2 配置更新(CLIENT_VOICE_CHAT_UPDATE / SERVER_VOICE_CHAT_UPDATED)
建连后只发一次,配置音频格式/采样率/二进制传输/音色。收到 SERVER_VOICE_CHAT_UPDATED 才算成功。
| 方向 | 事件 |
|---|---|
| 上行 | CLIENT_VOICE_CHAT_UPDATE |
| 下行 | SERVER_VOICE_CHAT_UPDATED |
⚠ 重复发送会打断对话;对话中切换角色也需重发此事件。
上行:更新语音对话配置(CLIENT_VOICE_CHAT_UPDATE)
外层结构:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| mid | string | 是 | 消息唯一标识 |
| contentType | string | 是 | 固定 EVENT |
| content | object | 是 | 事件数据载体 |
| content.eventType | string | 是 | 固定 CLIENT_VOICE_CHAT_UPDATE |
| content.eventData | object | 是 | 语音对话配置项(见下表) |
语音对话配置项(eventData.audio / eventData.chat):
| 字段 | 类型 | 必选 | 取值 / 默认 | 说明 |
|---|---|---|---|---|
| audio | object | 否 | — | 音频配置 |
| audio.binary | bool | 否 | true/false | true=二进制传输(上下行),false=base64 文本(上下行) |
| audio.vad | bool | 否 | 默认 false | 是否开启端侧 VAD,true 开启 / false 关闭 |
| audio.input | object | 否 | — | 输入音频配置 |
| audio.input.codec | string | 否 | pcm/opus | 上行音频编码 |
| audio.input.sampleRate | string | 否 | 16000/24000/32000 | 上行采样率 |
| audio.input.frameSize | string | 否 | 字节数 | 输入 opus 帧的字节数,仅多定长 opus 拼接时传 |
| audio.input.binary | bool | 否 | true/false | 上行单独二进制开关,设此字段时 audio.binary 不设 |
| audio.output | object | 否 | — | 输出音频配置 |
| audio.output.codec | string | 否 | pcm/opus/mp3 | 下行 TTS 编码 |
| audio.output.sampleRate | string | 否 | 16000/24000/32000 | 下行采样率 |
| audio.output.binary | bool | 否 | true/false | 下行单独二进制开关 |
| audio.output.enableOpusCbr | bool | 否 | 默认 false | 输出 opus 是否启用 CBR |
| audio.output.frameSizeMs | string | 否 | pcm:60-120 / opus:10/20/40/60,默认 60 | 下行 TTS 帧时长(ms),mp3 不支持切分 |
| audio.timbre | object | 否 | — | 输出音色配置 |
| audio.timbre.voiceSpeed | float | 否 | 0.8-1.2 | 输出音频语速 |
| audio.timbre.voiceVolume | float | 否 | 0.5-10 | 输出音频音量 |
| chat | object | 否 | — | 对话配置 |
| chat.roleCode | string | 否 | 角色编号 | 对话角色编号 |
⚠ binary 覆盖关系:
audio.binary是上下行总开关。若上下行二进制策略不同,单独设audio.input.binary/audio.output.binary,此时不设audio.binary。
完整 JSON 示例(点击展开)
json
{
"mid": "24279824-8def-48c6-8d1c-ea8ec3aa50ac",
"contentType": "EVENT",
"content": {
"eventType": "CLIENT_VOICE_CHAT_UPDATE",
"eventData": {
"audio": {
"binary": true,
"vad": true,
"input": {
"codec": "pcm",
"sampleRate": "16000"
},
"output": {
"codec": "opus",
"sampleRate": "16000",
"frameSizeMs": "40",
"enableOpusCbr": false
},
"timbre": {
"voiceSpeed": 1.0,
"voiceVolume": 5.0
}
},
"chat": {
"roleCode": "角色编号"
}
}
}
}下行:更新配置成功响应(SERVER_VOICE_CHAT_UPDATED)
外层结构:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| code | int | 下行必选 | 响应状态码,200 表示成功 |
| msg | string | 下行必选 | 状态描述信息 |
| requestId | string | 下行必选 | 请求唯一标识符 |
| mid | string | 是 | 消息唯一标识 |
| t | long | 下行必选 | 服务端处理时间戳(毫秒) |
| contentType | string | 是 | 固定 EVENT |
| content | object | 是 | 识别结果数据 |
| content.eventType | string | 是 | 固定 SERVER_VOICE_CHAT_UPDATED |
| content.eventData | object | 是 | 语音对话配置项(与上行结构相同) |
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Event success",
"requestId": "a4595acb-de6c-4ac9-92b2-8fa59a7f91f7",
"mid": null,
"contentType": "EVENT",
"content": {
"eventType": "SERVER_VOICE_CHAT_UPDATED",
"eventData": {
"audio": {
"binary": true,
"input": { "codec": "pcm", "sampleRate": "16000" },
"output": { "codec": "opus", "sampleRate": "16000", "frameSizeMs": "40" }
}
}
},
"t": 1752724083510
}B.3.3 语音输入与识别
上行:流式上传音频(AUDIO)
流式向服务端提交音频片段。
外层结构:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| mid | string | 是 | 消息唯一标识 |
| contentType | string | 是 | 固定 AUDIO |
| content | object | 是 | 音频数据载体(见下表) |
content 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| audioBase64 | string | 是 | 音频数据 Base64 编码(二进制传输时改用 ws.send(bytes)) |
| index | string | 是 | 音频数据序号,由 1 递增;最后一帧可为取反值(~index) |
| mid | string | 否 | 音频轮次 ID(建议 UUID),开启端侧 VAD 时建议必传 |
切包规则:PCM 单包 ≤300ms,Opus 单包 ≤480 字节,间隔=音频时长。详见 4.5 音频格式与分片。
完整 JSON 示例(点击展开)
json
{
"mid": "f70e8955-8b39-4ae8-bba1-2bea4aa6c50b",
"contentType": "AUDIO",
"content": {
"audioBase64": "PwAVAOv/qP9i/yP/Df8O/wP/Cv8X/wr/8v7X/....",
"index": 1,
"mid": "aceb6a01-fa2e-4ada-a8f5-9e95c3cbb4d4"
}
}上行:结束音频上传(CLIENT_AUDIO_FINISH)
手动模式下通知服务端音频上传结束。
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| mid | string | 是 | 消息唯一标识 |
| contentType | string | 是 | 固定 EVENT |
| content | object | 是 | 事件数据载体 |
| content.eventType | string | 是 | 固定 CLIENT_AUDIO_FINISH |
完整 JSON 示例(点击展开)
json
{
"mid": "24279824-8def-48c6-8d1c-ea8ec3aa50ac",
"contentType": "EVENT",
"content": {
"eventType": "CLIENT_AUDIO_FINISH"
}
}下行:音频识别内容(ASR)
流式语音识别结果。
外层结构:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| code | int | 下行必选 | 响应状态码,200 表示成功 |
| msg | string | 下行必选 | 状态描述信息 |
| requestId | string | 下行必选 | 请求唯一标识符 |
| mid | string | 是 | 消息唯一标识 |
| t | long | 下行必选 | 服务端处理时间戳(毫秒) |
| contentType | string | 是 | 固定 ASR |
| content | object | 是 | 识别结果数据 |
content 字段:
| 字段 | 类型 | 必选 | 取值 | 说明 |
|---|---|---|---|---|
| text | string | 是 | — | 识别出的文本内容 |
| textType | string | 是 | IS_FINAL | 结果类型,IS_FINAL 为最终识别结果 |
| lang | string | 否 | 普通话/英文 | 语种识别 |
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "ASR success",
"requestId": "a4595acb-de6c-4ac9-92b2-8fa59a7f91f7",
"mid": "c673b518375a4c23aeab8cb8458994d6",
"contentType": "ASR",
"content": {
"text": "语音测试,给我个结果",
"textType": "IS_FINAL",
"lang": "普通话"
},
"t": 1745507675867
}B.3.4 文本输入
上行:发送文本对话内容(TEXT)
发文本与智能体对话,提交后流式回复文本 + 音频。
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| mid | string | 是 | 消息唯一标识 |
| contentType | string | 是 | 固定 TEXT |
| content | object | 是 | 文本数据载体 |
| content.input | string | 是 | 文本字符串 |
完整 JSON 示例(点击展开)
json
{
"mid": "f70e8955-8b39-4ae8-bba1-2bea4aa6c50b",
"contentType": "TEXT",
"content": {
"input": "讲个故事吧"
}
}B.3.5 智能体对话与回复
下行:智能体对话开始(CALL_AGENT_START_EVENT)
根据识别结果开启对话。
外层结构:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| code | int | 下行必选 | 响应状态码,200 表示成功 |
| msg | string | 下行必选 | 状态描述信息 |
| requestId | string | 下行必选 | 请求唯一标识符 |
| mid | string | 是 | 消息唯一标识 |
| t | long | 下行必选 | 服务端处理时间戳(毫秒) |
| contentType | string | 是 | 固定 EVENT |
| content | object | 是 | 事件数据载体 |
content 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| roundId | string | 是 | 消息轮次index |
| eventType | string | 是 | 固定为 CALL_AGENT_START_EVENT |
| eventData | object | 是 | 对话开始数据 |
| eventData.input | string | 是 | 智能体对话输入内容 |
| eventData.startTime | long | 是 | 智能体对话开始时间(毫秒) |
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Event success",
"requestId": "08ddd338-fd5b-4572-b03a-43974dc145db",
"mid": "c673b518375a4c23aeab8cb8458994d6",
"contentType": "EVENT",
"content": {
"roundId": "b1c9fc68-01c4-48b4-ba79-a8440dc9a9fa_222726_1",
"eventType": "CALL_AGENT_START_EVENT",
"eventData": {
"input": "语音测试,给我个结果",
"startTime": 1745507675867
},
"t": 1745507675867
}
}下行:智能体回复文本(AGENT)
智能体回复文本,流式下发,可当字幕展示。
外层结构:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| code | int | 下行必选 | 响应状态码,200 表示成功 |
| msg | string | 下行必选 | 状态描述信息 |
| requestId | string | 下行必选 | 请求唯一标识符 |
| mid | string | 是 | 消息唯一标识 |
| t | long | 下行必选 | 服务端处理时间戳(毫秒) |
| contentType | string | 是 | 固定 AGENT |
| content | object | 是 | 智能体生成的文本回复 |
content 字段:
| 字段 | 类型 | 必选 | 取值 | 说明 |
|---|---|---|---|---|
| roundId | string | 是 | — | 消息轮次index |
| role | string | 是 | assistant | 角色标识 |
| content | string | 是 | — | 流式文本片段 |
| reasoningContent | string | 是 | — | 智能体思考内容 |
| finishReason | string | 是 | stop/error/audit | 结束原因:stop 正常结束 / error 错误 / audit 安全审核过滤 |
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "LLM success",
"requestId": "08ddd338-fd5b-4572-b03a-43974dc145db",
"mid": "c673b518375a4c23aeab8cb8458994d6",
"contentType": "AGENT",
"content": {
"roundId": "a4595acb-de6c-4ac9-92b2-8fa59a7f91f7_2",
"role": "assistant",
"content": "嘿!你好呀,",
"reasoningContent": "",
"finishReason": ""
},
"t": 1749117487494
}下行:智能体主动回复文本(ACTIVITY)
静默推送触发的主动对话文本(一定时间无对话交互时触发)。字段与 AGENT 相同,区别在 contentType 为 ACTIVITY。
外层结构:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| code | int | 下行必选 | 响应状态码,200 表示成功 |
| msg | string | 下行必选 | 状态描述信息 |
| requestId | string | 下行必选 | 请求唯一标识符 |
| mid | string | 是 | 消息唯一标识 |
| t | long | 下行必选 | 服务端处理时间戳(毫秒) |
| contentType | string | 是 | 固定 ACTIVITY |
| content | object | 是 | 智能体主动生成的文本回复 |
content 字段:
| 字段 | 类型 | 必选 | 取值 | 说明 |
|---|---|---|---|---|
| roundId | string | 是 | — | 消息轮次index |
| role | string | 是 | assistant | 角色标识 |
| content | string | 是 | — | 流式文本片段 |
| reasoningContent | string | 是 | — | 智能体思考内容 |
| finishReason | string | 是 | stop/error/content_filter | 结束原因 |
⚠ AGENT 的审核命中是
audit,ACTIVITY 的审核命中是content_filter,两者不同。
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "LLM success",
"contentType": "ACTIVITY",
"requestId": "08ddd338-fd5b-4572-b03a-43974dc145db",
"mid": "c673b518375a4c23aeab8cb8458994d6",
"content": {
"roundId": "a4595acb-de6c-4ac9-92b2-8fa59a7f91f7_2",
"role": "assistant",
"content": "嘿!你好呀,",
"reasoningContent": "",
"finishReason": ""
},
"t": 1749117487494
}下行:智能体对话忽略(EMPTY_CONTENT)
未识别到有效音频,不开启对话(拒识四层防护见 拒识四层防护)。
content 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| roundId | string | 是 | 消息轮次index |
| eventType | string | 是 | 固定为 EMPTY_CONTENT |
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Event success",
"requestId": "08ddd338-fd5b-4572-b03a-43974dc145db",
"mid": "c673b518375a4c23aeab8cb8458994d6",
"contentType": "EVENT",
"content": {
"roundId": "a4595acb-de6c-4ac9-92b2-8fa59a7f91f7_1",
"eventType": "EMPTY_CONTENT",
"eventData": {
"startTime": 1749117482960
}
},
"t": 1749117482960
}下行:语音当轮对话完成(COMPLETE)
当轮对话结束。
content 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| roundId | string | 是 | 消息轮次index |
| eventType | long | 是 | 固定为 COMPLETE |
| eventData | object | 是 | 数据项 |
| eventData.time | long | 是 | 完成时间戳(毫秒) |
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Event success",
"requestId": "08ddd338-fd5b-4572-b03a-43974dc145db",
"mid": "c673b518375a4c23aeab8cb8458994d6",
"contentType": "EVENT",
"content": {
"roundId": "a4595acb-de6c-4ac9-92b2-8fa59a7f91f7_2",
"eventType": "COMPLETE",
"eventData": {
"time": 1749117488694
}
},
"t": 1749117488694
}B.3.6 TTS 音频合成
上行:请求音频合成(CLIENT_INPUT_TEXT_TO_SPEECH)
主动提交文字合成语音,不触发智能体,只流式生成 TTS 音频片段。提交时若智能体正在输出语音会被中断。
外层结构:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| mid | string | 是 | 消息唯一标识 |
| contentType | string | 是 | 固定 EVENT |
| content | object | 是 | 事件数据载体 |
| content.eventType | string | 是 | 固定 CLIENT_INPUT_TEXT_TO_SPEECH |
| content.eventData | object | 是 | 请求数据项(见下表) |
eventData 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| text | string | 是 | 文本信息(会切分且分段生成音频),长度限制 (0, 1000) 字节 |
完整 JSON 示例(点击展开)
json
{
"mid": "f70e8955-8b39-4ae8-bba1-2bea4aa6c50b",
"contentType": "EVENT",
"content": {
"eventType": "CLIENT_INPUT_TEXT_TO_SPEECH",
"eventData": {
"text": "需要合成的文本"
}
}
}下行:音频字幕(TTS_SENTENCE_START)
音频对应的字幕句子,先于 TTS 音频下发。后续的 TTS 音频均属于当前字幕。
content 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| roundId | string | 是 | 消息轮次index |
| eventType | long | 是 | 固定为 TTS_SENTENCE_START |
| eventData | object | 是 | 字幕数据项 |
| eventData.text | string | 是 | 对应文本字幕 |
| eventData.time | long | 是 | 时间戳(毫秒) |
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Event success",
"requestId": "08ddd338-fd5b-4572-b03a-43974dc145db",
"mid": "c673b518375a4c23aeab8cb8458994d6",
"contentType": "EVENT",
"content": {
"roundId": "140adc55-8d74-4eae-80d1-1425c36c8541_1",
"eventType": "TTS_SENTENCE_START",
"eventData": {
"time": 1748525295575,
"text": "音频对应的文本内容"
}
},
"t": 1748525295575
}下行:智能体回复音频(TTS)
发送语音合成后的流式音频片段。
外层结构:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| code | int | 下行必选 | 响应状态码,200 表示成功 |
| msg | string | 下行必选 | 状态描述信息 |
| requestId | string | 下行必选 | 请求唯一标识符 |
| mid | string | 是 | 消息唯一标识 |
| t | long | 下行必选 | 服务端处理时间戳(毫秒) |
| contentType | string | 是 | 固定 TTS |
| content | object | 是 | 识别结果数据 |
content 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| roundId | string | 是 | 消息轮次index |
| audioBase64 | string | 是 | 音频数据 Base64(二进制传输时改用 binary frame) |
| audioAue | string | 是 | 音频编码 |
| audioDuration | int | 是 | 音频时长(毫秒),⚠ 参考不准确 |
| finish | bool | 是 | 是否本轮最后一片(true/false) |
⚠
audioDuration为参考值不准确,不要用于精确时长计算。
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "TTS success",
"requestId": "08ddd338-fd5b-4572-b03a-43974dc145db",
"mid": "c673b518375a4c23aeab8cb8458994d6",
"contentType": "TTS",
"content": {
"roundId": "a4595acb-de6c-4ac9-92b2-8fa59a7f91f7_2",
"audioBase64": "UklGRiQAAABXQVZFZm10IBAAAAAB...",
"audioAue": "mp3",
"audioDuration": 2000,
"finish": false
},
"t": 1749117488653
}下行:语音音频回复完成(TTS_COMPLETE)
TTS 音频全部下发完成。
content 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| roundId | string | 是 | 消息轮次index |
| eventType | long | 是 | 固定为 TTS_COMPLETE |
| eventData | object | 是 | 数据项 |
| eventData.time | long | 是 | 完成时间戳(毫秒) |
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Event success",
"requestId": "08ddd338-fd5b-4572-b03a-43974dc145db",
"mid": "c673b518375a4c23aeab8cb8458994d6",
"contentType": "EVENT",
"content": {
"roundId": "551cc928-a9bb-464e-9ef0-aa7366b170a9_211532_1",
"eventType": "TTS_COMPLETE",
"eventData": {
"time": 1752758135335
}
},
"t": 1752758135335
}B.3.7 打断
上行:打断智能体(CLIENT_INTERRUPT)
手动模式下打断 TTS 播放必须发送。
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| mid | string | 是 | 消息唯一标识 |
| contentType | string | 是 | 固定 EVENT |
| content | object | 是 | 事件数据载体 |
| content.eventType | string | 是 | 固定 CLIENT_INTERRUPT |
⚠ 手动模式下,新一轮对话开始时若 TTS 还在输出,必须先发此事件打断,否则轮次判定异常。
完整 JSON 示例(点击展开)
json
{
"mid": "24279824-8def-48c6-8d1c-ea8ec3aa50ac",
"contentType": "EVENT",
"content": {
"eventType": "CLIENT_INTERRUPT"
}
}下行:智能体打断事件(CALL_AGENT_INTERRUPTED)
自由对话模式下,客户端收到此事件后需打断正在播放的 TTS,准备播放新音频流。
content 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| roundId | string | 是 | 消息轮次index |
| eventType | long | 是 | 固定为 CALL_AGENT_INTERRUPTED |
| eventData | object | 是 | 数据项 |
| eventData.startTime | long | 是 | 事件发生时间(毫秒) |
⚠ 端侧处理:停止 TTS 播放,清空播放队列,等待新 TTS。排查见 10.3 打断失效。
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Event success",
"requestId": "08ddd338-fd5b-4572-b03a-43974dc145db",
"mid": "c673b518375a4c23aeab8cb8458994d6",
"contentType": "EVENT",
"content": {
"roundId": "a4595acb-de6c-4ac9-92b2-8fa59a7f91f7_2",
"eventType": "CALL_AGENT_INTERRUPTED",
"eventData": {
"startTime": 1763968984181
}
},
"t": 1763968984181
}B.3.8 指令与情绪事件
下行:指令事件(CALL_SKILL_EVENT)
设备控制类指令(音量/电量/IOT 控制),属自定义事件子类。设备端收到后无需语义判断,直接调用对应功能模块。闲聊场景下,情绪事件也复用本事件下发,供端侧驱动表情/动作。
按用途分两类:
- 指令类:IOT 控制、设备动作(如前进/开灯),见 6.1 IOT 控制。
- 情绪类:闲聊场景下下发情绪(7 种基础情绪 + 23 种自定义情绪),驱动端侧表情。
外层结构(指令类 / 情绪类通用):
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| code | int | 下行必选 | 响应状态码,200 表示成功 |
| msg | string | 下行必选 | 状态描述信息 |
| requestId | string | 下行必选 | 请求唯一标识符 |
| mid | string | 是 | 消息唯一标识 |
| t | long | 下行必选 | 服务端处理时间戳(毫秒) |
| contentType | string | 是 | 固定 EVENT |
| content | object | 是 | 事件数据载体(见下两类明细) |
指令类 content 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| roundId | string | 是 | 消息轮次 index |
| eventType | string | 是 | 固定 CALL_SKILL_EVENT |
| eventData | object | 是 | 数据项 |
| eventData.data | object | 是 | 指令数据 |
| eventData.data.intentCode | string | 是 | 指令编码 |
| eventData.data.intentClassify | string | 是 | 意图分类(如 前进 / LIGHT_UP) |
| eventData.data.args | object | 否 | 指令参数(slotKey: slotValue) |
| eventData.data.instructions | array | 是 | 指令列表(可多条) |
| eventData.data.instructions[].action | string | 是 | 指令动作编码 |
| eventData.data.instructions[].desc | string | 是 | 指令描述 |
| eventData.data.instructions[].args | object | 是 | 指令参数(slotKey: slotValue) |
指令类完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Event success",
"requestId": "3871de5b-7e83-40ec-ba43-0e4f51f88b14",
"mid": "3871de5b-7e83-40ec-ba43-0e4f51f88b14_181908_2",
"contentType": "EVENT",
"content": {
"roundId": "3871de5b-7e83-40ec-ba43-0e4f51f88b14_181908_2",
"eventType": "CALL_SKILL_EVENT",
"eventData": {
"msg": "端侧事件下发",
"data": {
"instructions": [
{
"action": "ACTION_SLIDE_FORWARD",
"args": {},
"desc": "前进"
}
],
"args": {},
"intentClassify": "前进",
"intentCode": "ACTION_SLIDE_FORWARD"
},
"type": "CALL_SKILL_EVENT"
}
},
"t": 1786357156662
}情绪类 content 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| roundId | string | 是 | 消息轮次 index |
| eventType | string | 是 | 固定 CALL_SKILL_EVENT |
| eventData | object | 是 | 数据项 |
| eventData.msg | string | 是 | 描述(如 闲聊表情情绪事件) |
| eventData.data | object | 是 | 情绪数据 |
| eventData.data.intentClassify | string | 是 | 意图分类,情绪类固定 闲聊 |
| eventData.data.args | object | 是 | 情绪参数 |
| eventData.data.args.EMOTION | string | 是 | 情绪编码,取下表 23 种自定义情绪之一 |
| eventData.data.args.TTS_EMOTION | string | 否 | TTS 音色情绪描述(如 高兴) |
23 种自定义情绪 EMOTION 取值表:
| 情绪 | EMOTION | 情绪 | EMOTION |
|---|---|---|---|
| 愤怒 | angry_1 | 担忧 | anxious_1 |
| 谴责 | blamed_1 | 疑惑 | confused_1 |
| 撒娇 | coquetry_1 | 失望 | disappoint_1 |
| 鄙视 | disdainful_1 | 兴奋 | exciting_1 |
| 期待 | expect_1 | 恐惧 | fear_1 |
| 开心 | happy_1 | 厌恶 | hate_1 |
| 犹豫 | hesitate_1 | 好奇 | inquisitive_1 |
| 平静 | peace_1 | 伤心 | sad_1 |
| 震惊 | shock_1 | 害羞 | shy_1 |
| 厌倦 | sick_1 | 悲伤 | sorrowful_1 |
| 委屈 | wronged_1 | 摇头 | disagree_1 |
| 点头 | nod_1 |
情绪类完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Event success",
"requestId": "3871de5b-7e83-40ec-ba43-0e4f51f88b14",
"mid": "3871de5b-7e83-40ec-ba43-0e4f51f88b14_181908_21",
"contentType": "EVENT",
"content": {
"roundId": "3871de5b-7e83-40ec-ba43-0e4f51f88b14_181908_21",
"eventType": "CALL_SKILL_EVENT",
"eventData": {
"msg": "闲聊表情情绪事件",
"data": {
"args": {
"EMOTION": "happy_1",
"TTS_EMOTION": "高兴"
},
"intentClassify": "闲聊"
},
"type": "CALL_SKILL_EVENT"
}
},
"t": 1786360424484
}B.3.9 主动触发与上下文更新
上行:主动触发对话(VOICE_CHAT_TRIGGER)
触发智能体执行指令。
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| mid | string | 是 | 消息唯一标识 |
| contentType | string | 是 | 固定 ACTIVITY |
| content | object | 是 | 事件数据载体 |
| content.activityType | string | 是 | 固定 VOICE_CHAT_TRIGGER |
| content.kvData | object | 否 | 自定义事件消息体 |
完整 JSON 示例(点击展开)
json
{
"mid": "f70e8955-8b39-4ae8-bba1-2bea4aa6c50b",
"contentType": "ACTIVITY",
"content": {
"activityType": "VOICE_CHAT_TRIGGER",
"kvData": {
"自定义事件消息体": ""
}
}
}上行:主动更新对话上下文(CLIENT_UPDATE_CHAT_CONTEXT)
更新短期记忆,需向 JoyInside 运营团队申请权限。服务端收到后下发 CLIENT_CHAT_CONTEXT_RECEIVED 确认。
| 字段 | 类型 | 必选 | 取值 | 说明 |
|---|---|---|---|---|
| mid | string | 是 | — | 消息唯一标识 |
| contentType | string | 是 | ACTIVITY | 固定值 |
| content | object | 是 | — | 事件数据载体 |
| content.activityType | string | 是 | CLIENT_UPDATE_CHAT_CONTEXT | 固定值 |
| content.effectiveTimeMinutes | int | 是 | 1~1440 | 记忆时长(分钟) |
| content.kvData | object | 是 | — | 自定义扩展信息,提示词用 ${extInfo.字段} 取用 |
完整 JSON 示例(点击展开)
json
{
"mid": "1",
"contentType": "ACTIVITY",
"content": {
"activityType": "CLIENT_UPDATE_CHAT_CONTEXT",
"effectiveTimeMinutes": 5,
"kvData": {
"自定义字段名": "自定义值"
}
}
}上行:上报经纬度更新城市地址(CLIENT_UPDATE_COORDINATES_CONTEXT)
⚠ 使用此功能需向 JoyInside 运营团队申请权限。
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| mid | string | 是 | 消息唯一标识 |
| contentType | string | 是 | 固定 ACTIVITY |
| content | object | 是 | 事件数据载体 |
| content.activityType | string | 是 | 固定 CLIENT_UPDATE_COORDINATES_CONTEXT |
| content.coordinates | object | 是 | 坐标系数据 |
| content.coordinates.lat | string | 是 | 纬度 |
| content.coordinates.lng | string | 是 | 经度 |
完整 JSON 示例(点击展开)
json
{
"mid": "1",
"contentType": "ACTIVITY",
"content": {
"activityType": "CLIENT_UPDATE_COORDINATES_CONTEXT",
"coordinates": {
"lat": "39.9042",
"lng": "116.4074"
}
}
}下行:上下文更新成功(CLIENT_CHAT_CONTEXT_RECEIVED)
CLIENT_UPDATE_CHAT_CONTEXT / CLIENT_UPDATE_COORDINATES_CONTEXT 成功响应。
content 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| roundId | string | 是 | 消息轮次index |
| activityType | string | 是 | 固定为 CLIENT_CHAT_CONTEXT_RECEIVED |
| activityData | object | 是 | {} |
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Activity success",
"requestId": "08ddd338-fd5b-4572-b03a-43974dc145db",
"mid": "c673b518375a4c23aeab8cb8458994d6",
"contentType": "EVENT",
"content": {
"roundId": "1_3",
"activityType": "CLIENT_CHAT_CONTEXT_RECEIVED",
"activityData": {}
},
"t": 1775802187178
}B.3.10 心跳保活
上行:心跳(PING)
维持长连接,建议 30 秒间隔,服务端响应 PONG。
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| mid | string | 是 | 消息唯一标识 |
| contentType | string | 是 | 固定 PING |
有声书场景心跳间隔不同,见 6.2 有声书。
完整 JSON 示例(点击展开)
json
{
"mid": "f70e8955-8b39-4ae8-bba1-2bea4aa6c50b",
"contentType": "PING"
}下行:心跳响应(PONG)
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| code | int | 下行必选 | 响应状态码,200 表示成功 |
| msg | string | 下行必选 | 状态描述信息 |
| requestId | string | 下行必选 | 请求唯一标识符 |
| mid | string | 是 | 消息唯一标识 |
| t | long | 下行必选 | 服务端处理时间戳(毫秒) |
| contentType | string | 是 | 固定 PONG |
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Event success",
"requestId": "a4595acb-de6c-4ac9-92b2-8fa59a7f91f7",
"mid": "a4595acb-de6c-4ac9-92b2-8fa59a7f91f7_2",
"contentType": "PONG",
"t": 1749117488694
}B.3.11 安全审核与互踢
下行:审核命中(USER_AUDIT_FAIL)
输入音频命中审核,同时 AGENT 事件 finishReason=audit。
content 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| roundId | string | 是 | 消息轮次index |
| eventType | string | 是 | 固定为 USER_AUDIT_FAIL |
| eventData | object | 是 | {} |
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Event success",
"requestId": "08ddd338-fd5b-4572-b03a-43974dc145db",
"mid": "c673b518375a4c23aeab8cb8458994d6",
"contentType": "EVENT",
"content": {
"roundId": "",
"eventType": "USER_AUDIT_FAIL",
"eventData": { }
}
}下行:互踢(REPEAT_CLIENT_SESSION)
同 botId 双连接,后建踢先建,先建收到此事件被关闭。
根本原因与排查见 双连接互踢。
content 字段:
| 字段 | 类型 | 必选 | 说明 |
|---|---|---|---|
| eventType | long | 是 | 固定为 REPEAT_CLIENT_SESSION |
| eventData | object | 是 | {} |
完整 JSON 示例(点击展开)
json
{
"code": 200,
"msg": "Event success",
"requestId": "08ddd338-fd5b-4572-b03a-43974dc145db",
"mid": "c673b518375a4c23aeab8cb8458994d6",
"contentType": "EVENT",
"content": {
"eventType": "REPEAT_CLIENT_SESSION",
"eventData": { }
}
}B.4 上下行消息一览表
上行事件(设备端 → 云端)
| 事件名 | contentType | 触发时机 | 协议明细 |
|---|---|---|---|
CLIENT_VOICE_CHAT_UPDATE | EVENT | 建连后发一次,配置音频/音色/角色 | D.3.1 |
AUDIO | AUDIO | 流式上传音频片段 | D.3.2 |
CLIENT_AUDIO_FINISH | EVENT | 手动模式结束音频上传 | D.3.2 |
TEXT | TEXT | 发文本与智能体对话 | D.3.3 |
CLIENT_INPUT_TEXT_TO_SPEECH | EVENT | 主动提交文字合成语音(不触发智能体) | D.3.5 |
CLIENT_INTERRUPT | EVENT | 手动模式打断 TTS 播放 | D.3.6 |
VOICE_CHAT_TRIGGER | ACTIVITY | 主动触发智能体对话 | D.3.8 |
CLIENT_UPDATE_CHAT_CONTEXT | ACTIVITY | 注入短期记忆(需申请权限) | D.3.8 |
CLIENT_UPDATE_COORDINATES_CONTEXT | ACTIVITY | 上报经纬度(需申请权限) | D.3.8 |
PING | PING | 心跳保活,30s 间隔 | D.3.9 |
下行事件(云端 → 设备端)
| 事件名 | contentType | 触发时机 | 协议明细 |
|---|---|---|---|
CFG_BOT_EVENT | EVENT | 建连成功后下发默认配置 | D.3.1 |
SERVER_VOICE_CHAT_UPDATED | EVENT | 配置更新成功响应 | D.3.1 |
ASR | ASR | 语音识别结果 | D.3.2 |
CALL_AGENT_START_EVENT | EVENT | 智能体对话开始 | D.3.4 |
AGENT | AGENT | 智能体回复文本(流式) | D.3.4 |
ACTIVITY | ACTIVITY | 智能体主动开口(静默推送) | D.3.4 |
EMPTY_CONTENT | EVENT | 未识别到有效输入(拒识) | D.3.4 |
COMPLETE | EVENT | 当轮对话完成 | D.3.4 |
TTS_SENTENCE_START | EVENT | 音频字幕(先于 TTS 下发) | D.3.5 |
TTS | TTS | 智能体回复音频(流式) | D.3.5 |
TTS_COMPLETE | EVENT | TTS 音频全部下发完成 | D.3.5 |
CALL_AGENT_INTERRUPTED | EVENT | 打断事件(端侧需清空播放队列) | D.3.6 |
CALL_SKILL_EVENT | EVENT | 指令/IOT/情绪事件 | D.3.7 |
CLIENT_CHAT_CONTEXT_RECEIVED | EVENT | 上下文更新成功响应 | D.3.8 |
PONG | PONG | 心跳响应 | D.3.9 |
USER_AUDIT_FAIL | EVENT | 审核命中 | D.3.10 |
REPEAT_CLIENT_SESSION | EVENT | 互踢(同 botId 双连接) | D.3.10 |