You need to enable JavaScript to run this app.
导航
接收智能体状态
最近更新时间:2025.11.03 20:51:14首次发布时间:2025.01.09 17:23:24
复制全文
我的收藏
有用
有用
无用
无用

在实时对话式 AI 场景下,你可以通过回调机制接收智能体状态,如聆听中、思考中、说话中、被打断等,可用于在客户端实时展示智能体状态或在服务端进行存储与分析。

接收方式

支持通过客户端或服务端两种方式接收智能体状态信息,它们的适用场景有所不同:

  • 客户端接收(推荐):延迟更低,可靠性更高,适用于需要在终端实时展示智能体状态的场景。
  • 服务端接收:适用于需要持久化存储、进行二次分析,或在客户端性能受限、不便处理实时二进制消息的场景。

通过客户端接收

实现方式

  1. 调用 StartVoiceChat 接口将 AgentConfig.EnableConversationStateCallback 设置为 true
  2. 在客户端监听房间内广播二进制消息的回调 onRoomBinaryMessageReceived
    • 不同端回调名称可能有差异,具体请参见客户端 API 参考
    • 其中,C 语言端接口名称为 on_message_received
  3. 解析消息。具体操作,请参见解析消息
    当智能体状态发生变化时,客户端将通过该回调收到一个二进制消息。你需要对该消息进行解析,才能获取具体的状态信息。

解析消息

收到的智能体状态消息的回调格式如下:

参数名类型描述
uidString消息发送者 ID。
messageString二进制消息内容。长度不超过 64 KB。与服务端返回二进制消息格式相同,详细参看二进制消息格式

你可以参考以下示例代码对回调信息中的 message 内容进行解析。

import VERTC from '@volcengine/rtc';

/**
 * @brief TLV 数据格式转换成字符串
 * @note TLV 数据格式
 * | magic number | length(big-endian) | value |
 * @param {ArrayBufferLike} tlvBuffer
 * @returns 
 */
function tlv2String(tlvBuffer: ArrayBufferLike) {
  const typeBuffer = new Uint8Array(tlvBuffer, 0, 4);
  const lengthBuffer = new Uint8Array(tlvBuffer, 4, 4);
  const valueBuffer = new Uint8Array(tlvBuffer, 8);

  let type = '';
  for (let i = 0; i < typeBuffer.length; i++) {
    type += String.fromCharCode(typeBuffer[i]);
  }

  const length =
    (lengthBuffer[0] << 24) | (lengthBuffer[1] << 16) | (lengthBuffer[2] << 8) | lengthBuffer[3];

  const value = new TextDecoder().decode(valueBuffer.subarray(0, length));

  return { type, value };
};

/**
 * @brief Room Message Handler
 */
function handleRoomBinaryMessageReceived(
  event: {
    userId: string;
    message: ArrayBuffer;
  },
) {
  const { message } = event;
  const { type, value } = tlv2String(message);
  const data = JSON.parse(value);
  const { EventTime, RoundID, Stage, TaskId, UserID, ErrorInfo } = data || {};
  const { Code, Description } = Stage || {};
  // 对 type、data 进行业务处理
  console.log(type, EventTime, RoundID, TaskId, UserID, Code, Description);
  if (ErrorInfo) {
    const { ErrorCode, Reason } = ErrorInfo;
    console.log('Error Occurred:', ErrorCode, Reason);
  }
  // ...
}

/**
 * @brief 监听房间内二进制消息
 */
this.engine.on(VERTC.events.onRoomBinaryMessageReceived, handleRoomBinaryMessageReceived);

通过服务端接收

实现方式

  1. 调用 StartVoiceChat 接口时,需配置如下参数:
// 调用 StartVoiceChat 接口时 AgentConfig 部分示例
"AgentConfig": {
    "EnableConversationStateCallback": true,
    // ... 其他 AgentConfig 参数
    "ServerMessageURLForRTS": "YOUR_SERVER_CALLBACK_URL", // 必填,接收回调的 URL
    "ServerMessageSignatureForRTS": "YOUR_SIGNATURE" // 必填,签名密钥,用于验证回调来源的安全性
}
  1. 解析消息。具体操作,请参见解析消息
    当智能体状态发生变化时,配置的回调 URL 会收到一个包含二进制数据的 HTTP POST 请求消息。你需要对消息体进行解析,提取状态信息。

