HTTP 网关详解
wesgine HTTP Gateway 是引擎的 HTTP 服务层,提供单 Cell 和多 Cell 两种模式,包含完整的中间件链、Token 认证和错误处理。
概览
HTTP 请求
│
▼
Gateway(单 Cell 或多 Cell 模式)
│
▼ 中间件链
path parse → cell exist → auth → state → quota → dispatch
│
▼
Cell Handle(Runtime / Memory / Sessions / ...)
│
▼
HTTP 响应 / SSE 流
单 Cell 模式(ServeSingleCell)
适用于桌面应用、单租户场景:
cell, _ := hyp.Cells().GetOrCreate(ctx, wesgine.CellSpec{ID: "main"})
// 单 Cell 无 cellID 路径
// 所有业务端点直接挂在根路径
router := gateway.ServeSingleCell(cell, gateway.Options{
Addr: ":9091",
AdminToken: adminToken,
})
router.Start(ctx)
路由结构:
GET /run SSE 流式 Run
POST /chat 同步 Chat
GET /sessions 会话列表
GET /memory 记忆列表
POST /memory/search 记忆搜索
... (无 /cells/{id} 前缀)
GET /health 健康检查
GET /metrics Prometheus 指标
使用场景:
- wesclaw 桌面(1 用户 = 1 Cell
"main") - wescode(1 workspace = 1 Cell
"ws-{hash}",每进程一个) - wescraft 个人版(1 用户 = 1 Cell
"personal")
多 Cell 模式(ServeMultiCell)
适用于多租户、企业部署:
hyp, _ := wesgine.NewHypervisor(ctx, wesgine.HypervisorConfig{
DataDir: dataDir,
})
hyp.Start(ctx)
// 多 Cell 模式,所有业务端点在 /cells/{id}/* 路径
router := gateway.ServeMultiCell(hyp, gateway.Options{
Addr: ":9091",
AdminToken: adminToken,
})
router.Start(ctx)
路由结构:
# Cell 业务路由
POST /cells/{cellID}/run SSE 流式 Run
POST /cells/{cellID}/chat 同步 Chat
GET /cells/{cellID}/sessions 会话列表
GET /cells/{cellID}/memory 记忆列表
...
# Admin 路由
GET /admin/cells 列出所有 Cell
POST /admin/cells 创建 Cell
GET /admin/cells/{id} 获取 Cell 详情
...
# 基础设施
GET /health 健康检查
GET /metrics Prometheus 指标
使用场景:
- Teleclaw(部门 = Cell)
- wesclaw SaaS(多用户)
- 任何多租户部署
中间件链
HTTP 请求经过六层中间件处理:
1. Path Parse(路径解析)
从 URL 提取 cellID 和业务路径:
/cells/dept-legal/sessions → cellID="dept-legal", path="/sessions"
2. Cell Exist(Cell 存在性)
验证 cellID 对应的 Cell 是否存在:
- 内存有活跃 Cell → 通过
- 内存无 → hydrate 骨架(Cool 状态),不 Start(INV-CELL-06)
- 注册表无 → 404
3. Auth(认证)
验证请求携带的 Token:
Authorization: Bearer <token>
Token 类型:
| 类型 | 签发 | 权限 | 用途 |
|---|---|---|---|
| Admin Token | hyp.Tokens().IssueAdminToken(ttl) | 所有 Cell 全权限 | 管理工具 |
| Cell Token | cell.Tokens().Issue(roles) | 单 Cell 指定角色 | 应用集成 |
权限作用域:
cell:admin → 完整管理权限
cell:chat → 对话和会话变更
cell:read → 只读访问
4. State(状态检查)
检查 Cell 当前温度状态:
| 温度 | 行为 |
|---|---|
| Hot / Warm | 直接通过 |
| Cool | 自动 WarmUp(同步,~100-500ms) |
| Cold | 返回 503 + Retry-After: 5 + 异步唤醒 |
INV-SERVE-REACHABLE-01:wesgine serve 到达"可被探活"的时间是有界常数,不随租户数或数据库体积增长。
5. Quota(配额检查)
检查 Cell 配额:
MaxConcurrentRuns:并发 Run 数上限,超限 429TokensPerMinute:每分钟 Token 上限,超限 429TokensPerDay:每天 Token 上限,超限 429
6. Dispatch(分发)
将请求分发到对应的 Cell Handle 方法。
Token 签发与验证
Admin Token
// 签发 Admin Token
token := hyp.Tokens().IssueAdminToken(24 * time.Hour)
// 使用
curl -H "Authorization: Bearer ${token}" \
http://localhost:9091/admin/cells
bootstrap admin token:wesgine serve --admin-token-bootstrap 在启动时签发并输出到 stderr(不走 logger,因为 journal 常被转发出机器)。
Cell Token
// 签发 Cell Token
token, _ := cell.Tokens().Issue(wesgine.TokenRoles{
Scopes: []string{"cell:chat", "cell:read"},
Actor: "alice",
})
// 吊销
cell.Tokens().Revoke(ctx, tokenID)
Token 认证中间件行为
请求到达
│
├── 无 Authorization header → /health, /metrics 放行;其他 401
│
├── Bearer <token>
│ ├── Admin Token → 全权限,actor 可由 ?actor= 指定
│ └── Cell Token → 检查作用域
│ ├── 路径需要 cell:admin(如 /memory POST)→ 无权 403
│ ├── 路径需要 cell:chat(如 /sessions 变更)→ 检查
│ └── 路径需要 cell:read(默认)→ 通过
│
└── 无效 Token → 401
错误处理
错误响应格式
{
"error": {
"code": "cell_not_found",
"message": "Cell 'dept-xxx' not found",
"details": {}
}
}
常见错误码
| HTTP | code | 说明 |
|---|---|---|
| 400 | invalid_request | 请求参数错误 |
| 400 | model_required | 未指定 model(INV-MODEL-01) |
| 400 | actor_required | 未指定 actor |
| 401 | unauthorized | Token 无效或缺失 |
| 403 | forbidden | 权限不足 |
| 404 | cell_not_found | Cell 不存在 |
| 404 | session_not_found | 会话不存在 |
| 409 | degraded_secret_overwrite | 降级态密钥保护 |
| 429 | quota_exceeded | 配额超限 |
| 503 | cell_cold | Cell 冷态,Retry-After: 5 |
SSE 错误
SSE 流中的错误通过事件传递:
event: error
data: {"kind":"cognitive_error","message":"...","recoverable":true}
event: done
data: {"reason":"cognitive_error"}
Run 生命周期与 HTTP 解耦(INV-RUN-DETACH)
SSE 断开不取消 Run。 取消 Run 的唯一途径:
POST /sessions/{sid}/interrupt- CycleDetector 自愈失败后 HITL 超时
- ErrorStreakDetector HITL 超时
- 外部 BudgetCheckFn
- Cell Stop
SSE 断开后可重连续播:
GET /cells/{id}/runs/{runID}/events?from_seq=42
启动流程
wesgine serve
wesgine serve \
--data-dir /var/lib/wesgine \
--addr :9091 \
--admin-token-bootstrap
启动顺序:
1. router.Start(绑端口)
2. sdnotify.Ready()(通知 systemd)
3. ActivatePersisted(后台 goroutine 热 Cell)
INV-SERVE-REACHABLE-01:绑端口在前,热 Cell 在后。确保进程可探活的时间不随数据增长。
Gateway Options
gateway.Options{
Addr: ":9091",
AdminToken: "bootstrap-token",
CORSOrigins: []string{"http://localhost:3000"},
ReadTimeout: 30 * time.Second,
WriteTimeout: 0, // SSE 需要长连接
IdleTimeout: 120 * time.Second,
MaxHeaderBytes: 1 << 20,
}
最佳实践
- 生产环境使用多 Cell 模式:即使只有一个 Cell,多 Cell 模式便于后续扩展
- 使用 Cell Token 而非 Admin Token:最小权限原则
- 配置 CORS:明确允许的前端来源
- 监控 503 频率:Cold Cell 的 503 频率反映温度管理是否合理
- SSE 重连:客户端实现指数退避重连,使用
from_seq续播 - Nginx 超时对齐:反向代理的超时必须 > 引擎的超时
相关端点
完整端点列表见 wesgine AGENTS.md §7.4 HTTP Gateway,包含 Cell 路由(25 组)和 Admin 路由(4 组)的完整定义。