跳到主要内容

LLM 网关 & 密钥管理

SayClaw 通过 One API 作为统一 LLM 网关,实现主密钥保护、令牌独立计费、模型路由、请求日志和自动限额。所有 OC 实例使用 litellm provider 经网关访问模型,不直连 OpenAI/Anthropic/Google。

最后更新:2026-03-11

重大变更:

  1. 已从 LiteLLM Proxy 迁移至 One API(Go 原生,MySQL 存储,零 Prisma 依赖)。
  2. API Key 管理模块重构:Master Key 与 OneAPI Channel 自动同步,Sub Key 与 OneAPI Token 自动派生。

1. 架构总览

┌──────────────────────────────────────────────────────┐
│ SayClaw Admin 后台 │
│ ┌────────────┐ ┌──────────┐ ┌───────────────────┐ │
│ │ 主 Key 保险库│ │ 模型/渠道 │ │ 令牌管理 │ │
│ └─────┬──────┘ └─────┬────┘ └────────┬──────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────────────────────────────────────────────────┐ │
│ │ One API(Go / Docker / jp-1:3001) │ │
│ │ • 渠道(Channel) = 真实 Provider API Key │ │
│ │ • 令牌(Token) = 实例虚拟 Key,独立额度 │ │
│ │ • 请求日志 → MySQL (oneapi.logs) 实时写入 │ │
│ │ • 自动 Fallback(渠道优先级 + 权重) │ │
│ └──────────────────────┬─────────────────────────┘ │
└─────────────────────────┼────────────────────────────┘

┌───────────────┼───────────────┐
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐
│ OC 实例 A │ │ OC 实例 B │ │ OC 实例 C │
│ provider: │ │ provider: │ │ provider: │
│ litellm │ │ litellm │ │ litellm │
│ key=sk-令牌A│ │ key=sk-令牌B│ │ key=sk-令牌C│
└────────────┘ └────────────┘ └────────────┘

核心原则: OC 实例只持有 One API 虚拟令牌,永远看不到真实 Provider Key。


2. 为什么从 LiteLLM 迁移到 One API?

LiteLLM 的问题(已弃用)

问题影响
Prisma query-engine 反复崩溃为 zombie 进程LLM 请求本身可能成功,但消费日志(SpendLogs)写入失败并被丢弃
Python + Prisma ORM + PostgreSQL架构复杂,调试困难,资源消耗大
database_type: "postgres" 不支持原生直连只支持 dynamo_db,无法绕过 Prisma
SpendLog 异步批量写入(10s flush)engine 挂了期间所有日志丢失,无法恢复

One API 优势

特性说明
Go 单二进制零 Python、零 Prisma、零 zombie 风险
原生 MySQL直接用现有 sayclaw-mysql,日志实时写入
60k+ Star中国社区最活跃的 AI 网关,文档完善
内置功能渠道管理、令牌系统、额度控制、用量统计、请求日志
OpenAI 兼容OC 实例零改动(换 baseUrl + key 即可)

3. 部署架构

组件清单

