Files

399 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# LineUp Agents v1 — 设计方案
**版本:** v1.1(第二版)
**最后更新:** 2026-07-27
---
## 一、产品定位
LineUp Agents 是一个**远程 Agent 操作交互端**。用户通过手机或 Web App,与运行在本地或服务器上的 AI Agent 进行顺畅的交互。不是任务管理系统,Agent 的任务拆解、执行、管理属于 Agent 自己的工作范畴。
### MVP 范围
| 做 | 不做 |
|----|------|
| App 直连 Agent(局域网 WebSocket| 任务生命周期管理 |
| 通过 IM 中转连接 Agent(远程)| 自动化编排、调度 |
| App 收发消息、查看 Agent 状态 | 通知推送 |
| Agent 调 App 的工具(choice / 画板 / 计算器 等)| MCP 封装 |
| 工具发现与调用协议 | 多 Agent 工作流编排 |
| 用户 ↔ 用户基础通信(由 IM 平台提供)| 端到端加密(后续加) |
---
## 二、核心设计原则
**LineUp 协议只定义工具交互,不定义基础消息。**
这条原则是整个设计的关键。工具相关的内容(`tool.call``tool.result``tool.list`)由 LineUp 协议定义。文本、图片、语音、文件等基础消息,由下层传输平台(IM 服务或 WebSocket)原生处理,LineUp 不重复定义。
这让协议非常薄,换传输平台时工具协议不受影响。
---
## 三、架构总览
### 3.1 两种网络模式
LineUp 支持两种连接模式,插件根据配置自动切换。
**直连模式(局域网)**
```
Agent 插件 ── WebSocket 端口 :9527 ──→ App 端(Web
```
Agent 插件在本地开 WebSocket ServerApp 端手动输入 IP:端口连接。适合局域网内无公网 IP 的场景。
**中转模式(广域网)**
```
Agent 适配器 ──→ WuKongIM ←── 唐僧叨叨客户端 / LineUp App
│ Webhook / HTTP API
唐僧叨叨业务服务
```
WuKongIM 负责客户端长连接、消息投递和消息存储;唐僧叨叨业务服务负责用户、好友、群组、文件等 IM 业务能力,并通过 Webhook 与 WuKongIM 协作。客户端以 WuKongIM 官方 SDK 建立长连接,以唐僧叨叨 API 处理业务操作。LineUp 的中转适配器需使用 WuKongIM 官方 SDK 或经验证的协议实现,不能复用其他 IM 平台的网关协议。
### 3.2 分层架构
```
┌──────────────────────────────────────────────┐
│ 工具协议层(LineUp 定义) │
│ 内容:工具定义、tool.call / tool.result │
│ App 渲染 choice / canvas / calculator 等工具 │
├──────────────────────────────────────────────┤
│ 消息传输层(IM 平台或直连 WebSocket
│ 内容:文本 / 图片 / 文件 / 语音的收发 │
│ 直连模式:WebSocket 原生传输 │
│ 中转模式:WuKongIM 消息通道传输 │
├──────────────────────────────────────────────┤
│ 连接层(IM 平台或 WebSocket Server
│ 内容:连接建立、心跳保活、断线重连 │
│ 直连模式:Agent 插件 WS Server │
│ 中转模式:WuKongIM 连接管理 │
└──────────────────────────────────────────────┘
```
LineUp 协议只关心最上面一层。下面两层由传输平台处理。
### 3.3 设计决策
| 决策 | 当期结论 | 后续扩展思路 |
|------|---------|-------------|
| 网络模式 | 局域网直连 + WuKongIM 中转并存 | — |
| 中转服务 | 唐僧叨叨业务层 + WuKongIM 通讯层 | — |
| Agent 接入方式 | 直连模式用 LineUp 适配器;中转模式待基于 WuKongIM SDK 实现 | — |
| IM 平台选型 | WuKongIM;唐僧叨叨提供配套业务层和客户端 | — |
| App 端技术方向 | Vite + React(直连模式用 WebSocket;中转模式使用 WuKongIM JS SDK / 唐僧叨叨 API | 原生移动端 App |
| 连接认证 | 直连:预共享 Token;中转:唐僧叨叨用户系统与 WuKongIM Token | 端到端加密 |
| 工具路由方式 | 字典路由 | 可引入框架级路由 |
---
## 四、工具协议定义(LineUp 协议的全部内容)
LineUp 协议只定义工具相关的三个消息类型。
### 4.1 工具定义结构
所有工具使用统一的结构模板,通过 `type` 区分行为差异。
| type | 含义 | 定义结构 |
|------|------|---------|
| `app` | 有状态应用,有生命周期 | `{ name, type, description, actions[] }` |
| `toolset` | 无状态工具集,多个动作 | `{ name, type, description, actions[] }` |
| `action` | 单指令工具,一个动作 | `{ name, type, description, inputSchema }` |
### 4.2 三类工具的完整定义
#### type: app — 有状态应用
```json
{
"name": "canvas",
"type": "app",
"description": "画板应用,支持绘制、撤销、清空等操作",
"actions": [
{
"name": "open",
"description": "创建画板实例,返回 instance_id",
"inputSchema": {
"type": "object",
"properties": {
"width": { "type": "integer", "description": "画板宽度" },
"height": { "type": "integer", "description": "画板高度" }
},
"required": ["width", "height"]
}
},
{
"name": "draw",
"description": "在画板上绘制路径",
"inputSchema": {
"type": "object",
"properties": {
"instance_id": { "type": "string", "description": "画板实例 ID" },
"path": { "type": "string", "description": "SVG 路径数据" },
"color": { "type": "string", "description": "线条颜色" },
"width": { "type": "integer", "description": "线条粗细" }
},
"required": ["instance_id", "path"]
}
},
{
"name": "undo",
"description": "撤销上一步操作",
"inputSchema": {
"type": "object",
"properties": {
"instance_id": { "type": "string", "description": "画板实例 ID" }
},
"required": ["instance_id"]
}
},
{
"name": "clear",
"description": "清空画板内容",
"inputSchema": {
"type": "object",
"properties": {
"instance_id": { "type": "string", "description": "画板实例 ID" }
},
"required": ["instance_id"]
}
},
{
"name": "close",
"description": "关闭画板释放资源",
"inputSchema": {
"type": "object",
"properties": {
"instance_id": { "type": "string", "description": "画板实例 ID" }
},
"required": ["instance_id"]
}
}
]
}
```
#### type: toolset — 无状态工具集
```json
{
"name": "calculator",
"type": "toolset",
"description": "基础计算器,无状态,每次调用独立",
"actions": [
{
"name": "add",
"description": "两个数相加",
"inputSchema": {
"type": "object",
"properties": {
"a": { "type": "number" },
"b": { "type": "number" }
},
"required": ["a", "b"]
}
},
{
"name": "subtract",
"description": "两个数相减",
"inputSchema": {
"type": "object",
"properties": {
"a": { "type": "number" },
"b": { "type": "number" }
},
"required": ["a", "b"]
}
},
{
"name": "multiply",
"description": "两个数相乘",
"inputSchema": {
"type": "object",
"properties": {
"a": { "type": "number" },
"b": { "type": "number" }
},
"required": ["a", "b"]
}
},
{
"name": "divide",
"description": "两个数相除",
"inputSchema": {
"type": "object",
"properties": {
"a": { "type": "number" },
"b": { "type": "number" }
},
"required": ["a", "b"]
}
}
]
}
```
#### type: action — 单指令工具
```json
{
"name": "choice",
"type": "action",
"description": "向用户提供一组选项让其选择",
"inputSchema": {
"type": "object",
"properties": {
"question": { "type": "string", "description": "问题描述" },
"options": { "type": "array", "items": { "type": "string" }, "description": "可选列表" }
},
"required": ["question", "options"]
}
}
```
### 4.3 三类工具对比
| | app | toolset | action |
|--|-----|---------|--------|
| 定义结构 | name + type + description + actions[] | name + type + description + actions[] | name + type + description + inputSchema |
| 适用场景 | 需要维护内部状态的应用 | 多个独立功能可归类 | 单个独立功能 |
| 生命周期 | open → use → close | 无 | 无 |
| instance_id | 需要 | 不需要 | 不需要 |
| 每次调用需 action | 是 | 是 | 仍需 action 字段 |
| 示例 | canvas(画板) | calculator(计算器) | choice / confirm / input |
### 4.4 tool.call 消息格式
```json
{
"call_id": "c1",
"name": "canvas",
"action": "open",
"arguments": { "width": 800, "height": 600 }
}
```
字段说明:
- `call_id` — 调用方生成,唯一标识一次调用,用于 tool.result 配对
- `name` — 工具名
- `action` — 动作名(app 和 toolset 类型必填,action 类型可省略)
- `arguments` — 动作的参数,按 inputSchema 结构传入
### 4.5 tool.result 消息格式
```json
{
"call_id": "c1",
"name": "canvas",
"action": "open",
"result": {
"message": "instance_id: inst_001"
}
}
```
字段说明:
- `call_id` — 与 tool.call 中的 call_id 一致,用于配对
- `name` — 工具名
- `action` — 动作名
- `result` — 返回数据,约定统一放在 result.message,后续按工具定义扩展
### 4.6 tool.list 消息
```json
{
"tools": [
{ "name": "choice", "type": "action", "description": "...", "inputSchema": {} },
{ "name": "calculator", "type": "toolset", "description": "...", "actions": [] },
{ "name": "canvas", "type": "app", "description": "...", "actions": [] }
]
}
```
设备注册和查询工具列表用统一的数据结构。直连模式下双向可查,中转模式下 App 端通过自定义消息类型注册工具。
---
## 五、完整交互流程
### 5.1 choice 工具调用
```
Agent 需要用户做选择
├── Agent 发 tool.call
│ { call_id: "c1", name: "choice", action: "select",
│ arguments: { question: "部署到哪个环境?", options: ["测试", "预发布", "生产"] } }
├── App 渲染选择界面,用户点击"预发布"
├── App 返回 tool.result
│ { call_id: "c1", name: "choice", action: "select",
│ result: { message: "预发布" } }
└── Agent 拿到结果,继续执行
```
### 5.2 canvas 完整生命周期
Agent 调 `canvas``open` 动作:
```json
{ "call_id": "c1", "name": "canvas", "action": "open", "arguments": { "width": 800, "height": 600 } }
```
App 返回 instance_id
```json
{ "call_id": "c1", "name": "canvas", "action": "open", "result": { "message": "instance_id: inst_001" } }
```
Agent 绘制路径:
```json
{ "call_id": "c2", "name": "canvas", "action": "draw", "arguments": { "instance_id": "inst_001", "path": "M10 10 L50 50", "color": "red" } }
```
Agent 关闭画板:
```json
{ "call_id": "c3", "name": "canvas", "action": "close", "arguments": { "instance_id": "inst_001" } }
```
---
## 六、与 MCP 的关系
```
MCP LineUp
───────────────────────────────────────
MCP Server ──────────────── Tool(画板 / 计算器 / 选择框)
│ │
├─ MCP Tool A ├─ Actionopen / draw / add / select
├─ MCP Tool B ├─ Action
└─ MCP Tool C └─ Action
```
Tool = MCP Server 层,Action = MCP Tool 层。Action 才是实际可调用的最小能力单元。
工具定义格式复用 MCP 的 JSON Schema 标准。
---
## 七、后续可能的扩展
- 端到端加密,中转不可读消息内容
- 移动端原生 App(目前用响应式 Web)
- 直连模式切换到中转模式时的无缝过渡
- 更多 Agent 框架的插件支持(目前以 Hermes 为第一期)
- 框架级工具路由替代字典路由