多租户部署
wesgine 天然支持多租户——Hypervisor(控制面)管理多个 Cell(数据面),每个 Cell 是完整、独立、可移植的 AI Agent 运行时。本文档介绍多租户场景的部署架构、Cell 规划、资源分配和运维工具。
部署架构
两层架构
┌────────────────────────────────────────────────────────────────┐
│ Application Layer (wesclaw / wescode / wescraft / teleclaw) │
└────────────────────────────────────────────────────────────────┘
│ SDK API (Go / HTTP)
┌───────────────────▼────────────────────────────────────────────┐
│ Hypervisor (控制面,全局唯一) │
│ 只做三件事:Cell 生命周期 / 共享 Provider 池 / 跨 Cell 只读观测 │
└───────────────────┬────────────────────────────────────────────┘
│ manages
┌───────────────────▼────────────────────────────────────────────┐
│ Cell (数据面,每租户一份,完全隔离) │
│ 6 BC: Cognitive / Context / Execution / Memory / Knowledge / │
│ Coordination + TaskMemory │
└────────────────────────────────────────────────────────────────┘
部署模式
| 模式 | 说明 | 典型消费方 |
|---|---|---|
| SDK 嵌入 | Go 进程内直接调用 wesgine | wesclaw/wescode/wescraft |
| HTTP 二进制 | wesgine 独立进程,HTTP 通信 | teleclaw (Java) |
| 混合 | SDK 用于热路径,HTTP 用于管理 | 自定义部署 |
HTTP 二进制模式架构
应用进程 (Java/Python/Node)
│ HTTP + SSE
▼
wesgine 进程 (:9091)
├── /admin/* → Hypervisor 管理
├── /cells/{id}/* → Cell 业务
├── /health → 健康检查
└── /metrics → Prometheus
Cell 规划
租户映射策略
不同产品使用不同的租户 → Cell 映射:
| 产品 | 映射 | Cell ID 模式 |
|---|---|---|
| wesclaw 桌面 | 1 用户 = 1 Cell | main |
| wescode | 1 workspace = 1 Cell | ws-{hash} |
| wescraft 个人版 | 1 用户 = 1 Cell | personal |
| wescraft 团队版 | 1 团队 = 1 Cell | team-{id} |
| teleclaw | 1 部门 = 1 Cell | dept-{id} |
Cell 与 Actor 的关系
Cell (Tenant, 物理隔离)
├── Actor A (User, 运行时行为)
│ ├── 自己的记忆 (L3 about_me, L4 agent_memory)
│ ├── 自己的会话
│ └── 自己的 Run 记录
├── Actor B
│ └── ...
└── 共享资源
├── Agent 配置
├── Skill 包
├── MCP 连接
├── Knowledge Corpus
└── 部门共识 (L2 consensus)
核心原则:结构资源归 Cell 不区分 Actor;运行时行为(记忆/会话/HITL/Token 归因)区分 Actor。
Cell 数量规划
| 规模 | Cell 数 | 推荐配置 |
|---|---|---|
| 小型(< 10 Cell) | 1-10 | 单进程,SQLite |
| 中型(10-100 Cell) | 10-100 | 单进程,温度管理优化 |
| 大型(100+ Cell) | 100+ | 多进程,考虑分片 |
资源分配
Per-Cell 配额
通过 CellSpec.Quotas 为每个 Cell 分配资源:
spec := wesgine.CellSpec{
ID: "dept-legal",
Quotas: wesgine.CellQuotas{
MaxConcurrentRuns: 3,
TokensPerMinute: 50000,
TokensPerDay: 2000000,
MaxMemoryEntries: 5000,
MaxIMChannels: 5,
MaxMCPServers: 5,
MaxCronJobs: 10,
MaxEmailAccounts: 3,
MaxSkillsInstalled: 20,
},
}
共享 Provider 池
多个 Cell 共享 Hypervisor 级 Provider 池:
hyp.SharedProviders().Reconfigure(ctx, SharedProviderConfig{
Providers: []ProviderConfig{
{Name: "openai", Type: "openai", APIKeyRef: SecretRef{...}},
{Name: "azure", Type: "azure_openai", APIKeyRef: SecretRef{...}},
},
})
Cell 通过 ProviderStrategy 声明如何使用 Provider:
| 策略 | 说明 |
|---|---|
shared_only | 只用共享池 |
own_only | 只用私有 Provider |
own_first | 优先私有,fallback 到共享 |
shared_first | 优先共享,fallback 到私有 |
温度管理
| 温度 | 含义 | 资源占用 |
|---|---|---|
| Hot | 有活跃 Run | 最高 |
| Warm | goroutine/DB 在 | 中等 |
| Cool | 磁盘保留,无 goroutine | 低 |
| Cold | Stopped | 零 |
温度转换:Hot → Warm(Run 结束)→ Cool(idle 15min)→ Cold(idle N 天)。
外设需要 Warm 态(Cron/IMAP 需要 goroutine)→ Cell 无法降到 Cool。
隔离策略
物理隔离(引擎保证)
- 数据库隔离:每个 Cell 有独立的
meta.db/sessions.db/state.db - 文件隔离:
{DataDir}/cells/{ID}/完全独立 - 进程排他锁:同一 Cell 同一时刻只有一个写入者(flock)
- 工具隔离:Cell A 的 MCP 工具对 Cell B 物理不可见
逻辑隔离(应用层)
- Actor 过滤:记忆/会话/HITL 按 actor 过滤
- Agent 可见性:应用层
creator_id+shared标记 - 配额隔离:每个 Cell 独立配额
合规隔离
通过 Compliance 预设实现不同安全等级:
// 金融合规部门
governance.RegulatedPreset() // locked + internal_only + Redactor
// 一般部门
governance.StandardPreset() // open + allow
// 展示 / Demo
governance.ReadonlyPreset() // locked + deny
运维工具
Cell 管理
# 列出所有 Cell
curl -H "Authorization: Bearer <admin-token>" \
http://localhost:9091/admin/cells
# 创建 Cell
curl -X POST -H "Authorization: Bearer <admin-token>" \
-H "Content-Type: application/json" \
-d '{"id":"dept-legal","timezone":"Asia/Shanghai"}' \
http://localhost:9091/admin/cells
# 查看 Cell 详情
curl -H "Authorization: Bearer <admin-token>" \
http://localhost:9091/admin/cells/dept-legal
# 更新 Cell 配置
curl -X PATCH -H "Authorization: Bearer <admin-token>" \
-H "Content-Type: application/json" \
-d '{"quotas":{"max_concurrent_runs":5}}' \
http://localhost:9091/admin/cells/dept-legal
# 停止 Cell
curl -X POST -H "Authorization: Bearer <admin-token>" \
http://localhost:9091/admin/cells/dept-legal/stop
# 重启 Cell
curl -X POST -H "Authorization: Bearer <admin-token>" \
http://localhost:9091/admin/cells/dept-legal/restart
# 删除 Cell(registry + 磁盘)
curl -X DELETE -H "Authorization: Bearer <admin-token>" \
http://localhost:9091/admin/cells/dept-legal
Cell 导入导出
# 导出 Cell(tar.gz 流)
curl -H "Authorization: Bearer <admin-token>" \
http://localhost:9091/admin/cells/dept-legal/export > dept-legal.tar.gz
# 导入 Cell
curl -X POST -H "Authorization: Bearer <admin-token>" \
-H "Content-Type: application/gzip" \
--data-binary @dept-legal.tar.gz \
http://localhost:9091/admin/cells/import?overwrite=1
跨 Cell 观测
# Hypervisor 快照
curl -H "Authorization: Bearer <admin-token>" \
http://localhost:9091/admin/observe/snapshot
# 各 Cell 统计
curl -H "Authorization: Bearer <admin-token>" \
"http://localhost:9091/admin/observe/per-cell-stats?cell=dept-legal&cell=dept-hr"
# Provider 延迟
curl -H "Authorization: Bearer <admin-token>" \
http://localhost:9091/admin/observe/provider-latency
# 跨 Cell Run 列表
curl -H "Authorization: Bearer <admin-token>" \
"http://localhost:9091/admin/observe/runs?cell=dept-legal"
Token 管理
# 签发 Admin Token
curl -X POST -H "Authorization: Bearer <bootstrap-token>" \
http://localhost:9091/admin/tokens
# 吊销 Admin Token
curl -X DELETE -H "Authorization: Bearer <admin-token>" \
http://localhost:9091/admin/tokens/<token-id>
# 签发 Cell Token
curl -X POST -H "Authorization: Bearer <admin-token>" \
http://localhost:9091/cells/dept-legal/tokens
# 吊销 Cell Token
curl -X DELETE -H "Authorization: Bearer <admin-token>" \
http://localhost:9091/cells/dept-legal/tokens/<token-id>
TenantBootstrap 模式
对于 HTTP 二进制模式部署(如 teleclaw),推荐使用 TenantBootstrap 模式在应用启动时自动对齐 Cell:
应用启动
→ 等待 wesgine 就绪(/health)
→ 读取部门列表
→ 幂等 upsert 每个部门的 Cell
→ 完成
关键原则:
- 幂等——重启不产生副作用
- 对齐不删——wesgine 里多余的 Cell 保留
- 失败降级——单个 Cell 创建失败不阻塞整体
最佳实践
- Cell ID 使用有意义的前缀——
dept-、ws-、team-便于管理 - 设置合理的配额——防止单个 Cell 耗尽共享资源
- 监控温度分布——过多 Hot Cell 说明负载不均
- 定期导出重要 Cell——作为灾难恢复备份
- 使用 Compliance 预设——而不是手写治理规则
- Actor 隔离在应用层——不要在 Cell 内为每个子系统加 Actor 过滤