组件位置端口说明
One APIjp-1 (35.243.76.69)3001Docker 容器 sayclaw-oneapi
MySQLjp-13306数据库 oneapi(容器 sayclaw-mysql
Admin 面板http://35.243.76.69:3001One API 自带 Web 管理界面

Docker 启动命令

docker run -d --name sayclaw-oneapi --network host \
--restart unless-stopped \
-e SQL_DSN="sayclaw:SayClaw_App_2026!@tcp(127.0.0.1:3306)/oneapi" \
-e SESSION_SECRET="sayclaw-oneapi-secret-2026" \
-e TZ=Asia/Tokyo \
-v /opt/sayclaw-oneapi/data:/data \
justsong/one-api:latest \
--port 3001

MySQL 表结构(One API 自动创建)

表名说明
channels渠道(Provider API Key 配置)
tokens令牌(实例虚拟 Key)
logs请求日志(实时写入)
users用户管理
abilities模型-渠道映射
options系统配置

4. 渠道配置(Channel = 主 Key)

渠道是 One API 中管理真实 Provider API Key 的核心概念。每个渠道对应一个 Provider 的 API Key。

当前渠道

#渠道名类型优先级支持模型
1anthropic14 (Anthropic)10claude-opus-4-6, claude-sonnet-4-6, claude-haiku-3-5
2openai1 (OpenAI)5gpt-4o, gpt-4o-mini
3google24 (Google Gemini)5gemini-2.5-flash, gemini-2.5-pro, gemini-3-flash-preview, gemini-3.1-pro-preview

渠道管理

  • 优先级:数值越大优先使用(Anthropic=10 优先于 OpenAI=5)
  • 权重:同优先级多渠道时按权重负载均衡
  • 自动禁用:连续失败后自动禁用渠道,定期自动测试恢复
  • 多 Key 轮转:同一 Provider 可创建多个渠道实现 Key 轮转
  • 自动同步:在 Admin 后台添加/修改主密钥时,会自动调用 OneAPI 接口创建或更新对应的 Channel。

添加渠道 API

curl -X POST http://localhost:3001/api/channel/ \
-b <cookie> \
-H "Content-Type: application/json" \
-d '{
"name": "anthropic",
"type": 14,
"key": "sk-ant-xxx",
"models": "claude-opus-4-6,claude-sonnet-4-6,claude-haiku-3-5",
"priority": 10,
"weight": 1
}'

5. 令牌系统(Token = 实例 Key)

每个 OC 实例分配一个 One API 令牌,作为访问网关的凭证。

当前令牌分配

实例令牌名额度
oc-xialong-mainoc-xialong-main无限
oc-ai-jp-2-01 ~ 10oc-ai-jp-2-01 ~ 10无限
oc-ai-jp-3-01 ~ 08oc-ai-jp-3-01 ~ 08无限

令牌与实例名一一对应,映射保存在 /opt/sayclaw-oneapi/token-mapping.txt

令牌管理

  • 额度控制:可设置 remain_quota(剩余额度)或 unlimited_quota: true
  • 过期时间:可设置 expired_time,到期自动失效
  • 模型限制:可指定令牌只允许访问特定模型
  • 子网限制:可限制令牌只从特定 IP 使用
  • 自动派生:在 Admin 后台为实例创建子密钥时,会自动调用 OneAPI 接口生成 Token,并将 oneapi_key_id 关联存储在数据库中。

创建令牌 API

curl -X POST http://localhost:3001/api/token/ \
-b <cookie> \
-H "Content-Type: application/json" \
-d '{
"name": "oc-ai-jp-2-02",
"remain_quota": 0,
"unlimited_quota": true
}'

6. OC 实例配置

openclaw.json

{
"models": {
"providers": {
"litellm": {
"baseUrl": "http://35.243.76.69:3001", // One API 地址
"api": "openai-completions",
"models": [
{ "id": "claude-opus-4-6", "name": "Claude Opus 4.6" },
{ "id": "claude-sonnet-4-6", "name": "Claude Sonnet 4.6" },
{ "id": "claude-haiku-4-5", "name": "Claude Haiku 4.5" },
{ "id": "gpt-4o", "name": "GPT-4o" },
{ "id": "gpt-4o-mini", "name": "GPT-4o Mini" },
{ "id": "gemini-2.5-flash", "name": "Gemini 2.5 Flash" },
{ "id": "gemini-2.5-pro", "name": "Gemini 2.5 Pro" }
]
}
}
},
"agents": {
"defaults": {
"model": {
"primary": "litellm/claude-sonnet-4-6",
"fallbacks": ["litellm/claude-haiku-4-5", "litellm/gemini-2.5-flash"]
}
}
}
}

注意: OpenClaw 的 provider 名仍然叫 litellm(历史兼容),实际指向 One API。

auth-profiles.json

{
"version": 1,
"profiles": {
"litellm:default": {
"type": "api_key",
"provider": "litellm",
"key": "sk-xxxx" // One API 令牌
}
}
}

文件位置:/opt/oc-home-NN/.openclaw/agents/main/agent/auth-profiles.json


