前置:第 01 篇。本篇不需要真机,用文本即可跑通全流程。
一、凭证与验签
云端开发的第一步是拿到凭证:登录灵心开放平台 → 进入「应用」页面 → 创建应用。
| 凭证 | 用途 |
|---|---|
app_id |
应用标识 |
app_key |
参与 HMAC-SHA256 签名 |
app_secret |
签名密钥 |
1 | export AGIBOT_APP_ID="app_xxxxxxxx" |
⚠️
app_key与app_secret用于网关签名,不得写进可公开的代码或日志。生产环境走环境变量或密钥管理服务。
二、v1.4.0 的不兼容升级
这是上手前必须确认的一件事:v1.4.0 与 v1.3.0 及更早版本不兼容。
| 项目 | v1.3.0 及更早 | v1.4.0 |
|---|---|---|
| 鉴权机制 | JWT(AGIBOT_AUTHORIZATION 头) |
HMAC-SHA256 五元组请求头 |
| 请求头 | 1 个 | X-App-Id / X-App-Key / X-Timestamp / X-Nonce / X-Signature |
| 凭证来源 | 二开智能体模板 | 灵心开放平台「应用」 |
create() 签名 |
create(url, app_id, app_secret) |
create(url, app_id, app_key, app_secret) |
| 网关地址 | wss://agentsdk.agibot.com/v1/agentsdk |
wss://open.agibot.com/api/V1/open-portal/app/wss/agent-sdk |
| 回调类型 | JWT payload 字段 | 独立请求头 X-Callback-Types(JSON 数组字符串) |
1 | from linksoul_agentsdk import AgentSdk |
安装:linksoul_agentsdk 目前未发布到公共 PyPI,需从官方获取离线分发包后本地安装:
1 | pip install ./linksoul_agentsdk-1.4.0a0-py3-none-any.whl |
依赖 websocket-client>=1.7.0 会自动拉取。版本号 1.4.0a0 是 PEP 440 的 alpha 预发布标识,与 Java SDK 的 1.4.0-SNAPSHOT 语义对齐。
三、生命周期与运行时约束
3.1 四步初始化,顺序不可颠倒
必须先 register_*() 再 initialize()。顺序反了回调不会生效,且不会报错——这类静默失败排查成本很高。
3.2 线程模型决定了代码怎么写
| 线程 | 数量 | 职责 |
|---|---|---|
linksky-recv-<app_id> |
1 | WebSocket 接收线程 |
agent-worker-N |
1..50 | 每个 agent_id 绑定一个串行 worker |
threading.Timer daemon |
0..1 | 重连定时器 |
三条直接约束:
- 同一
agent_id的请求是串行的。on_request阻塞多久,该智能体的后续消息就积压多久。 response.on_*可在任意线程安全调用(内部用threading.Lock串行化)。- 回调是单例,所有上线的智能体共享同一实例。不能用全局变量存会话状态——必须按
agent_id分桶。
⚠️ 结论:
on_request内禁止同步阻塞(长时间sleep、同步 HTTP 调用)。需要等待结果时用线程池,回调立即返回。第 05 篇会看到官方 demo 恰好在这里踩了坑。
3.3 重连
- 连接失败 / 断开后自动重连,默认延迟 3 秒(构造时可覆盖)
- 默认无限重连(
max_reconnect_attempts=-1),直到调用agent_sdk.release() - 心跳:每 10 秒 Ping(websocket-client 内置)
四、8 种被动回调的选型
被动交互是 SDK 的核心能力:机器人发起(音频 / 视频 / 文本)→ 回调处理 → 通过 Response 返回结果。
按”输入 × 输出”组合共 8 种:
| 类别 | 回调类 | 输入 | 输出 |
|---|---|---|---|
| 纯音频 | Audio2LlmCallback |
音频流 | ASR + LLM 文本 |
Audio2TtsCallback |
音频流 | ASR + LLM + TTS | |
| 纯文本 | Asr2LlmCallback |
ASR 文本 | LLM 文本 |
Asr2TtsCallback |
ASR 文本 | LLM + TTS | |
| 多模态 | AsrVideo2VlmCallback |
ASR 文本 + 视频 | VLM 文本 |
AsrVideo2TtsCallback |
ASR 文本 + 视频 | VLM + TTS | |
AudioVideo2VlmCallback |
音频 + 视频 | ASR + VLM 文本 | |
AudioVideo2TtsCallback |
音频 + 视频 | ASR + VLM + TTS |
选型是一条三步判断链:
取舍:本系列选
Asr2LlmCallback。ASR 在端侧完成,云端只处理文本——链路最短、延迟最低、调试最直观。代价是云端拿不到音频原始特征(情绪、语速、停顿),需要这些时应改用Audio2Llm。
v1.4.0 变更:
Audio2Asr/Audio2Audio/AudioVideo2Audio/Text2Tts四种回调及其 Response 类已从 SDK 删除。
五、flag 与标准响应流程
5.1 flag:区分同一回调中的不同数据
音频类回调(Audio2*、AudioVideo2*):
| flag | 含义 | buf |
触发时机 |
|---|---|---|---|
0 |
VAD 开始 | None |
用户开始说话 |
1 |
音频帧 | PCM bytes |
持续传输中 |
2 |
VAD 结束 | None |
用户停止说话 |
3 |
H264 视频帧 | H264 字节 | 视频流传输 |
AsrVideo2* 类:
| flag | 含义 | 有效参数 |
|---|---|---|
3 |
ASR 文本 | text 有效,buf=None |
4 |
H264 视频帧 | buf 有效,text=None |
5 |
图片帧 | buf 有效,text=None |
AsrVideo2*的on_request会被多次调用(分别传文本与视频),必须按flag分派。
5.2 标准响应流程
5.3 Response 方法矩阵
| Response 类 | ASR | LLM | VLM | TTS | Skill | Interrupt |
|---|---|---|---|---|---|---|
Audio2LlmResponse |
✓ | ✓ | ✓ | ✓ | ||
Audio2TtsResponse |
✓ | ✓ | ✓ | ✓ | ✓ | |
Asr2LlmResponse |
✓ | ✓ | ✓ | |||
Asr2TtsResponse |
✓ | ✓ | ✓ | ✓ | ||
AsrVideo2VlmResponse |
✓ | ✓ | ✓ | |||
AsrVideo2TtsResponse |
✓ | ✓ | ✓ | ✓ | ||
AudioVideo2VlmResponse |
✓ | ✓ | ✓ | ✓ | ||
AudioVideo2TtsResponse |
✓ | ✓ | ✓ | ✓ | ✓ |
常用方法:
| 方法 | 说明 |
|---|---|
on_llm_item_delta(event_id, item_id, text) |
LLM 流式输出(增量) |
on_llm_item_done(event_id, item_id) |
LLM 单段完成 |
on_llm_done(event_id) |
LLM 全部完成 |
on_skill(event_id, item_id, skill_type, skill_name, param) |
下发技能 |
on_interrupt(event_id, type, tips) |
打断当前对话 |
on_error(event_id, code, msg) |
错误上报(所有 Response 均支持) |
六、打断与拒识
这两条是最容易写错、且错误后果最严重的部分。
6.1 打断顺序是硬约束
⚠️ 一旦判定为有效指令,必须先调用
on_interrupt,之后才能调用on_skill/on_llm_*/on_vlm_*/on_tts_*。顺序颠倒会导致机器人无法正确进入新一轮应答状态。
interrupt_type 四种取值:
| 取值 | 语义 | 场景 | interrupt_tips |
|---|---|---|---|
risk_control |
风控打断 | 内容违规、敏感话题 | 必填,作为给用户的话术 |
action |
技能打断 | 命中技能 / 动作 | 传 None |
chat |
有效闲聊打断 | 命中普通对话 | 传 None |
realtime |
实时对话打断 | 边听边说场景 | 传 None |
6.2 拒识:一个都不调用
拒识(误唤醒、噪音、无效查询)的正确处理是完全不调用任何 response.on_*:不返回技能、不调用 on_interrupt、不返回 LLM / VLM 结果,让机器人保持当前状态。
常见错误:对任意输入都回一句”我收到你的话:xxx”。这等于把噪音当成有效对话,会让机器人对着环境噪音自言自语。
6.3 分类决策表
| 语义理解结果 | 第一步 | 之后允许的应答 |
|---|---|---|
| 命中风控 | on_interrupt(..., "risk_control", "<话术>") |
一般不再返回 LLM / VLM / 技能 |
| 命中技能 | on_interrupt(..., "action", None) |
on_skill(...),可并行 on_llm_* |
| 命中有效闲聊 | on_interrupt(..., "chat", None) |
on_llm_* / on_vlm_* / on_tts_* |
| realtime 对话 | on_interrupt(..., "realtime", None) |
realtime 应答内容 |
| 拒识 | 不调用 | 一个都不调用 |
七、语义技能
技能是 ASR 文本经语义理解分类后的一种结果分支,通过 on_skill(event_id, item_id, skill_type, skill_name, skill_param) 下发。skill_param 的键值对即为”语义”。
| 类别 | 示例语义 |
|---|---|
| 动作(action) | {"action":"wave_hands"}、{"action":"cheer","hand":"left"}、{"action":"blow_kiss"}、{"action":"hug"}、{"action":"dance"}、{"action":"taichi"} |
| 移动(movement) | {"movement":"move_forward"}、{"movement":"move_forward","meter":10}、{"movement":"turn_left","angle":30}、{"movement":"run"} |
| 表情(expression) | {"expression":"smile"}、{"expression":"cry"}、{"expression":"heart_eyes"} |
| 状态控制(status) | {"status":"freeze"}(停止行走)、{"status":"hush"}(退出) |
| 二次确认(confirmation) | {"confirmation":"yes"}、{"confirmation":"no"} |
| 技能问答 | {"action":"sing","genre":"children"}、{"action":"play_music","song":"小星星"} |
⚠️ 平台过滤机制:上表是平台设计能力的全集。端侧不同型号 / 系统版本支持的子集可能不同,但二开侧无需关心——按语义结果直接下发即可,平台会按目标机型与技能清单过滤:
- 命中且端侧支持 → 正常执行
- 命中但端侧不支持 → 平台向端侧返回
unknown,端侧按”不支持”处理
多意图:同一 event_id 下可多次调用 on_skill,每个意图使用独立 item_id。”先跳个舞再比个心”就是两次 on_skill。
⚠️ 部分移动类技能(
move_backward、move_left、move_right、continuous持续行走)需要二次确认。文档在技能表中已标注,实现时必须先走confirmation流程。
八、最小云端 Agent
1 | #!/usr/bin/env python3 |
这份代码固化了四条规范:
- 拒识分支不调用任何
response.on_* - 有效指令先
on_interrupt,再回填技能 / 文本 - 技能与文本并行下发,互不阻塞
- 凭证从环境变量读取
九、故障对照表
| 现象 | 根因 | 处理 |
|---|---|---|
| 连接建立瞬间被服务端关闭 | 使用旧网关,或 create() 缺少 app_key |
换新网关 + 四参调用 |
| 握手 401 / 403 | 凭证不同源;本机时钟偏差过大;代理未透传 5 个 X-* 头 |
核对凭证、date -u 对齐时钟、修代理 |
| 握手成功但回调不触发 | X-Callback-Types 缺失或格式错误(需 JSON 数组字符串) |
抓包确认该头存在且合法 |
AttributeError: register_state_listen |
v1.4.0 已移除该 API | 状态改用 on_state;主动交互只用 register_task_flow |
pip install linksoul_agentsdk 找不到包 |
未发布到公共 PyPI | 用离线 wheel 本地安装 |
| 机器人卡住、不响应后续消息 | on_request 内同步阻塞,卡死 per-agent worker |
改为线程池,回调立即返回 |
结论
- v1.4.0 是不兼容升级:HMAC-SHA256 五元组、新网关、四参
create()、X-Callback-Types头。 - 生命周期四步
create → register_auth → register_* → initialize,顺序不可颠倒,颠倒后静默失效。 - 同一
agent_id串行处理,on_request内禁止同步阻塞;回调是单例,状态必须按agent_id分桶。 - 8 种回调按”是否已 ASR / 是否要视频 / 是否要音频输出”三步选型。
- 有效指令必须先
on_interrupt;拒识一个response.on_*都不能调。 on_skill按语义全集下发即可,平台按机型过滤;多意图用独立item_id。
下一篇把端云接起来:拆解官方端云联合 demo,定位并修复其中 5 个致命缺陷,最终实现”一句话控制机器人做动作与导航”。
声明
本文首发智元AIMA开放平台,并在博客同步