员工对话接口(无需认证)
更新时间:2025-12-17
本接口描述了数字员工对话系统的API接口,包括获取对话实例ID、建立WebSocket连接和实时对话功能。
前置条件:
employeeId—— 数字员工 IDaiobOnlineRobotId—— 数字员工绑定的上岗机器人 ID- 数字员工必须已上岗
基础信息:
- API版本: v1
- 内容类型:
application/json - 响应格式: JSON / Server-Sent Events (SSE)
接口概览:
| 功能 | 方法 | 路径 | 描述 |
|---|---|---|---|
| 获取访问凭证 | GET | /access/r/ai-agent/token/{employeeId} | 获取对话实例ID |
| WebSocket连接 | WebSocket | /access/w/ai-agent/keepalive-pool/{employee_id}/{instance_id} | 建立心跳连接 |
| 流式对话 | POST | /open/aiob-server/text/stream/query | 实时对话接口 |
1. 获取对话访问凭证
请求信息:
- 方法:
GET - 路径:
/employee-console/v1/access/r/ai-agent/token/{employeeId} - 功能描述: 通过数字员工ID获取对话访问凭证和实例ID,用于后续WebSocket连接和对话请求
路径参数: |参数名|类型|必填|描述|示例| | --- | --- | --- | --- | --- | |employeeId|String|是|数字员工唯一标识|Hnh4hDWKh1uAoFDgQIUZ|
请求示例:
Plain Text
1curl -X GET 'https://ky.cloud.baidu.com/employee-console/v1/access/r/ai-agent/token/Hnh4hDWKh1uAoFDgQIUZ'
响应参数:
成功响应 (200):
| 参数名 | 类型 | 描述 |
|---|---|---|
| code | String | 响应状态码,成功为 employee-console_ok |
| message | String | 响应消息 |
| data | Object | 响应数据 |
| data.authorization | String | 访问凭证token,暂未使用 |
| data.instanceId | String | 实例ID,用于WebSocket连接 |
响应示例:
Plain Text
1{
2 "code": "employee-console_ok",
3 "message": "请求成功",
4 "data": {
5 "authorization": "i-rfdtr28pbnjtt/b0223368801657befc8c05c1a0983078f779eaf30db35feb7b9181afa4bc9f34/2025-11-19T03:44:08.241571048Z/dialogue",
6 "instanceId": "ECI_81e57cf6-41ad-4e32-a748-e915daae74ad"
7 }
8}
2. 建立WebSocket心跳连接
连接信息:
- 协议:
WebSocket - 路径:
wss://ky.cloud.baidu.com/employee-console/v1/access/w/ai-agent/keepalive-pool/{employee_id}/{instance_id} - 功能描述: 建立WebSocket连接保持会话活跃状态,用于数字员工并发控制
路径参数:
| 参数名 | 类型 | 必填 | 描述 | 示例 |
|---|---|---|---|---|
| employee_id | String | 是 | 数字员工ID | Hnh4hDWKh1uAoFDgQIUZ |
| instance_id | String | 是 | 实例ID(从token接口获取) | ECI_81e57cf6-41ad-4e32-a748-e915daae74ad |
连接示例:
Plain Text
1const websocket = new WebSocket('wss://ky.cloud.baidu.com/employee-console/v1/access/w/ai-agent/keepalive-pool/Hnh4hDWKh1uAoFDgQIUZ/ECI_81e57cf6-41ad-4e32-a748-e915daae74ad');
2
3// 连接建立后每1秒发送心跳
4websocket.onopen = function(event) {
5 // 启动心跳发送
6 setInterval(() => {
7 if (websocket.readyState === WebSocket.OPEN) {
8 websocket.send('ping');
9 }
10 }, 1000);
11};
12
13// 接收服务端消息(关键:防止网关超时)
14websocket.onmessage = function(event) {
15 console.log('收到服务端心跳响应:', event.data);
16};
心跳维护:
- 心跳频率: 每1秒发送一次
- 心跳消息: 文本类型
"ping" - 用途: 保持连接活跃,防止超时断开
- 重要说明: 除了发送ping消息外,必须同时接收服务端返回的消息,否则可能因网关超时(约60秒)而断开连接
3. 流式对话接口
注意:
- 首次对话时 sessionId 需要传空,并从响应中获取到生成的 sessionId
- 后续对话时,需传首次对话生成的 sessionId
请求信息:
- 方法:
POST - 路径:
/employee-console/v1/open/aiob-server/text/stream/query - 功能描述: 发送用户消息并接收数字员工的流式响应
- 响应类型: Server-Sent Events (SSE)
Headers: |参数名|类型|必填|描述| | --- | --- | --- | --- | |Content-Type|String|是|application/json|
Body参数:
| 参数名 | 类型 | 必填 | 描述 | 示例 |
|---|---|---|---|---|
| query | String | 否 | 用户消息内容,空字符串表示开场白 | "你好" |
| queryId | String | 是 | 请求唯一标识,每次对话时需随机生成并传入 | "uuid-123" |
| employeeId | String | 是 | 数字员工ID | "Hnh4hDWKh1uAoFDgQIUZ" |
| instanceId | String | 是 | 实例ID | "ECI_81e57cf6-41ad-4e32-a748-e915daae74ad" |
| robotId | String | 是 | 机器人ID,aiobOnlineRobotId | "3a1c45a670d949239af524dc3c2668c2" |
| sessionId | String | 否 | 会话ID 1. 首次对话时需要传空,并从响应中获取到生成的 sessionId 2. 后续对话时,需传首次对话生成的 sessionId | "session-abc-123" |
| enableContactCard | Integer | 否 | 是否启用联系卡片 (0/1) | 0 |
| enableSlotFillCard | Integer | 否 | 是否启用留资表单 (0/1) | 0 |
| isComplete | Integer | 是 | 结果状态 (0:中间结果 1:最终结果) | 1 |
| index | integer | 否 | 中间态对应索引编号,默认为0 | |
| action | integer | 否 | 指令 1-静默 2-打断 3-挂机 | |
| promptVar | MapString | 否 | 传递给prompt变量信息 {"name":"张三","sex":"男"} |
首次请求示例:
Plain Text
1curl -X POST 'https://ky.cloud.baidu.com/employee-console/v1/open/aiob-server/text/stream/query' \
2 -H 'Content-Type: application/json' \
3 -d '{
4 "query": "你好",
5 "queryId": "uuid-123",
6 "employeeId": "Hnh4hDWKh1uAoFDgQIUZ",
7 "instanceId": "ECI_1f206342-b1ce-4041-8a62-d219279e95a6",
8 "robotId": "3a1c45a670d949239af524dc3c2668c2",
9 "sessionId": "",
10 "enableContactCard": 0,
11 "enableSlotFillCard": 0,
12 "isComplete": 1
13 }'
后续请求示例:
Plain Text
1curl -X POST 'https://ky.cloud.baidu.com/employee-console/v1/open/aiob-server/text/stream/query' \
2 -H 'Content-Type: application/json' \
3 -d '{
4 "query": "你好",
5 "queryId": "uuid-123",
6 "employeeId": "Hnh4hDWKh1uAoFDgQIUZ",
7 "instanceId": "ECI_1f206342-b1ce-4041-8a62-d219279e95a6",
8 "robotId": "3a1c45a670d949239af524dc3c2668c2",
9 "sessionId": "b0eacf38-2bf3-47f5-a42c-4f4b7cd7f248",
10 "enableContactCard": 0,
11 "enableSlotFillCard": 0,
12 "isComplete": 1
13 }'
响应参数:
SSE数据格式,每个数据块包含以下字段:
| 参数名 | 类型 | 描述 |
|---|---|---|
| answer | String | 机器人回复内容片段 |
| isEnd | Boolean | 当前数据块是否为最后一块 |
| index | Integer | 数据块序号 |
| sessionId | String | 会话ID |
| queryId | String | 请求ID |
| code | Integer | 状态码 (0:成功) |
| type | Integer | 消息类型 (1:异常 2:正常对话 3:指令 4:大模型接管 5: 意图识别结果) |
| action | Integer | 指令类型 (1:静默 2:打断 3:挂机) |
| msg | String | 状态消息 |
| intentResult | String | 意图识别结果,需要开启 enableContactCard 和 enableSlotFillCard 1. CONTACT —— 获取企业联系方式的意图 2. SLOT_FILL —— 套取用户联系方式的意图 |
响应示例:
Plain Text
1data:{"answer":"您好,我是表单,","isEnd":false,"index":0,"sessionId":"b0eacf38-2bf3-47f5-a42c-4f4b7cd7f248","queryId":"9c7219f4-9b53-4635-8aaf-608ba27ec6f6","code":0}
2
3data:{"answer":"是宝马汽车销售精英培训手册的数字员工。","isEnd":false,"index":1,"sessionId":"b0eacf38-2bf3-47f5-a42c-4f4b7cd7f248","queryId":"9c7219f4-9b53-4635-8aaf-608ba27ec6f6","code":0}
4
5data:{"answer":"请问您想了解哪方面的内容呢?","isEnd":false,"index":2,"sessionId":"b0eacf38-2bf3-47f5-a42c-4f4b7cd7f248","queryId":"9c7219f4-9b53-4635-8aaf-608ba27ec6f6","code":0}
6
7data:{"answer":"","type":4,"isEnd":true,"index":3,"sessionId":"b0eacf38-2bf3-47f5-a42c-4f4b7cd7f248","action":0,"queryId":"9c7219f4-9b53-4635-8aaf-608ba27ec6f6","code":0}
8
9data:{"type":5}
4. 完整对话流程
客户端调用流程:
Plain Text
1// 1. 获取访问凭证
2 const tokenResponse = await fetch('/employee-console/v1/access/r/ai-agent/token/1omFAG5XYjrkJWdr8hC7');
3 const { authorization, instanceId } = tokenResponse.data;
4
5 // 2. 建立WebSocket连接
6 const ws = new WebSocket(`wss://ky.cloud.baidu.com/employee-console/v1/access/w/ai-agent/keepalive-pool/1omFAG5XYjrkJWdr8hC7/${instanceId}`);
7
8 // 3. 维持心跳(双向通信)
9 setInterval(() => {
10 if (ws.readyState === WebSocket.OPEN) {
11 ws.send('ping');
12 }
13 }, 1000);
14
15 // 接收服务端消息(防止网关超时)
16 ws.onmessage = function(event) {
17 console.log('收到服务端心跳响应:', event.data);
18 };
19
20 // 4. 发起对话
21 const eventSource = new EventSource('/employee-console/v1/open/aiob-server/text/stream/query', {
22 method: 'POST',
23 headers: { 'Content-Type': 'application/json' },
24 body: JSON.stringify({
25 query: "你好",
26 employeeId: "1omFAG5XYjrkJWdr8hC7",
27 instanceId: instanceId,
28 robotId: "3a1c45a670d949239af524dc3c2668c2",
29 enableSlotFillCard: 1,
30 isComplete: 1
31 })
32 });
33
34 // 5. 处理流式响应
35 eventSource.onmessage = function(event) {
36 const data = JSON.parse(event.data);
37 console.log('收到消息:', data.answer);
38
39 if (data.isEnd) {
40 console.log('对话结束');
41 eventSource.close();
42 }
43 };
5. Python完整示例 (conversation_client.py)
依赖安装:
Plain Text
1pip install aiohttp==3.9.0 websockets==12.0 requests==2.31.0
完整代码:
Plain Text
1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3"""
4数字员工对话客户端脚本
51. 获取访问凭证
62. 建立WebSocket心跳连接
73. 流式对话交互
84. 会话状态管理
9
10使用方法:
11python conversation_client.py
12
13功能特性:
14- 异步WebSocket心跳保活
15- SSE流式响应处理
16- 自动会话状态管理
17- 交互式命令行界面
18- 支持多轮对话上下文
19"""
20
21import aiohttp
22import asyncio
23import json
24import requests
25import sys
26import uuid
27import websockets
28from typing import Optional, Dict, Any
29
30
31class DigitalEmployeeClient:
32 """数字员工对话客户端"""
33
34 def __init__(self, base_url: str = "https://ky.cloud.baidu.com"):
35 self.base_url = base_url
36 self.employee_id = None
37 self.instance_id = None
38 self.authorization = None
39 self.session_id = None
40 self.robot_id = None
41 self.websocket = None
42 self.heartbeat_task = None # 保存心跳任务引用
43
44 async def get_access_token(self, employee_id: str) -> bool:
45 """获取访问凭证"""
46 try:
47 url = f"{self.base_url}/employee-console/v1/access/r/ai-agent/token/{employee_id}"
48
49 async with aiohttp.ClientSession() as session:
50 async with session.get(url) as response:
51 if response.status == 200:
52 data = await response.json()
53 if data.get("code") == "employee-console_ok":
54 self.employee_id = employee_id
55 self.authorization = data["data"]["authorization"]
56 self.instance_id = data["data"]["instanceId"]
57 print(f"✓ 获取访问凭证成功")
58 print(f" 实例ID: {self.instance_id}")
59 return True
60
61 print(f"✗ 获取访问凭证失败: {response.status}")
62 return False
63
64 except Exception as e:
65 print(f"✗ 获取访问凭证异常: {e}")
66 return False
67
68 async def connect_websocket(self) -> bool:
69 """建立WebSocket心跳连接"""
70 if not self.employee_id or not self.instance_id:
71 print("✗ 缺少必要参数,请先获取访问凭证")
72 return False
73
74 try:
75 ws_url = f"wss://ky.cloud.baidu.com/employee-console/v1/access/w/ai-agent/keepalive-pool/{self.employee_id}/{self.instance_id}"
76 self.websocket = await websockets.connect(ws_url)
77 print("✓ WebSocket连接建立成功")
78
79 # 启动心跳任务并保存引用
80 self.heartbeat_task = asyncio.create_task(self._heartbeat())
81 print("✓ 心跳任务已启动")
82 return True
83
84 except Exception as e:
85 print(f"✗ WebSocket连接失败: {e}")
86 return False
87
88 async def _heartbeat(self):
89 """维持心跳连接"""
90 try:
91 while self.websocket and not self.websocket.closed:
92 # 发送心跳
93 await self.websocket.send("ping")
94
95 # 尝试接收服务端消息
96 try:
97 message = await asyncio.wait_for(self.websocket.recv(), timeout=0.1)
98 except asyncio.TimeoutError:
99 pass # 没有消息是正常的
100
101 # 等待1秒
102 await asyncio.sleep(1)
103
104 print("x 心跳保活终止")
105 except Exception as e:
106 print(f"✗ 心跳停止: {e}")
107
108 async def send_query(self, query: str, robot_id: str) -> None:
109 """发送对话请求并处理流式响应"""
110 if not self.employee_id or not self.instance_id:
111 print("✗ 缺少必要参数,请先获取访问凭证和建立连接")
112 return
113
114 # 保存robot_id供后续使用
115 if robot_id:
116 self.robot_id = robot_id
117
118 query_id = str(uuid.uuid4())
119
120 payload = {
121 "query": query,
122 "queryId": query_id,
123 "employeeId": self.employee_id,
124 "instanceId": self.instance_id,
125 "robotId": robot_id,
126 "sessionId": self.session_id or "",
127 "enableContactCard": 0,
128 "enableSlotFillCard": 1,
129 "isComplete": 1
130 }
131
132 try:
133 url = f"{self.base_url}/employee-console/v1/open/aiob-server/text/stream/query"
134 headers = {"Content-Type": "application/json"}
135
136 async with aiohttp.ClientSession() as session:
137 async with session.post(url, json=payload, headers=headers) as response:
138 if response.status == 200:
139 answer_parts = []
140
141 async for line in response.content:
142 line = line.decode('utf-8').strip()
143
144 if line.startswith('data:'):
145 try:
146 json_str = line[5:] # 移除 'data:' 前缀
147 data = json.loads(json_str)
148
149 # 保存session_id供后续对话使用
150 if data.get('sessionId') and not self.session_id:
151 self.session_id = data['sessionId']
152 print(f"✓ 会话ID: {self.session_id}")
153
154 # 收集回复内容
155 if 'answer' in data and data['answer']:
156 answer_parts.append(data['answer'])
157 print(data['answer'], end='', flush=True)
158
159 # 检查是否结束
160 if data.get('isEnd', False):
161 print() # 换行
162 break
163
164 except json.JSONDecodeError:
165 continue
166 else:
167 print(f"✗ 请求失败: {response.status} {response.text}")
168
169 except Exception as e:
170 print(f"✗ 发送请求异常: {e}")
171
172 async def close(self):
173 """关闭连接"""
174 # 停止心跳任务
175 if self.heartbeat_task and not self.heartbeat_task.done():
176 self.heartbeat_task.cancel()
177 try:
178 await self.heartbeat_task
179 except asyncio.CancelledError:
180 pass
181 print("✓ 心跳任务已停止")
182
183 # 关闭WebSocket连接
184 if self.websocket:
185 await self.websocket.close()
186 print("✓ WebSocket连接已关闭")
187
188
189async def async_input(prompt: str = "") -> str:
190 """异步输入函数,避免阻塞事件循环"""
191 print(prompt, end='', flush=True)
192 loop = asyncio.get_event_loop()
193 return await loop.run_in_executor(None, sys.stdin.readline)
194
195
196async def main():
197 """主函数 - 交互式对话"""
198 print("=" * 50)
199 print("数字员工对话客户端")
200 print("=" * 50)
201
202 client = DigitalEmployeeClient()
203
204 # 获取用户输入的配置 (初始化时使用同步输入)
205 employee_id = input("请输入员工ID (例如: Hnh4hDWKh1uAoFDgQIUZ): ").strip()
206 robot_id = input("请输入机器人ID (例如: e9f4dc51440f45c99b9ed9adcaa642ac): ").strip()
207
208 if not employee_id or not robot_id:
209 print("✗ 员工ID和机器人ID不能为空")
210 return
211
212 # 1. 获取访问凭证
213 print("\n1. 获取访问凭证...")
214 if not await client.get_access_token(employee_id):
215 return
216
217 # 2. 建立WebSocket连接
218 print("\n2. 建立WebSocket连接...")
219 if not await client.connect_websocket():
220 return
221
222 # 3. 开始对话
223 print("\n3. 开始对话 (输入 'quit' 或 'exit' 退出)")
224 print("-" * 50)
225
226 # 发送开场白 (空query)
227 print("\n机器人: ", end='')
228 await client.send_query("", robot_id)
229
230 try:
231 while True:
232 # 使用异步输入,不阻塞心跳
233 query = await async_input("\n用户: ")
234 query = query.strip()
235
236 if query.lower() in ['quit', 'exit', '退出']:
237 break
238
239 if query:
240 print("机器人: ", end='')
241 await client.send_query(query, robot_id)
242
243 except KeyboardInterrupt:
244 print("\n\n✓ 用户中断对话")
245 finally:
246 await client.close()
247
248
249if __name__ == "__main__":
250 # 安装依赖提示
251 try:
252 import aiohttp
253 import websockets
254 except ImportError:
255 print("请先安装依赖包:")
256 print("pip install aiohttp websockets")
257 exit(1)
258
259 asyncio.run(main())
