29 KiB
29 KiB
设备注册到聊天记录上传接口文档
1. 设备请求平台时的请求头
运营后台和用户 App 调用 /api/v1/* 时使用:
Authorization: Bearer <用户访问令牌>
设备调用 /device/* 时使用以下 HMAC 请求头:
| 请求头 | 中文含义 | 计算方式 |
|---|---|---|
X-Device-Id |
平台设备编号 | 平台登记设备时返回的 credential.device_id |
X-Device-Timestamp |
请求时间 | 当前 UTC 时间,RFC3339 格式,例如 2026-09-05T09:20:00Z |
X-Device-Nonce |
防重放随机数 | 每个请求重新生成,长度 16–128 字符,不得重复 |
X-Device-Content-SHA256 |
请求正文摘要 | hex_lower(SHA256(rawBody));GET 使用空字节正文 |
X-Device-Signature |
请求签名 | base64url_no_padding(HMAC-SHA256(platformDeviceSecret, canonical)) |
Idempotency-Key |
业务幂等键 | 仅指定接口需要;同一次请求重试必须保持不变,长度 16–128 字符 |
Content-Type |
正文类型 | 有 JSON 正文时为 application/json |
签名原文 canonical:
{大写HTTP方法}\n{请求路径和查询参数}\n{X-Device-Timestamp}\n{X-Device-Nonce}\n{X-Device-Content-SHA256}
计算示例:
body = UTF8('{"hardware_id":"echoear-a1b2c3"}')
bodySha256 = hex_lower(SHA256(body))
timestamp = "2026-09-05T09:20:00Z"
nonce = "d8b81b916ddd4f4584a80a82"
canonical =
"POST\n" +
"/device/v3/hardware-agent-credentials:provision\n" +
timestamp + "\n" +
nonce + "\n" +
bodySha256
signature = base64url_no_padding(
HMAC-SHA256(platformDeviceSecret, UTF8(canonical))
)
注意:
- 摘要必须针对实际发送的原始字节计算,签名后不能再次格式化 JSON。
- 查询参数属于签名内容,例如
/device/v2/commands?limit=10。 - GET 空正文 SHA-256 固定为
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855。 platformDeviceSecret是平台注册时返回的设备密钥,不是火山Product Secret,也不是火山device_secret。- 平台统一响应:成功为
{"request_id":"...","data":...};失败为{"request_id":"...","error":...}。
2. 完整流程
| 顺序 | 调用方 | 动作 | 接口/地址 | 结果 |
|---|---|---|---|---|
| 1 | 运营平台 | 登记设备 | POST /api/v1/ops/devices |
返回平台设备 ID、平台设备密钥和绑定码 |
| 2 | 用户 App | 绑定设备 | POST /api/v1/device-claims |
状态变为 BOUND |
| 3 | 设备 | 获取火山运行凭据 | POST /device/v3/hardware-agent-credentials:provision |
平台动态注册火山设备,消耗一个 License,状态变为 ACTIVE |
| 4 | 设备 | 检查固件 | GET /device/v2/bootstrap |
得到 firmware_compatible |
| 5 | 设备 | 获取设备配置 | GET /device/v2/config |
得到配置版本和运行时配置 |
| 6 | 设备 | 判断是否继续 | firmware_compatible=false 时停止聊天并进入 OTA 流程 |
只有兼容固件可以继续 |
| 7 | 设备 | 创建对话会话 | POST /device/v3/agent-sessions |
获取 Bot ID、系统提示词、人设和授权记忆 |
| 8 | 设备 | 连接火山 | 火山 WebSocket + session.update |
注入本次人设并建立 16 kHz PCM 对话 |
| 9 | 设备 | 上报会话开始 | POST /device/v3/agent-sessions/{id}/events |
平台会话变为 ACTIVE |
| 10 | 设备 | 上传最终聊天文本 | POST /device/v3/agent-sessions/{id}/turns:batch |
用户和智能体最终文本入库 |
| 11 | 设备 | 上报会话结束 | 同一个 events 接口,session_ended |
平台会话变为 COMPLETED |
激活状态:
FACTORY → CLAIMABLE → BOUND → PROVISIONING → ACTIVE → LOST/REVOKED
设备重置流程:
停止语音 → 上传剩余聊天记录 → 上报session_ended → POST /device/v3/factory-reset
→ 平台解除绑定并暂停火山凭据 → 设备按local_actions清理 → 重启进入CLAIMABLE
3. 接口
3.1 登记设备
地址:
POST /api/v1/ops/devices
输入:
| 字段 | 类型 | 必填 | 中文含义 |
|---|---|---|---|
model |
string | 是 | 设备型号 |
hardware_revision |
string | 否 | 硬件版本 |
minimum_security_version |
string | 否 | 最低安全版本 |
minimum_firmware_version |
string | 否 | 最低固件版本 |
household_id |
UUID | 否 | 直接绑定的家庭编号;走绑定码时不传 |
subject_id |
UUID | 否 | 直接绑定的服务对象编号;走绑定码时不传 |
voice_runtime |
enum | 是 | 传 volc_hardware_agent |
hardware_agent_bot_id |
string | 否 | 兼容字段;当前方案不传,由平台产品配置决定 |
hardware_agent_transport |
enum | 否 | low_load 或 high_quality;建议由平台配置 |
hardware_agent_minimum_sdk_version |
string | 否 | 最低硬件智能体 SDK 版本 |
activation_state |
enum | 是 | FACTORY、CLAIMABLE 或 BOUND;一般传 CLAIMABLE |
输出:
| 字段 | 类型 | 中文含义 |
|---|---|---|
device.id |
UUID | 平台设备编号 |
device.status |
string | 设备业务状态 |
device.activation_state |
enum | 激活状态 |
device.activation_revision |
integer | 激活状态版本 |
device.model |
string | 设备型号 |
device.hardware_revision |
string/null | 硬件版本 |
device.minimum_security_version |
string/null | 最低安全版本 |
device.minimum_firmware_version |
string/null | 最低固件版本 |
device.voice_runtime |
enum | 语音运行时 |
device.version |
integer | 设备记录版本 |
credential.device_id |
UUID | 平台设备编号 |
credential.secret |
string | 设备调用平台所用的 HMAC 密钥,仅明文返回一次 |
credential.key_version |
integer | 平台设备密钥版本 |
credential.issued_at |
datetime | 密钥签发时间 |
claim.claim_code |
string/null | 一次性绑定码 |
claim.issued_at |
datetime/null | 绑定码签发时间 |
claim.expires_at |
datetime/null | 绑定码过期时间 |
示例:
POST /api/v1/ops/devices
Authorization: Bearer <ops-token>
Content-Type: application/json
{
"model": "echoear-esp32s3",
"hardware_revision": "v1.0",
"minimum_firmware_version": "1.0.0",
"voice_runtime": "volc_hardware_agent",
"activation_state": "CLAIMABLE"
}
{
"request_id": "req-register-001",
"data": {
"device": {
"id": "10000000-0000-0000-0000-000000000512",
"status": "registered",
"activation_state": "CLAIMABLE",
"activation_revision": 1,
"model": "echoear-esp32s3",
"voice_runtime": "volc_hardware_agent",
"version": 1
},
"credential": {
"device_id": "10000000-0000-0000-0000-000000000512",
"secret": "<platform-device-secret>",
"key_version": 1,
"issued_at": "2026-09-05T09:00:00Z"
},
"claim": {
"claim_code": "ABCD-EFGH-IJKL-MNOP",
"issued_at": "2026-09-05T09:00:00Z",
"expires_at": "2026-09-06T09:00:00Z"
}
}
}
3.2 用户绑定设备
地址:
POST /api/v1/device-claims
输入:
| 字段 | 类型 | 必填 | 中文含义 |
|---|---|---|---|
claim_code |
string | 是 | 一次性绑定码,不能填写设备 UUID |
household_id |
UUID | 是 | 家庭编号 |
subject_id |
UUID | 是 | 设备服务对象编号 |
输出:
| 字段 | 类型 | 中文含义 |
|---|---|---|
binding_id |
UUID | 设备绑定关系编号 |
device_id |
UUID | 平台设备编号 |
household_id |
UUID | 家庭编号 |
subject_id |
UUID | 服务对象编号 |
bound_at |
datetime | 绑定时间 |
示例:
POST /api/v1/device-claims
Authorization: Bearer <user-token>
Content-Type: application/json
{
"claim_code": "ABCD-EFGH-IJKL-MNOP",
"household_id": "10000000-0000-0000-0000-000000000211",
"subject_id": "10000000-0000-0000-0000-000000000411"
}
{
"request_id": "req-bind-001",
"data": {
"binding_id": "10000000-0000-0000-0000-000000000611",
"device_id": "10000000-0000-0000-0000-000000000512",
"household_id": "10000000-0000-0000-0000-000000000211",
"subject_id": "10000000-0000-0000-0000-000000000411",
"bound_at": "2026-09-05T09:10:00Z"
}
}
3.3 占用 License 并获取火山设备凭据
地址:
POST /device/v3/hardware-agent-credentials:provision
输入:
| 字段 | 位置 | 类型 | 必填 | 中文含义 |
|---|---|---|---|---|
Idempotency-Key |
Header | string | 是 | 凭据申请幂等键,16–128 字符 |
hardware_id |
Body | string | 是 | 不随固件升级变化的物理硬件标识 |
输出:
| 字段 | 类型 | 中文含义 |
|---|---|---|
instance_id |
string | 火山硬件智能体实例编号 |
product_key |
string | 火山产品标识 |
device_name |
string | 火山设备名称 |
hardware_id |
string | 已绑定的物理硬件标识 |
device_secret |
string | 火山设备专属密钥,需要加密保存 |
credential_ref |
string | 平台内部凭据引用 |
credential_version |
integer | 火山设备凭据版本 |
credential_source |
enum | platform_dynamic_registration 为新注册,platform_stored 为复用已有凭据 |
issued_at |
datetime | 凭据签发时间 |
示例:
POST /device/v3/hardware-agent-credentials:provision
Idempotency-Key: provision-device-00000512-v1
Content-Type: application/json
<设备HMAC请求头>
{"hardware_id":"echoear-esp32s3-a1b2c3d4"}
{
"request_id": "req-provision-001",
"data": {
"instance_id": "6a92945cc0c4689234aef656",
"product_key": "6a9568047dd4b23eacab9b1a",
"device_name": "dt-10000000000000000000000000000512",
"hardware_id": "echoear-esp32s3-a1b2c3d4",
"device_secret": "<volc-device-secret>",
"credential_ref": "volc-device-secret://10000000-0000-0000-0000-000000000512",
"credential_version": 1,
"credential_source": "platform_dynamic_registration",
"issued_at": "2026-09-05T09:12:00Z"
}
}
3.4 设备恢复出厂
地址:
POST /device/v3/factory-reset
输入:
| 字段 | 类型 | 必填 | 中文含义 |
|---|---|---|---|
Header Idempotency-Key |
string | 是 | 本次重置幂等键,16–128 字符;重试保持不变 |
reset_id |
UUID | 是 | 本次重置唯一编号 |
reset_counter |
integer | 是 | 设备安全存储中的单调递增重置次数 |
occurred_at |
datetime | 是 | 设备确认重置的 UTC 时间;不得晚于请求时间 5 分钟 |
trigger |
enum | 是 | physical_long_press、device_menu 或 service_tool |
firmware_version |
string | 是 | 当前固件版本 |
pending_turn_count |
integer | 是 | 未上传聊天记录数;必须为 0 |
active_conversation_id |
UUID | 否 | 设备认为仍在运行的会话编号 |
输出:
| 字段 | 类型 | 中文含义 |
|---|---|---|
reset_id |
UUID | 重置编号 |
device_id |
UUID | 平台设备编号 |
activation_state |
enum | 重置后固定为 CLAIMABLE |
reset_counter |
integer | 平台接受的重置次数 |
binding_removed |
boolean | 是否关闭了原用户绑定 |
previous_binding_id |
UUID/null | 原绑定关系编号 |
provider_credential_status |
enum | 火山设备凭据状态,通常为 SUSPENDED |
license_action |
enum | 固定为 RETAINED,重置不释放火山 License |
ended_conversation_count |
integer | 平台强制结束的残留会话数 |
cancelled_command_count |
integer | 平台取消的待执行命令数 |
config_revision |
integer | 重置后的设备配置版本 |
claim.code |
string | 新的一次性绑定码 |
claim.issued_at |
datetime | 绑定码签发时间 |
claim.expires_at |
datetime | 绑定码过期时间 |
local_actions |
string[] | 设备收到成功响应后必须执行的本地清理动作 |
reset_at |
datetime | 平台完成重置的时间 |
平台同时把旧用户侧的设备状态置为离线,并推送 device.binding.reset 事件。设备收到成功响应后,按 local_actions 清理本地火山凭据、用户上下文、会话与网络配置;设备平台身份和 HMAC 密钥不得删除。
示例:
POST /device/v3/factory-reset
Idempotency-Key: factory-reset-00000512-0001
Content-Type: application/json
<设备HMAC请求头>
{
"reset_id": "10000000-0000-0000-0000-000000000901",
"reset_counter": 1,
"occurred_at": "2026-09-05T09:30:00Z",
"trigger": "physical_long_press",
"firmware_version": "1.1.0",
"pending_turn_count": 0
}
{
"request_id": "req-reset-001",
"data": {
"reset_id": "10000000-0000-0000-0000-000000000901",
"device_id": "10000000-0000-0000-0000-000000000512",
"activation_state": "CLAIMABLE",
"reset_counter": 1,
"binding_removed": true,
"previous_binding_id": "10000000-0000-0000-0000-000000000611",
"provider_credential_status": "SUSPENDED",
"license_action": "RETAINED",
"ended_conversation_count": 0,
"cancelled_command_count": 0,
"config_revision": 9,
"claim": {
"code": "QRST-UVWX-YZ23-4567",
"issued_at": "2026-09-05T09:30:01Z",
"expires_at": "2026-09-06T09:30:01Z"
},
"local_actions": [
"clear_volc_credential",
"clear_user_context",
"clear_session_state",
"clear_network_credentials",
"reboot_to_claimable"
],
"reset_at": "2026-09-05T09:30:01Z"
}
}
设备必须保留平台 device_id、平台 HMAC secret 和 hardware_id;其余用户上下文、火山凭据、会话状态和网络配置按 local_actions 清除。
3.5 检查固件版本
地址:
GET /device/v2/bootstrap
输入:
| 字段 | 位置 | 类型 | 必填 | 中文含义 |
|---|---|---|---|---|
firmware_version |
Query | string | 是 | 当前固件版本 |
device_time |
Query | datetime | 是 | 设备 UTC 时间,RFC3339 |
board_rev |
Query | string | 否 | 硬件版本 |
rtc_sdk_version |
Query | string | 否 | 火山 SDK 版本 |
codec |
Query | string | 否 | 音频格式,例如 pcm16 |
sample_rate |
Query | integer | 否 | 音频采样率,当前为 16000 |
network |
Query | string | 否 | 网络类型,例如 wifi |
输出:
| 字段 | 类型 | 中文含义 |
|---|---|---|
server_time |
datetime | 平台 UTC 时间 |
clock_skew_ms |
integer | 平台时间减设备时间的毫秒差 |
device.device_id |
UUID | 平台设备编号 |
device.status |
string | 设备业务状态 |
device.model |
string | 设备型号 |
device.hardware_revision |
string/null | 硬件版本 |
device.minimum_security_version |
string/null | 最低安全版本 |
device.minimum_firmware_version |
string/null | 最低固件版本 |
device.firmware_compatible |
boolean | 当前固件是否允许继续聊天 |
device.config_revision |
integer | 当前平台配置版本 |
device.binding.bound |
boolean | 是否已绑定 |
device.binding.household_id |
UUID/null | 家庭编号 |
device.binding.subject_id |
UUID/null | 服务对象编号 |
device.binding.subject_name |
string/null | 服务对象名称 |
示例:
GET /device/v2/bootstrap?firmware_version=1.0.0&board_rev=v1.0&rtc_sdk_version=1.1.0&codec=pcm16&sample_rate=16000&network=wifi&device_time=2026-09-05T09%3A15%3A00Z
<设备HMAC请求头>
{
"request_id": "req-bootstrap-001",
"data": {
"server_time": "2026-09-05T09:15:01Z",
"clock_skew_ms": 1000,
"device": {
"device_id": "10000000-0000-0000-0000-000000000512",
"status": "registered",
"model": "echoear-esp32s3",
"minimum_firmware_version": "1.0.0",
"firmware_compatible": true,
"config_revision": 8,
"binding": {
"bound": true,
"household_id": "10000000-0000-0000-0000-000000000211",
"subject_id": "10000000-0000-0000-0000-000000000411",
"subject_name": "测试用户"
}
}
}
}
3.6 获取设备配置
地址:
GET /device/v2/config
输入:
| 字段 | 位置 | 类型 | 必填 | 中文含义 |
|---|---|---|---|---|
If-None-Match |
Header | string | 否 | 本地配置 ETag;未变化时返回 304 |
输出:
| 字段 | 类型 | 中文含义 |
|---|---|---|
Response Header ETag |
string | 当前配置 ETag |
device_id |
UUID | 平台设备编号 |
revision |
integer | 配置版本 |
desired_config |
object | 平台期望设备应用的配置 |
desired_config.voice_runtime |
enum | 语音运行时 |
desired_config.hardware_agent_transport |
enum | 火山传输方式 |
desired_config.minimum_sdk_version |
string | 最低 SDK 版本 |
reported_revision |
integer/null | 设备此前报告的配置版本 |
binding |
object | 当前绑定信息,字段与 bootstrap 相同 |
示例:
GET /device/v2/config
If-None-Match: "7"
<设备HMAC请求头>
{
"request_id": "req-config-001",
"data": {
"device_id": "10000000-0000-0000-0000-000000000512",
"revision": 8,
"desired_config": {
"voice_runtime": "volc_hardware_agent",
"hardware_agent_transport": "low_load",
"minimum_sdk_version": "1.1.0"
},
"reported_revision": 7,
"binding": {
"bound": true,
"household_id": "10000000-0000-0000-0000-000000000211",
"subject_id": "10000000-0000-0000-0000-000000000411"
}
}
}
3.7 创建会话并获取系统提示词
地址:
POST /device/v3/agent-sessions
输入:
| 字段 | 类型 | 必填 | 中文含义 |
|---|---|---|---|
Header Idempotency-Key |
string | 是 | 创建会话幂等键,16–128 字符 |
device_time |
datetime | 是 | 设备 UTC 时间 |
monotonic_ms |
integer | 否 | 开机后的单调时钟毫秒数 |
capabilities.hardware_agent |
boolean | 是 | 必须为 true |
capabilities.sdk_version |
string | 是 | 硬件智能体 SDK 版本 |
capabilities.transports |
string[] | 是 | 支持的传输方式 |
capabilities.input_audio_format |
string | 是 | 上行音频能力,当前为 pcm_s16le_16000_mono |
capabilities.output_audio_format |
string | 是 | 下行音频能力,当前为 pcm_s16le_16000_mono |
capabilities.server_event_callback |
boolean | 是 | 当前传 false |
capabilities.transcript_upload |
boolean | 是 | 必须为 true |
capabilities.dynamic_session_config |
boolean | 是 | 必须为 true |
capabilities.credential_rotation |
boolean | 是 | 必须为 true |
capabilities.near_pcm_recording |
boolean | 是 | 是否支持近端录音 |
capabilities.far_pcm_recording |
boolean | 是 | 是否支持远端录音 |
network.type |
string | 是 | 网络类型 |
network.rssi |
integer | 否 | Wi-Fi RSSI |
requested_goal |
string | 是 | 固定为 open_conversation |
config_revision |
integer | 是 | /device/v2/config 返回的配置版本 |
输出:
| 字段 | 类型 | 中文含义 |
|---|---|---|
conversation_id |
UUID | 平台会话编号 |
status |
string | 正常为 SESSION_READY |
runtime_type |
string | volc_hardware_agent |
runtime.provider |
string | 服务商,当前为 volcengine |
runtime.bot_id |
string | 本次使用的 Bot ID |
runtime.transport |
string | 本次传输方式 |
runtime.provider_session_ref |
string | 火山会话引用 |
runtime.session_nonce |
string | 会话证明随机值 |
runtime.config_digest |
string | 本次动态配置摘要 |
runtime.wait_for_session_update |
boolean | 是否必须先应用动态人设 |
session_config.dialog_id |
string | 本次对话标识 |
session_config.system_prompt |
string | 系统提示词/核心人设 |
session_config.persona_tone |
string | 人设语气和表达风格 |
session_config.authorized_context |
string | 授权的用户背景、近期摘要和长期记忆 |
session_config.prompt_bundle_version |
string | 提示词版本 |
session_config.tool_url |
URL/null | 工具调用地址 |
session_config.tool_scope_token |
string/null | 本次会话工具令牌 |
privacy.retention_mode |
string | 数据保留模式 |
privacy.record_near |
boolean | 是否允许近端录音 |
privacy.record_far |
boolean | 是否允许远端录音 |
privacy.upload_allowed |
boolean | 是否允许上传聊天记录 |
session.engine_mode |
string | 会话引擎模式 |
session.heartbeat_interval_sec |
integer | 会话状态上报间隔 |
session.allocation_expires_at |
datetime | 会话分配过期时间 |
示例:
POST /device/v3/agent-sessions
Idempotency-Key: session-device-00000512-0001
Content-Type: application/json
<设备HMAC请求头>
{
"device_time": "2026-09-05T09:20:00Z",
"monotonic_ms": 812345,
"capabilities": {
"hardware_agent": true,
"sdk_version": "1.1.0-echoear",
"transports": ["low_load"],
"input_audio_format": "pcm_s16le_16000_mono",
"output_audio_format": "pcm_s16le_16000_mono",
"server_event_callback": false,
"transcript_upload": true,
"dynamic_session_config": true,
"credential_rotation": true,
"near_pcm_recording": false,
"far_pcm_recording": false
},
"network": {"type":"wifi","rssi":-52},
"requested_goal": "open_conversation",
"config_revision": 8
}
{
"request_id": "req-session-001",
"data": {
"conversation_id": "10000000-0000-0000-0000-000000000801",
"status": "SESSION_READY",
"runtime_type": "volc_hardware_agent",
"runtime": {
"provider": "volcengine",
"bot_id": "botM4gWQ9A9y",
"transport": "low_load",
"provider_session_ref": "provider-session-ref",
"session_nonce": "<session-nonce>",
"config_digest": "<config-digest>",
"wait_for_session_update": true
},
"session_config": {
"dialog_id": "dialog-00000801",
"system_prompt": "你是面向长者的陪伴助手……",
"persona_tone": "率真、自然",
"authorized_context": "经授权的背景和记忆……",
"prompt_bundle_version": "persona-v12"
},
"privacy": {
"retention_mode": "transcript_only",
"record_near": false,
"record_far": false,
"upload_allowed": true
},
"session": {
"engine_mode": "hardware_agent",
"heartbeat_interval_sec": 30,
"allocation_expires_at": "2026-09-05T09:25:00Z"
}
}
}
3.8 连接火山并注入人设
地址:
wss://ai-gateway.vei.volces.com/v1/realtime?bot={bot_id}&wait_for_session_update=true
输入:
| 字段 | 位置 | 中文含义 | 来源/计算 |
|---|---|---|---|
bot |
Query | Bot ID | 创建会话返回的 runtime.bot_id |
X-Auth-Type |
Header | 鉴权类型 | 固定为 1 |
X-Product-Key |
Header | 火山产品标识 | provision 返回的 product_key |
X-Device-Name |
Header | 火山设备名称 | provision 返回的 device_name |
X-Random-Num |
Header | 随机数 | 每次连接重新生成 |
X-Timestamp |
Header | Unix 秒 | 当前时间 |
X-Instance-Id |
Header | 火山实例编号 | provision 返回的 instance_id |
X-Hardware-Id |
Header | 物理硬件标识 | provision 使用的 hardware_id |
X-Signature |
Header | 火山鉴权签名 | base64(HMAC-SHA256(device_secret, canonical)) |
session.update |
WebSocket JSON | 动态会话配置 | 注入平台返回的人设和记忆 |
输出:
| 事件 | 中文含义 |
|---|---|
session.created / session.updated |
火山会话创建/动态人设生效 |
conversation.item.input_audio_transcription.completed |
用户最终识别文本 |
response.audio_transcript.done |
智能体最终回复文本 |
| 音频数据 | 智能体返回的 PCM16 音频,按 16 kHz 单声道播放 |
| error 事件 | 火山连接或会话失败 |
示例:
canonical = "auth_type=1&device_name={device_name}&random_num={random_num}&product_key={product_key}×tamp={timestamp}&instance_id={instance_id}"
X-Signature = base64(HMAC-SHA256(device_secret, canonical))
{
"event_id": "evt-session-update-001",
"type": "session.update",
"session": {
"object": "realtime.session",
"model": "",
"input_audio_format": "pcm16",
"output_audio_format": "pcm16",
"config": {
"ASRConfig": {"TurnDetectionMode": 0},
"LLMConfig": {
"SystemMessages": [
"<system_prompt>\n表达风格:<persona_tone>\n授权上下文:<authorized_context>\n会话标识:<dialog_id>"
]
}
},
"agent_config": {"EnableConversationStateCallback": false}
}
}
3.9 上报会话事件
地址:
POST /device/v3/agent-sessions/{conversation_id}/events
输入:
| 字段 | 类型 | 必填 | 中文含义 |
|---|---|---|---|
Path conversation_id |
UUID | 是 | 平台会话编号 |
event_id |
string | 是 | 事件唯一编号 |
sequence_no |
integer | 是 | 事件顺序号,从 1 开始递增 |
event_type |
enum | 是 | session_started、session_updated、session_ended 或 session_failed |
occurred_at |
datetime | 是 | 事件发生时间 |
provider_session_ref |
string | 是 | 火山会话引用 |
session_nonce |
string | 是 | 会话证明随机值 |
provider_connection_ref |
string | 启动时必填 | WebSocket 连接标识 |
bot_id |
string | 启动时必填 | 实际连接的 Bot ID |
transport |
string | 启动时必填 | 实际传输方式 |
config_digest |
string | 启动时必填 | 已应用的人设配置摘要 |
dynamic_config_applied |
boolean | 启动时必填 | 必须为 true |
error_code |
string | 失败时填写 | 失败错误码 |
输出:
| 字段 | 类型 | 中文含义 |
|---|---|---|
conversation_id |
UUID | 平台会话编号 |
status |
string | 会话状态,开始后为 ACTIVE,正常结束后为 COMPLETED |
action |
enum | continue 或 stop_session |
duplicate |
boolean | 是否为重复事件 |
accepted_at |
datetime | 平台接收时间 |
示例:
开始请求:
{
"event_id": "device-event-start-001",
"sequence_no": 1,
"event_type": "session_started",
"occurred_at": "2026-09-05T09:20:03Z",
"provider_session_ref": "provider-session-ref",
"session_nonce": "<session-nonce>",
"provider_connection_ref": "ws-connection-001",
"bot_id": "botM4gWQ9A9y",
"transport": "low_load",
"config_digest": "<config-digest>",
"dynamic_config_applied": true
}
结束示例:
{
"event_id": "device-event-end-001",
"sequence_no": 2,
"event_type": "session_ended",
"occurred_at": "2026-09-05T09:25:00Z",
"provider_session_ref": "provider-session-ref",
"session_nonce": "<session-nonce>"
}
响应示例:
{
"request_id": "req-event-001",
"data": {
"conversation_id": "10000000-0000-0000-0000-000000000801",
"status": "ACTIVE",
"action": "continue",
"duplicate": false,
"accepted_at": "2026-09-05T09:20:03Z"
}
}
3.10 上传聊天记录
地址:
POST /device/v3/agent-sessions/{conversation_id}/turns:batch
输入:
| 字段 | 类型 | 必填 | 中文含义 |
|---|---|---|---|
Path conversation_id |
UUID | 是 | 平台会话编号 |
Header Idempotency-Key |
string | 是 | 本批记录幂等键,16–128 字符 |
turns |
array | 是 | 最终聊天记录数组,每批 1–500 条 |
turns[].turn_key |
string | 是 | 会话内唯一的轮次标识,最长 255 字符 |
turns[].sequence_no |
integer | 是 | 对话顺序号,会话内唯一且大于 0 |
turns[].speaker |
enum | 是 | 用户为 subject,智能体为 agent |
turns[].start_at |
datetime | 是 | 本轮开始时间 |
turns[].end_at |
datetime | 是 | 本轮结束时间,不早于开始时间 |
turns[].final_text |
string | 是 | 最终文本,最长 20000 字符 |
turns[].interrupted |
boolean | 是 | 本轮是否被打断 |
输出:
| 字段 | 类型 | 中文含义 |
|---|---|---|
conversation_id |
UUID | 平台会话编号 |
accepted_count |
integer | 本次新写入的记录数 |
duplicate_count |
integer | 本次幂等重复的记录数 |
示例:
POST /device/v3/agent-sessions/10000000-0000-0000-0000-000000000801/turns:batch
Idempotency-Key: turns-conversation-00000801-0001
Content-Type: application/json
<设备HMAC请求头>
{
"turns": [
{
"turn_key": "user-final-001",
"sequence_no": 1,
"speaker": "subject",
"start_at": "2026-09-05T09:20:10Z",
"end_at": "2026-09-05T09:20:12Z",
"final_text": "今天天气怎么样?",
"interrupted": false
},
{
"turn_key": "agent-final-001",
"sequence_no": 2,
"speaker": "agent",
"start_at": "2026-09-05T09:20:12Z",
"end_at": "2026-09-05T09:20:16Z",
"final_text": "我来帮你看看。",
"interrupted": false
}
]
}
{
"request_id": "req-turns-001",
"data": {
"conversation_id": "10000000-0000-0000-0000-000000000801",
"accepted_count": 2,
"duplicate_count": 0
}
}