配置
Hub 使用 Viper 加载配置,环境变量优先级最高。本页是完整的环境变量参考,并包含升级与多租户说明。服务器
数据库
认证
Hub 提供两个可互换的认证后端,由AUTH_MODE 选择:
builtin(默认):自包含的用户名密码系统,开源部署开箱即用,无需外部身份提供方。首次访问显示初始化页面,创建固定用户名的admin账号;后续用户通过 admin 签发的一次性邀请链接加入。角色为admin/maintainer/member。casdoor:把认证委托给已有的 Casdoor SSO,适用于已运行 Casdoor 的托管与私有化部署。
Casdoor(仅 AUTH_MODE=casdoor)
角色由 Hub 本地管理;JWT 中的 Casdoor roles claim 被完全忽略。Casdoor 只提供用户身份(认证)。详见下文多租户一节。
多租户与角色管理(仅 casdoor 模式)
- 租户 = Casdoor 组织:token 中的组织(owner)即租户 ID,业务数据按租户隔离。组织的创建与配置在 Casdoor 侧完成,Hub 不接管。
- 角色由 Hub 本地管理:角色真实源是本地
user_identities租户成员表(Role + Status pending/active),Casdoor 仅提供用户身份。JWT 中的 Casdoor roles claim 完全忽略。CASDOOR_ROLE_MAPPING/CASDOOR_DEFAULT_ROLE环境变量已废弃(检测到仅打 warning,不影响启动);升级后 Casdoor 侧的agent-hub-*角色可手动删除。 - 新用户待审批流程:新用户首次登录成功后自动创建 pending 记录,前端渲染「等待审批」页(可访问
/auth/userinfo与 logout,其余 API 返回 403PENDING_APPROVAL)。admin 在用户管理页为其分配角色后自动转为 active。 - admin 锚定 Casdoor 组织管理员:本地 admin 资格与 Casdoor 组织管理员(IsAdmin)双向同步——组织管理员登录/CLI 身份核对时自动成为本地 admin;被取消组织管理员则本地 admin 撤销为待审批。admin 任命/降级采用「Casdoor 先行」双写:先成功修改 Casdoor
is_admin,再写本地。 - 用户管理(admin):列表来自本地成员表(禁用状态实时查 Casdoor);审批 = 给 pending 用户分配角色(自动转 active);禁用/重置密码直通 Casdoor;admin 在用户管理页获取本组织的一次性 OAuth 授权登录链接(
/api/v1/admin/users/login-url,带本组织 client_id + PKCE)引导新用户走 Casdoor 登录/注册流。邀请制接口仅 builtin 模式可用。 - 升级指引(breaking):升级到此模型后所有现有用户变为待审批;Casdoor 组织管理员登录后自动成为 admin,再逐个为其他用户分配角色。业务数据方面:升级时存量 agents / providers / AIGC 配置等自动回填——无需任何配置,回填租户从
user_identities自动推断(恰好一个组织登录过即推断为该组织);聊天记录按user_id → user_identities映射回填到各用户所属租户,映射不到的兜底回填推断租户。仅在存量数据无法自动归属(user_identities为空或含多个组织)时,启动会报错指引临时配置CASDOOR_ORGANIZATION指定回填目标,完成本次一次性迁移后即可移除。 - 已知限制:
- JWT 无吊销通道:admin 在 Casdoor 侧被降级后,其未过期的 access token 在过期前仍有效;CLI token 最迟 5 分钟内经身份缓存纠正。
- 用户列表只显示登录过的用户(列表数据源为本地成员表,而非直通 Casdoor)。
- 部署要求:Hub 使用的 Casdoor Application 需要所在组织的用户管理权限(读写用户、组织管理员标志)。
数据隔离语义
业务表(agents / cloud_sessions / cloud_messages / provider_summaries / tools / mcp_servers / skills / scenes / aigc_configs)均含tenant_id 列并按租户隔离:
- tenant_id = Casdoor 组织名:与登录 token 的组织(owner)一致;builtin 模式恒为
default。 - 哨兵约定:业务表
tenant_id列的默认值为空串''(共享哨兵)——写入时由代码显式盖章请求租户,不依赖数据库默认值;空串仅在共享行(内置/种子数据)合法。 - 内置/种子数据全局共享:内置 tools、MCP servers、skills、scenes 及共享 provider 种子行的
tenant_id为空串(全局共享行)——各租户均可读、不可修改;租户编辑共享 provider 时按 copy-on-write 复制为本租户行后再改动,原共享行不受影响。 - 存量数据回填:从旧版本升级时,启动迁移把存量业务数据回填到归属租户(builtin 模式 →
default;casdoor 模式 → 从user_identities自动推断的唯一组织,可用CASDOOR_ORGANIZATION显式覆盖)。正常运行不依赖任何组织配置,CASDOOR_ORGANIZATION仅在存量数据无法自动归属(0 或多个组织登录过)时作为一次性升级逃生舱存在。 - 同名资源跨租户共存:原全局唯一约束(如 agents 的
uk_name、provider_summaries 的uk_key)已改为(tenant_id, name)/(tenant_id, key)复合唯一索引——不同租户可各自持有同名 agent / 同 key provider。 - 聊天数据两级隔离:cloud_sessions / cloud_messages 首先按租户隔离,会话列表在租户内再按用户隔离(member 仅见自己的会话,admin/maintainer 可见本租户全部会话)。
- AIGC 配置纯 per-tenant:每个租户各自配置自己的 aigc_configs 行(ContentProducer 主体编码等);未配置的租户不注入 AIGC 标识,不存在跨租户的共享默认回退。写操作(Save / RotateKey / Delete)只作用于本租户行,且拒绝在租户身份缺失(builtin 之外的空租户上下文)时执行。升级时,旧「全局一份」时代的遗留共享行自动归属回填租户(显式指定或自动推断的唯一租户);若该租户已保存自有配置,则丢弃遗留共享行、保留租户自有配置。
- knowledge MCP 链(runtime token):以 runtime token 访问知识库时,租户取自所命中的 agents 行的 TenantID,与操作者无关。
- Kong 对账为全局语义:后台 Kong 路由对账任务扫描全表(agent ID 全局唯一),不受租户隔离过滤影响。
角色权限矩阵
管理台(/api/v1/admin/*)按角色开放如下(builtin 与 casdoor 模式语义一致):
要点:
- member 只读边界:member 可读管理台的非敏感数据(列表/详情/知识库/部署状态
deploy,含 runtimeUrl/apiKey),但管理写操作(POST/PUT/PATCH/DELETE,含探活、部署启停)与敏感读(AIGC 配置含密钥、agent 运行时文件内容files/content)仍返回 403——中间件是权限墙,前端按钮隐藏仅 UX。例外:member 可删除自己的聊天会话。 - 聊天会话按用户隔离:member 仅可查看/删除自己的聊天会话;admin/maintainer 可见并管理全部会话。
- 用户管理仅 admin:审批/角色分配/邀请/重置密码保持 admin 专属(
RequireAdmin)。 - 路径未改名:全部保持
/api/v1/admin/*,仅内部按 write(admin/maintainer)/ read(admin/maintainer/member)分组注册。 - CLI token 收口:
/api/v1/cli仅 admin/maintainer 可用(member 403),不属于/admin面但同样由角色中间件拦截;member 历史已签发的 token 不主动吊销,自然过期后无法续签。 - member 部署按钮:member 在 Agent 页可见部署按钮,弹窗内仅「聊天」可用,其他操作按钮置灰。
运维(Ops API)
运维端点(/api/v1/ops/*,当前用于多组织 OAuth client 登记,见下文 runbook)的鉴权开关:
多组织接入 runbook(仅 casdoor 模式)
单组织部署(一个 Casdoor 组织 = 一个租户)无需任何操作:租户 client 表为空时自动回落 env 全局CASDOOR_CLIENT_ID / CASDOOR_CLIENT_SECRET / CASDOOR_CERTIFICATE,行为与旧版本完全一致。只有当第二个及以后的组织(租户)需要通过各自 Casdoor Application 登录时,才按以下三步操作。
第一步:Casdoor 侧建组织与应用
每个组织(如acme)在 Casdoor 中:
- 创建组织
acme(组织即租户,业务数据按组织隔离)。 - 在该组织下创建一个 Casdoor Application,回调(redirect URL)配置为 Hub 全局回调
CASDOOR_CALLBACK_URL(无需 per-org 回调),记录其 Client ID / Client Secret。 - 无需创建
agent-hub-admin/agent-hub-maintainer/agent-hub-member角色——Hub 的角色以本地成员表(user_identities)为准,Casdoor 侧角色不被消费(Casdoor 仅提供用户身份,Casdoor 组织管理员自动同步为本地 admin)。旧版本若在 Casdoor 侧创建过这些角色,可手动删除。
第二步:通过 Ops API 登记租户 client
先在 Hub 侧配置OPS_API_KEY 并重启,然后:
org = Casdoor 组织名(即租户 ID);cert 可选,仅当该组织使用独立于全局 CASDOOR_CERTIFICATE 的验签证书时才需要传(PEM 明文;非空时必须为合法 PEM 证书(-----BEGIN CERTIFICATE----- 开头),否则 400);isDefault 可选。
org 命名约束:组织名必须匹配 ^[a-z][a-z0-9]{0,62}$(小写字母开头,仅小写字母和数字,不超过 63 字符),不允许连字符、大写、下划线等,不合法返回 400。原因:组织名用于拼接部署键 <org>-<agent> 与 runtime URL 路径段 /<org>/<agent>(见下文「Agent ID、部署键与 runtime URL」),而 agent 名本身允许连字符——若 org 也允许连字符,(org "a", agent "b-c") 与 (org "a-b", agent "c") 会拼出同一个部署键,产生跨租户覆盖/误删的歧义。已登记的存量组织不受影响,无需迁移。
default tenant 语义(不变式:有且唯一):
- 首行自动成为 default:登记的第一条记录自动
isDefault=true。 - 登录页组织输入框留空(或无
org参数访问)即走 default 行。 - 切换 default:给新行显式传
"isDefault":true(原子切换,旧 default 自动降级)。 - 降级保护:把当前 default 降级(新增非 default 行时)且表内还有其他行 → 409;删除 default 行且表内还有其他行 → 409(响应含迁移指引:先把 default 切给其他组织再删)。删 default 是最后一行时允许;删除不存在的 org 幂等返回 204。
GET /api/v1/ops/tenant-clients(返回 org / clientId / isDefault / hasCert / 时间,不返回 secret);删除登记:DELETE /api/v1/ops/tenant-clients/<org>(default 行且表内还有其他行 → 409;删除不存在的 org 幂等返回 204)。
第三步:分发组织专属登录链接
给该组织成员分发:https://<hub>/login?org=acme
- 登录页「更多」折叠区内会出现组织输入框(仅存在多组织配置时渲染),成员也可手动填组织名。
- 组织用户首次登录自动创建 pending 记录(等待 admin 审批分配角色);Casdoor 组织管理员登录自动成为该租户 admin。
- 登录后的 refresh token 按 token 内的 owner 自解析对应组织凭证,无需额外配置。
解析链与边界行为
- 显式 org 未注册 → 404,绝不回落:
?org=xxx指定了不存在/未登记的组织,登录预检就地报错,不会回退到 default。 - 留空 / 无参数 → default 行 → env 全局:default 行不存在(表空)时回落 env
CASDOOR_CLIENT_ID(存量单组织部署零改动)。
Agent ID、部署键与 runtime URL
自 deployer v3.1 契约起,agent 的三个标识各自独立:- 数据库仍存裸名(
agents.name等),租户归属由tenant_id列表达,部署键仅在部署/网关层拼接。 - 链路版本要求:agent-deployer ≥ v3.1.0(deploymentKey 必填拆分;Hub 部署前做能力探测,旧版 deployer 会被明确拒绝并返回 503)+ agent-runtime ≥ v2.6.1 + agent-sdk ≥ v3.1.0。
- 升级顺序:deployer v3.1.0 → Hub → 强制重新部署存量 Agent(runtime 图中的 prefixed root ID 需经重部署改回裸 ID;重部署前聊天/详情对旧 agent 返回 404 属预期)。存量
<org>-<name>容器与数据目录无需迁移。 - builtin Kong 路由自动迁移:升级后首个对账周期(约 300s)把
/default/<name>路由收敛为/<name>;无 Kong 时公开 URL 从/runtime/default/<name>变为/runtime/<name>(无重定向,调用方需更新)。
OSS(S3 / MinIO)
Provider 加密
生成加密密钥:
Agent Deployer
Agent 图部署协议:Hub 部署 Agent 时向 agent-deployer 下发完整 Agent 图——
rootAgentId + agents[],subagent 为纯 id 引用,每个 Agent 携带自身完整能力(不继承、不回退父级配置),maxSessionQueries 等运行时全局字段仅 root 携带;自 deployer v3.1 起 rootAgentId 为裸 Agent ID,租户限定移至独立的 deploymentKey 字段。链路版本要求:agent-deployer ≥ v3.1.0(Hub 部署前探测并拒绝旧版)+ agent-runtime ≥ v2.6.1 + agent-sdk ≥ v3.1.0;Hub 升级后需重新部署存量 Agent。
Multirag(知识库)
大文件上传从浏览器流式直传 multirag,不会在 Hub 内整体缓冲。生产环境的反向代理或 Kong Route 也必须允许目标文件大小、关闭全请求体缓冲,并把上游超时设置为不小于
MULTIRAG_UPLOAD_TIMEOUT_SECONDS。