7. 请求日志 & 审计

日志表:oneapi.logs

One API 在每次请求完成后同步写入 MySQL,零延迟。

-- One API 自动创建,关键字段:
SELECT
id,
FROM_UNIXTIME(created_at) AS time,
token_name, -- 令牌名 = 实例名(如 oc-ai-jp-2-02)
model_name, -- 实际使用的模型
prompt_tokens,
completion_tokens,
quota, -- 消耗额度(One API 内部单位)
channel_id, -- 使用的渠道 ID
elapsed_time, -- 请求耗时(ms)
type, -- 2=成功, 其他=失败
content -- 日志详情
FROM oneapi.logs
ORDER BY id DESC;

Admin API 审计接口

GET /api/v1/audit/request-logs

参数:

  • keyword — 搜索令牌名/模型名/用户名
  • model — 按模型过滤
  • statussuccesserror
  • start_date / end_date — 日期范围
  • page / page_size — 分页

返回字段:

字段说明
instance_id令牌名(= 实例名)
user_email关联用户邮箱(通过 sayclaw_portal.user_instances + users JOIN)
model使用的模型
input_tokens输入 token 数
output_tokens输出 token 数
cost_usd费用(quota / 500000)
latency_ms请求耗时
statussuccess / error

用户关联逻辑

oneapi.logs.token_name (如 oc-ai-jp-2-02)
↓ = instance_id
sayclaw_portal.user_instances.instance_id → user_id
↓ JOIN
sayclaw_portal.users.id → email, name

聊天消息双向关联

系统打通了 LLM 调用日志与用户聊天消息之间的双向关联:

  1. 聊天历史展示用量GET /me/chat/history 接口中,assistant 消息通过 instance_id + ±5s 时间窗口匹配 oneapi.logs,返回 prompt_tokens / completion_tokens / cost_usd / latency_ms / model
  2. 用量日志展示消息GET /me/usage/logs 接口中,LLM 调用日志反向关联 chat_messages,返回 user_message / ai_message 预览。

查询示例

-- 某实例今日花费
SELECT model_name, COUNT(*) AS calls, SUM(quota) AS total_quota,
SUM(prompt_tokens) AS prompt_tk, SUM(completion_tokens) AS completion_tk
FROM oneapi.logs
WHERE token_name = 'oc-ai-jp-2-02' AND created_at >= UNIX_TIMESTAMP(CURDATE())
GROUP BY model_name;

-- 所有实例月度排行
SELECT token_name, COUNT(*) AS calls, SUM(quota) AS total_quota
FROM oneapi.logs
WHERE created_at >= UNIX_TIMESTAMP(DATE_FORMAT(NOW(), '%Y-%m-01'))
GROUP BY token_name ORDER BY total_quota DESC;

8. Fallback & 路由策略

渠道级 Fallback(One API 自动)

One API 根据渠道优先级和权重自动路由:

  1. 请求模型 claude-sonnet-4-6 → 匹配 Anthropic 渠道(priority=10)
  2. 如果 Anthropic 失败 → 自动禁用该渠道 → 尝试备用渠道
  3. 定期自动测试已禁用渠道 → 恢复可用后重新启用

OC 实例级 Fallback

"model": {
"primary": "litellm/claude-sonnet-4-6",
"fallbacks": ["litellm/claude-haiku-4-5", "litellm/gemini-2.5-flash"]
}

当 One API 返回错误时,OpenClaw 按 fallback 列表依次尝试。

建议: fallback 链中不混用不同计费等级的模型(如 claude-sonnet → claude-haiku → gemini-flash,而非 → gpt-4o),避免意外高额消费。


9. 主 Key 保险库(Admin 侧)

主 Key 仍然通过 SayClaw Admin 管理,加密存储在 llm_master_keys 表。 One API 渠道中填入的是解密后的真实 Key。

管理规则

  • 主 Key 加密存储在 MySQL(AES-256-GCM),Admin 后台仅展示前缀
  • 只配置到 One API 渠道,不下发给任何 OC 实例
  • 支持多 Key 轮转(同一 Provider 创建多个渠道)
  • 创建/轮换/吊销均有审计日志

