私有Agent平台多租户隔离,知识库

私有Agent平台多租户隔离的核心,是保证不同租户的知识库和Agent实例在数据读写、API调用时互不可见。
本文以自建系统为例,给出基于 tenant_id 的逻辑隔离方案,包含建表、中间件校验和验证命令,零基础也能照着配置。

先分清隔离边界:知识库和Agent实例到底隔离什么

多租户隔离不是简单地把用户分开,而是要覆盖三类数据:

  • 知识库数据:文档切片、向量索引、检索记录,属于底层数据资产。
  • Agent配置与状态:提示词、记忆、会话历史、工具绑定等运行时数据。
  • 访问权限:不同租户的API Key、Token 或用户身份,不能访问其他租户的资源。

所以本文采用的方案是:在数据库表中增加 tenant_id 字段,并在应用层强制校验该字段。
这样即使两个租户使用同一个私有Agent平台,知识库和Agent实例也不会互相串数据。

数据库设计:为每张核心表加上租户字段

以 MySQL / PostgreSQL 为例,先给 knowledge_baseagent_instance 两张表加上 tenant_id

假设已有 knowledge_base 表,执行:

ALTER TABLE knowledge_base ADD COLUMN tenant_id VARCHAR(64) NOT NULL DEFAULT '';
CREATE INDEX idx_kb_tenant ON knowledge_base (tenant_id, id);

ALTER TABLE agent_instance ADD COLUMN tenant_id VARCHAR(64) NOT NULL DEFAULT '';
CREATE INDEX idx_agent_tenant ON agent_instance (tenant_id, id);

tenant_id 建议使用 UUID 或租户唯一编码,不要用自增ID,避免被遍历猜测。
索引必须跟上,否则后续租户数量增大后查询会明显变慢。

如果知识库关联了向量数据库,还需要在向量集合或分片中带上租户标识。
例如使用 Milvus 时,可以在每个 Collection 的 partition key 上记录 tenant_id,或者在每条向量数据的 metadata 中写入 tenant_id,检索时作为过滤条件。

中间件层强制校验:不让恶意请求跨租户

建好字段还不够,真正起到隔离作用的是应用层的强制拦截。
建议在 API 网关或后端服务入口增加一个租户校验中间件,逻辑如下:

# 伪代码示例:FastAPI 中间件
@app.middleware("http")
async def tenant_guard(request: Request, call_next):
    tenant_id = request.headers.get("X-Tenant-ID")
    if not tenant_id:
        return JSONResponse(status_code=401, content={"error": "missing tenant"})

    # 从请求参数或路径中提取资源ID
    resource_id = request.path_params.get("id")
    if resource_id:
        # 查询该资源归属的租户
        owner = await db.query(
            "SELECT tenant_id FROM agent_instance WHERE id = ?", resource_id
        )
        if owner != tenant_id:
            return JSONResponse(status_code=403, content={"error": "tenant mismatch"})

    response = await call_next(request)
    return response

要点是:前端传的 tenant_id 只能作为身份提示,不能作为信任依据
服务端必须根据资源ID去数据库反查归属租户,再和当前登录租户比对,不一致直接拒绝。

对于知识库检索接口,同样要带上租户过滤。
查询向量时,强制加上 tenant_id == 当前租户 的过滤条件,防止一个租户通过遍历ID读取别人的知识库内容。

部署与存储层面的附加隔离选项

如果租户数量少,但数据敏感度高,可以考虑物理隔离方案:每个租户独立一套数据库和向量索引,或者使用独立的 Kubernetes Namespace 部署 Agent 运行环境。

  • 数据库:为每个租户创建独立的 schema 或 database,连接串由路由层动态选择。
  • 对象存储:知识库上传的原始文件,使用 s3://bucket/tenant/{tenant_id}/ 路径前缀隔离。
  • Agent 实例:如果每个租户需要独占模型资源,可以按租户部署独立 Pod,通过网络策略限制跨租户访问。

逻辑隔离适合大多数内部场景,物理隔离更稳但成本高。
建议先做逻辑隔离,运行一段时间后发现某个租户资源占用过高,再单独将其迁移到物理环境。

验证是否真正隔离:用两个租户跑通全链路

配置完成后,用两个测试租户验证:

  1. 租户A创建知识库 kb_a,并上传一个文档。
  2. 租户B调用“获取知识库列表”接口,确认看不到 kb_a
  3. 租户B直接访问 knowledge_base/{kb_a_id} 详情接口,预期返回 403。
  4. 租户A发布一个 Agent,租户B无法调用该 Agent 的对话接口。
  5. 使用数据库查询确认所有带 tenant_id 的表都正确写入:
SELECT tenant_id, COUNT(*) FROM knowledge_base GROUP BY tenant_id;
SELECT tenant_id, COUNT(*) FROM agent_instance GROUP BY tenant_id;

如果只有预期租户的数据行,说明隔离已生效。

避坑提醒:这些细节容易导致隔离失效

  • 创建表时忘记 tenant_id 索引:租户多了后全表扫描,接口会超时。
  • 中间件只校验了 Header,没校验资源归属:攻击者可以直接改 Header 绕过隔离。
  • 向量检索时只按文档ID过滤:必须同时加上 tenant_id,否则向量数据库可能返回其他租户的相似片段。
  • 缓存导致跨租户串数据:如果用了 Redis 缓存知识库答案,缓存键必须包含租户ID,例如 kb:{tenant_id}:{hash}
  • 备份恢复时混租户:恢复数据库时如果只按表恢复,可能把别的租户数据带进来。恢复后要重新校验 tenant_id

如果你正在处理私有Agent平台多租户隔离,建议先按本文步骤完整执行,再根据自己的环境做微调;
遇到异常时优先回看避坑和高频问题部分。

实际部署中,还会涉及数据库连接池、接口限流和审计日志等细节,但只要 tenant_id 真正贯穿知识库和Agent实例的存储、查询、缓存和API层,相互隔离就不会有大的疏漏。

分享到:
上一篇
Agent工具调用失败自动重试、回退降级策略
下一篇
文档解析大PDF乱码、表格丢失,LangChain文档加载器
1
系统公告

机房迁移升级通知

尊敬的用户: IP 段 103.23.148.x、156.224.29.x 原香港一区线路波动、攻击频繁,平台定于 7 月 5 日凌晨分批迁移至香港 GIA 机房,硬件升级 AMD 铂金机型。 迁移均在凌晨操作,最大程度降低业务影响,迁移期间服务器临时关机; 升级后配置不降低、费用不涨价,数据默认同步迁移; 迁移后 IP 全部更换,请及时修改域名解析、防火墙白名单; 建议提前备份重要数据,有问题可联系在线客服。 感谢理解与支持! 泽御云科技 2026.06.30
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意