架构设计
PicoAide 系统架构、设计哲学、组件边界和关键架构决策
设计哲学
PicoAide 的核心理念可以概括为一句话:
AI 的力量应当被释放,但数据的边界必须被守护。
这决定了 PicoAide 的架构走向——它不是一个直接把 AI 能力暴露给用户的管理工具,而是一个控制平面。所有 AI 操作都在明确定义的边界内执行:容器隔离了执行环境,认证继承了组织权限,MCP 中继控制了工具访问范围,文件白名单限制了数据读写。
PicoAide 不试图替代大模型或 Agent 框架。它解决的是企业在引入 AI 操作助手时面临的三个核心矛盾:
- 能力 vs 安全 — AI 需要操作真实环境才有价值,但操作权限必须精确可控
- 统一 vs 个性化 — 管理需要统一策略,但每位员工的工作场景各不相同
- 集成 vs 独立 — AI 需要接入浏览器、桌面、文件系统,但不能拥有不受限的访问权
系统总览
PicoAide 由一个 Go 服务端、多个用户级 PicoClaw 容器、浏览器扩展和桌面客户端组成。服务端不直接执行浏览器或桌面动作,而是作为认证、配置、容器和 MCP 消息的控制平面。
┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ 管理员/用户 │────▶│ PicoAide Server │────▶│ SQLite 配置存储 │
│ (浏览器) │ │ (Go + Gin) │ │ (用户/容器/配置) │
└──────────────┘ └────────┬─────────┘ └──────────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────────┐ ┌──────────┐
│ Docker │ │ MCP SSE │ │ WebSocket │
│ Engine │ │ 端点 │ │ 中继 │
└──────────┘ └──────┬───────┘ └─────┬────┘
│ │ │
▼ ▼ ▼
┌──────────┐ ┌──────────────┐ ┌──────────┐
│ PicoClaw │ │ 浏览器扩展 │ │ 桌面客户端 │
│ 容器×N │ │ (Chrome) │ │ (Python) │
└──────────┘ └──────────────┘ └──────────┘
五大设计决策
一、控制平面模式
PicoAide 不做 Agent 框架,不做大模型推理。它做一个清晰的控制平面——
- 认证:统一管理用户身份,支持 Local / LDAP / OIDC 三种模式
- 配置:在 SQLite 中存储全局配置,以 KV 键值对展平,分层合并下发
- 容器:通过 Docker SDK 管理用户容器生命周期
- 中继:MCP SSE + WebSocket 负责消息转发,不参与执行
这个边界带来的好处:PicoAide 不绑定任何大模型,不限定任何 Agent 框架。用户容器内跑什么 AI 软件由管理员决定,PicoAide 只负责供给和连接。
二、容器级隔离
每位员工拥有独立的 PicoClaw 容器。这不是为了性能,而是为了安全边界:
- 容器使用独立网络
picoaide-net(100.64.0.0/16),ICC=false 禁止容器间通信 - 用户工作目录通过 bind mount 挂载到容器
/root - 一个用户的 AI Agent 无法访问其他用户的容器或数据
- 删除用户时容器和目录会归档,不会留下残留
容器是"执行沙箱"——AI Agent 在里面运行,但它能调用的外部工具(浏览器、桌面)由 PicoAide 的 MCP 中继层控制。
三、认证可插拔
PicoAide 不创造新的身份体系,而是继承已有的。它支持三种认证模式:
| 模式 | 适用场景 | 用户来源 | 密码管理 |
|---|---|---|---|
| Local | 小团队、个人部署 | SQLite 本地用户 | argon2id 哈希,PicoAide 管理 |
| LDAP | 企业内网、AD/OpenLDAP | 目录服务器同步 | LDAP 服务器管理 |
| OIDC | SSO 平台、Keycloak/Azure AD | IdP 浏览器跳转 | IdP 管理 |
关键设计:超管逃生通道。无论哪种认证模式,超管账户始终在本地存储。即使 LDAP 服务器宕机或 OIDC Provider 不可用,管理员也能用本地超管密码登录系统。
切换认证模式时,系统会自动清理旧模式下的普通用户数据(容器、目录、组成员),确保状态一致。
四、MCP 三层中继
PicoAide 使用 Model Context Protocol(MCP)作为 AI 与外部工具的通信协议。架构分为三层:
用户 PicoClaw 容器 (AI Agent)
│
▼ SSE 连接 (MCP 协议)
┌───────────────────────────────┐
│ MCP Service 层 │
│ ─ initialize / tools/list │
│ ─ tools/call 路由到执行端 │
├───────────────────────────────┤
│ ServiceHub 层 │
│ ─ WebSocket 连接管理 │
│ ─ 命令转发 / 超时 / keepalive│
├───────────────────────────────┤
│ 代理层 (browser/computer) │
│ ─ 浏览器扩展 / 桌面客户端 │
└───────────────────────────────┘
- AI 通过 SSE 端点发送
tools/call请求 - PicoAide 服务端查找该用户已连接的 WebSocket 执行端
- 命令通过 WebSocket 转发到浏览器扩展或桌面客户端
- 执行端执行操作并返回结果
这种架构确保 AI 不直接接触用户的浏览器或桌面 API,所有操作都经过 PicoAide 的认证和路由。
五、配置分层下发
PicoAide 的配置体系采用分层策略:
全局配置 (SQLite settings 表)
│
├── Picoclaw 基础配置 (model, temperature...)
├── 渠道策略 (全局启用/禁用)
├── 安全配置 (.security.yml 中的密钥)
└── 技能仓库 (repos 定义)
│
▼
各用户配置合并 (util.MergeMap)
│
├── 用户级渠道覆盖 (启用/禁用)
├── 用户级配置字段
└── 组级技能绑定
│
▼
用户目录 config.json + .security.yml
配置以展平的键值对存储在 SQLite 中,通过 flattenConfig() / buildNested() 实现 Go 结构体到 KV 的双向转换。Picoclaw Adapter 包负责版本管理——当升级镜像时,迁移引擎自动将配置从旧版本迁移到新版本。
组件关系
| 组件 | 代码位置 | 职责 |
|---|---|---|
| 服务端 | cmd/picoaide, internal/web | HTTP API、管理后台、认证、MCP 中继、WebSocket 中继 |
| 配置层 | internal/config, internal/auth | SQLite 配置、用户、组、白名单、会话密钥 |
| 容器层 | internal/docker, internal/user | Docker 网络、容器生命周期、用户工作区 |
| 浏览器执行端 | picoaide-extension | 当前浏览器标签页控制、Cookie 同步 |
| 桌面执行端 | picoaide-desktop | 截图、鼠标、键盘、OCR、白名单文件访问 |
| 官网 | website | Hugo 静态站点和文档 |
数据流示例
以下是 AI 执行一次浏览器操作的完整路径:
1. 用户在浏览器扩展中点击"授权 AI 控制"
2. 扩展通过 WebSocket 连接到 PicoAide Server
3. AI 在容器中调用 browser_navigate 工具
4. 容器通过 SSE 向 PicoAide Server 发送 tools/call 请求
5. Server 查找该用户的 browser 执行端 WebSocket
6. Server 将命令转发给浏览器扩展
7. 扩展在用户当前标签页执行导航
8. 结果沿原路径返回给 AI
整个过程中,AI 不知道浏览器的真实地址,不持有用户的会话 Cookie,所有操作都在用户授权的范围内执行。
安全边界总结
| 层面 | 机制 | 说明 |
|---|---|---|
| 网络 | Docker ICC=false | 容器间无法直连 |
| 认证 | HMAC 签名会话 | Cookie 不包含敏感信息 |
| 工具 | MCP 代理 | AI 不直接调用浏览器/桌面 API |
| 文件 | 白名单 + 沙盒路径 | 限定 .picoclaw/workspace/ 内操作 |
| 配置 | 敏感键过滤 | internal.* 键不暴露给 API |
| 速率 | 登录限流 | 10 次/5 分钟,防暴力破解 |