DB 表:llm_master_keys(Admin 侧,不变)

CREATE TABLE llm_master_keys (
id VARCHAR(36) PRIMARY KEY,
provider VARCHAR(50) NOT NULL COMMENT 'openai/anthropic/google',
name VARCHAR(100) NOT NULL COMMENT '密钥名称',
encrypted_key TEXT NOT NULL COMMENT 'AES-256-GCM 加密后的原始 key',
key_prefix VARCHAR(20) NOT NULL COMMENT '前缀用于识别(如 sk-ant-...)',
is_active TINYINT(1) DEFAULT 1,
monthly_budget_usd DECIMAL(10,2) DEFAULT 0,
current_spend_usd DECIMAL(10,2) DEFAULT 0,
created_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3),
updated_at DATETIME(3) DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

10. 可用模型

供应商Model ID渠道类型
Anthropicclaude-opus-4-614
Anthropicclaude-sonnet-4-614
Anthropicclaude-haiku-3-514
OpenAIgpt-4o1
OpenAIgpt-4o-mini1
Googlegemini-2.5-flash24
Googlegemini-2.5-pro24
Googlegemini-3-flash-preview24
Googlegemini-3.1-pro-preview24

新增模型流程:

  1. 在 One API 渠道中添加模型名到 models 字段
  2. 更新 OC 实例 openclaw.json 的 models 列表
  3. (可选)在 ai_models 表注册元信息

11. 运维手册

常用命令

# 查看 One API 状态
docker ps --filter name=oneapi

# 查看日志
docker logs --tail 50 sayclaw-oneapi

# 重启
docker restart sayclaw-oneapi

# 查看最近请求日志
docker exec sayclaw-mysql mysql -uroot -p'SayClaw_MySQL_2026!' oneapi \
-e "SELECT FROM_UNIXTIME(created_at), token_name, model_name, prompt_tokens, completion_tokens FROM logs ORDER BY id DESC LIMIT 10;"

健康检查

# API 可达性
curl -s http://localhost:3001/api/status

# 模型调用测试
curl -s -X POST http://localhost:3001/v1/chat/completions \
-H "Authorization: Bearer <admin-token>" \
-H "Content-Type: application/json" \
-d '{"model":"claude-sonnet-4-6","messages":[{"role":"user","content":"hi"}],"max_tokens":3}'

故障排查

症状排查处理
实例报 401令牌过期或被删One API 后台检查令牌状态
实例报 404 模型渠道未配该模型渠道 models 字段加入
日志不出现MySQL 连接异常docker logs sayclaw-oneapi 查错
请求超时渠道 Key 限额检查 Provider 仪表盘

12. 迁移记录

从 LiteLLM 到 One API(2026-03-10)

步骤说明状态
部署 One APIDocker, 端口 3001, MySQL oneapi
创建渠道Anthropic(14) / OpenAI(1) / Google(24)
生成令牌19 个实例各一个 Token
切换 jp-2 实例10 个实例 baseUrl + key 更新
切换 jp-3 实例8 个实例 baseUrl + key 更新
Admin API 审计改查 oneapi.logs + 用户关联
停用 LiteLLM容器停止 + watchdog cron 移除
数据验证请求 → 日志 1 秒内出现

历史遗留

  • llm_sub_keys 表:LiteLLM 时代的子 Key 管理,数据保留但不再使用
  • llm_request_logs 表:LiteLLM 时代的请求日志,已被 oneapi.logs 取代
  • PostgreSQL litellm 库:LiteLLM SpendLogs 历史数据保留,不再写入

13. 安全约束

  • 渠道中的真实 API Key 仅存在于 One API 数据库和 Admin 后台
  • OC 实例只持有 One API 虚拟令牌,无法反推真实 Key
  • One API 管理面板建议设置强密码,限制访问 IP
  • 令牌创建/停用/删除操作通过 One API 审计日志追溯
  • 主 Key 在 llm_master_keys 表中加密存储(AES-256-GCM)