解析消息

收到的回调格式如下:

参数名类型描述
messageStringBase64 编码的二进制消息内容。长度不超过 48 KB。格式参看二进制消息格式
signatureString鉴权签名。可与 StartVoiceChat 接口中传入的 ServerMessageSignatureForRTS 字段值进行对比以进行鉴权验证。

你可以参考以下示例代码对回调信息中的 message 内容进行解析。

package main

import (
   "encoding/base64"
   "encoding/binary"
   "encoding/json"
   "fmt"
)

const (
   conversationStageHeader = "conv"
   exampleSignature        = "example_signature"
)

type RtsMessage struct {
   Message   string `json:"message"`
   Signature string `json:"signature"`
}

type Conv struct {
   TaskID    string    `json:"TaskId"`
   UserID    string    `json:"UserID"`
   RoundID   int64     `json:"RoundID"`   
   EventTime int64     `json:"EventTime"`
   Stage     StageInfo `json:"Stage"`
}

type StageInfo struct {
   Code        stageCode `json:"Code"`
   Description string    `json:"Description"`
}
type stageCode int

const (
   _ stageCode = iota
   listening
   thinking
   answering
   interrupted
   answerFinish
)

var (
   stageListening    = StageInfo{Code: listening, Description: "listening"}
   stageThinking     = StageInfo{Code: thinking, Description: "thinking"}
   stageAnswering    = StageInfo{Code: answering, Description: "answering"}
   stageInterrupted  = StageInfo{Code: interrupted, Description: "interrupted"}
   stageAnswerFinish = StageInfo{Code: answerFinish, Description: "answerFinish"}
)

func HandleConversationStageMsg(c *gin.Context) {
   msg := &RtsMessage{}
   if err := c.BindJSON(&msg); err != nil {
      fmt.Printf("BindJson failed,err:%v\n", err)
      return
   }
   if msg.Signature != exampleSignature {
      fmt.Printf("Signature not match\n")
      return
   }

   conv, err := Unpack(msg.Message)
   if err != nil {
      fmt.Printf("Unpack failed,err:%v\n", err)
      return
   }

   fmt.Println(conv)

   //业务逻辑

   c.String(200, "ok")
}

func Unpack(msg string) (*Conv, error) {
   data, err := base64.StdEncoding.DecodeString(msg)
   if err != nil {
      return nil, fmt.Errorf("DecodeString failed,err:%v", err)
   }
   if len(data) < 8 {
      return nil, fmt.Errorf("Data invalid")
   }
   dataHeader := string(data[:4])
   if dataHeader != conversationStageHeader {
      return nil, fmt.Errorf("Header not match")
   }
   dataSize := binary.BigEndian.Uint32(data[4:8])
   if dataSize+8 != uint32(len(data)) {
      return nil, fmt.Errorf("Size not match")
   }

   subData := data[8:]
   conv := &Conv{}
   err = json.Unmarshal(subData, conv)
   if err != nil {
      return nil, fmt.Errorf("Unmarshal failed,err:%v\n", err)
   }
   return conv, nil
}

func main() {

   r := gin.Default()
   r.POST("/example_domain/vertc/cstage", HandleConversationStageMsg)
   r.Run()
}

附录

二进制消息格式

二进制消息格式如下:

alt

参数名类型描述
magic numberbinary消息格式,固定为 conv
lengthbinary消息长度,单位为 bytes。存放方式为大端序。
conversation_status_messagebinary消息详细信息。格式参看 conversation_status_message 格式

conversation_status_message:

参数名类型描述
TaskIdString智能体任务 ID。
UserIDString说话人 UserId。
RoundIDInt64对话轮次。从 0 开始计数。
EventTimeInt64该事件在 RTC 服务器上发生的 Unix 时间戳 (ms)。
StageStage任务状态详细描述。
ErrorInfoErrorDetail任务错误详细信息。仅当 Stage.Code 为 0 时,会返回该字段。

Stage

参数名类型描述
CodeInt任务状态码。
  • 0:任务发生错误。
  • 1:智能体聆听中。
  • 2:智能体思考中。
  • 3:智能体说话中。
  • 4:智能体被打断。
  • 5:智能体说话完成。
DescriptionString任务状态描述。

ErrorDetail

参数名类型描述
CodeInt错误状态码。详细定义,请参见错误码
ReasonString错误详细原因。