架构概述
架构概述
系统架构
text
┌─────────────────────────────────────────────────────────────────────────────────────────────────┐
│ 灵心平台 (LinkSoul Platform) │
│ │
│ ┌─────────────────────┐ Bridge (桥接器) ┌─────────────────────┐ │
│ │ LinkskyGateway │ ◄──────────────────────────────► │ 交互网关 (Gateway) │ │
│ │ (二开网关) │ Boss Channel (控制面) │ │ │
│ │ 接收二开SDK连接 │ Worker Channel (数据面) │ 连接机器人终端 │ │
│ │ 认证 & 消息路由 │ 双向信令握手 │ 音频/视频/指令转发 │ │
│ └──────────┬──────────┘ └──────────┬──────────┘ │
│ │ │ │
└─────────────│────────────────────────────────────────────────────────│─────────────────────────┘
│ │
│ WebSocket (wss) │ WebSocket / TCP
│ wss://open.agibot.com/api/V1/open-portal/app/wss/agent-sdk │
│ │
┌─────────────▼──────────────┐ ┌────────────▼─────────────┐
│ 您的二开应用 (AgentSdk) │ │ 机器人终端 / 智能体 │
│ │ │ │
│ ┌──────────────────────┐ │ │ ┌────────────────────┐ │
│ │ LinkskyClient │ │ │ │ 音频采集 (MIC) │ │
│ │ (Netty WebSocket) │ │ │ │ 视频采集 (Camera) │ │
│ └──────────┬───────────┘ │ │ │ TTS 播放 (Speaker) │ │
│ │ │ │ │ 动作执行 (Motor) │ │
│ ┌──────────▼───────────┐ │ │ └────────────────────┘ │
│ │ MsgHandler │ │ └──────────────────────────┘
│ │ (被动消息分发) │ │
│ ├──────────────────────┤ │
│ │ ActiveMsgHandler │ │
│ │ (主动消息分发) │ │
│ └──────────┬───────────┘ │
│ │ │
│ ┌──────────▼───────────┐ │
│ │ PassiveCallbacks │ │ 被动交互:机器人发起 → 二开处理 → 返回结果
│ │ (8种回调实现) │ │ Audio → ASR → LLM → TTS
│ ├──────────────────────┤ │
│ │ ActiveRequests │ │ 主动交互:二开发起 → 网关转发 → 机器人响应
│ │ (任务流 TaskFlow) │ │ registerTaskFlow / startRequest / taskRequest / endRequest
│ └──────────────────────┘ │
└────────────────────────────┘
数据流向
被动交互(机器人 → 二开SDK)
text
机器人麦克风 → 交互网关 → Bridge Worker → LinkskyGateway(二开网关) → AgentSdk → Callback.onRequest()
│
Callback返回 → AgentSdk → LinkskyGateway(二开网关) → Bridge Worker → 交互网关 → 机器人扬声器
主动交互(二开SDK → 机器人)
text
AgentSdk.registerTaskFlow() → LinkskyGateway(二开网关) → Bridge Boss → 交互网关 → 机器人
│
机器人响应 → 交互网关 → Bridge Boss → LinkskyGateway(二开网关) → AgentSdk → Callback.onResponse()
Bridge 桥接器
桥接器是二开网关与交互网关之间的通信枢纽:
| 通道 | 方向 | 职责 |
|---|---|---|
| Boss Channel | 控制面 | Agent 注册/注销、callId 广播、信令同步 |
| Worker Channel | 数据面 | 音频/视频/ASR/TTS 数据转发、状态同步 |
- 每对网关之间建立 Boss + Worker 两条 WebSocket 连接
- 通过 ZooKeeper 服务发现,自动感知网关实例上下线
- 使用
CountDownGate(2)确保双通道就绪后才开始消息转发 - 支持集群部署,多个二开网关实例可同时服务
模块结构
text
com.agibot.aiem.sdk/
├── AgentSdk.java # 主入口(单例工厂、回调注册、生命周期)
├── AgentParam.java # 类型安全的参数包装器
├── AgentMeta.java # 智能体元数据
├── AgentAuthCallback.java # 认证回调接口
├── IdGenerator.java # ID生成器
├── client/
│ ├── LinkskyClient.java # Netty WebSocket客户端
│ ├── LinkskyClientInboundHandler.java # 消息分发
│ ├── MsgHandler.java # 被动消息处理
│ └── ActiveMsgHandler.java # 主动消息处理
├── enums/ # 枚举定义
├── passive/ # 被动交互(8种Callback + Response,以及 GreetResponse 等基类共享方法)
├── active/ # 主动交互(任务流 TaskFlowRequest)
├── mgr/ # 管理器(回调类型、响应缓存、线程池)
└── delayed/ # 延迟任务(心跳超时检测)
通信协议
连接认证
HTTP Header:
AGIBOT_APP_ID: 应用IDAGIBOT_AUTHORIZATION:Bearer <JWT Token>
JWT Payload: { "appId": "xxx", "callbackTypes": "[\"audio2llm\"]" }
消息格式 (JSON)
json
{
"type": "agentsdk.audio_request.start",
"agentId": "AGENT_0000001",
"eventId": "event_xxxxx",
"robotCid": "cid_xxx",
"cid": "cid_xxx"
}
线程模型
- Netty EventLoop (1线程): WebSocket I/O
- AgentThreadPool: 每个
agentId(灵心平台配置的智能体 ID)绑定一个工作线程,保证同一智能体消息顺序处理- 核心线程: 3
- 最大线程: 50
- 空闲超时: 300秒
- DelayedPool (2线程): 心跳超时检测
- 清理定时器 (10秒): 清理过期的响应/回调缓存
重连机制
- 连接失败/断开后自动重连
- 重连延迟: 3秒
- 无限重连(直到调用
AgentSdk.release(appId)) - 心跳: 每10秒发送 Ping
典型时序
下面以 Audio2Tts(音频输入 → ASR + LLM + TTS 全管道)为例展示一次完整对话的时序。
其他被动回调只是 onRequest 收到的数据形态不同,整体节奏一致。
mermaid
sequenceDiagram
participant Robot as 机器人
participant IGW as 交互网关
participant Bridge as Bridge 桥接器
participant Linksky as LinkskyGateway<br/>(二开网关)
participant SDK as AgentSdk<br/>(二开应用)
Note over SDK,Linksky: 启动阶段
SDK->>Linksky: WebSocket 连接 + JWT 鉴权
Linksky-->>SDK: onAuthState(code=0)
Robot->>IGW: 机器人上线
IGW->>Bridge: 上线事件
Bridge->>Linksky: 上线事件
Linksky-->>SDK: onRobotOnline(agentId, agentMeta)
Note over Robot,SDK: 一次对话
Robot->>IGW: 用户开始说话 (VAD start)
IGW->>Bridge: audio_request.start
Bridge->>Linksky: 转发
Linksky-->>SDK: onRequest(flag=0)
loop 音频帧
Robot->>IGW: PCM 音频帧
IGW->>Linksky: audio_request.append
Linksky-->>SDK: onRequest(flag=1, buf=audio)
end
Robot->>IGW: VAD end
IGW->>Linksky: audio_request.commit
Linksky-->>SDK: onRequest(flag=2)
Note over SDK: 业务侧 ASR → LLM → TTS
SDK->>Linksky: response.onAsrMiddle / onAsrFinal
Linksky->>IGW: ASR 文本
IGW->>Robot: 屏幕显示
SDK->>Linksky: response.onLlmItemDelta × N
SDK->>Linksky: response.onLlmItemDone / onLlmDone
Linksky->>IGW: LLM 文本流
IGW->>Robot: 屏幕显示
SDK->>Linksky: response.onSkill(技能指令)
Linksky->>IGW: 技能指令
IGW->>Robot: 执行技能
SDK->>Linksky: response.onTtsItemDelta × N
SDK->>Linksky: response.onTtsItemDone / onTtsDone
Linksky->>IGW: TTS 音频
IGW->>Robot: 扬声器播放
关键点:
- 一次对话的整个生命周期通过
eventId关联,跨多次onRequest/response.on*调用都共用同一个eventId。 - ASR/LLM/VLM/TTS 都是流式输出,可以多次
*Delta,最后用*Done收尾。 - 技能下发
response.onSkill(...)与文本/音频输出可以并行,互不阻塞;具体可下发的技能见 语义技能参考。 - 业务侧异常时调用
response.onError(eventId, code, msg)通知机器人端。