Agent 的「数据隔离「如何保证?多租户场景下如何设计
1️⃣ 考察意图
面试官想看你能否设计多租户 Agent 系统的数据隔离方案。刁钻点在于:Agent 不仅访问数据库,还通过工具访问文件系统、API、缓存等多种数据源,每种数据源都需要隔离。很多人只答"不同用户用不同数据库",但说不出上下文隔离、工具级隔离、输出过滤等深层内容。答好了能展示你在 SaaS 多租户架构和数据安全方面的经验。
2️⃣ 标准答
多租户 Agent 数据隔离从"存储层、上下文层、工具层、输出层"四个层面设计:
1. 存储层隔离(Storage Isolation)
- 数据库隔离:三种模式按安全级别递增:共享数据库+租户ID字段(成本最低,隔离最弱):所有租户数据在同一张表,用
tenant_id字段过滤。风险:SQL 注入可能跨租户访问 - 独立 Schema(中等隔离):每个租户独立 Schema,同一数据库实例。风险:数据库管理员可见所有租户数据
- 独立数据库(最高隔离):每个租户独立数据库实例。成本高但完全隔离 文件系统隔离:每个租户的文件存储在独立目录(如 /data/tenant_001/),工具访问文件时校验路径是否在当前租户目录内缓存隔离:Redis key 加租户前缀(如 tenant_001:session:xxx),防止缓存串租户向量数据库隔离:如果 Agent 用 RAG,向量索引按租户分区(如 Milvus 的 partition 或 Qdrant 的 collection)
2. 上下文层隔离(Context Isolation)
- 会话隔离:每个用户会话的 LLM 上下文(对话历史、系统 prompt、工具返回值)完全独立。会话结束后上下文立即销毁,不残留
- 上下文注入风险:如果 Agent 在会话 A 中读取了用户甲的数据,会话 B 中用户乙的请求可能"看到"会话 A 的残留数据。防御:会话开始时初始化干净的上下文
- 工具返回值在写入上下文前做租户校验
- 会话结束后清理所有中间状态(如临时文件、缓存) LLM 缓存隔离:某些 LLM 服务(如 OpenAI)会缓存 prompt 用于优化。如果缓存跨租户,可能导致信息泄露。解法:使用无缓存的 API(如 cache: false)或私有化部署
3. 工具层隔离(Tool-Level Isolation)
- 每个工具绑定租户上下文(tenant context),工具执行时自动注入租户信息:
def search_documents(query, tenant_id): # 只搜索当前租户的文档 return db.query("SELECT * FROM documents WHERE tenant_id = ? AND content LIKE ?", tenant_id, query) - 工具配置隔离:不同租户可能有不同的工具配置(如不同的 API endpoint、不同的权限策略)。用工具工厂模式,根据租户 ID 动态生成工具实例
- 工具结果校验:工具返回数据后,校验数据是否属于当前租户。例如
get_document(doc_id)返回的文档tenant_id必须等于当前租户 ID,否则拒绝返回
4. 输出层隔离(Output Filtering)
- Agent 输出前,用敏感信息检测扫描是否包含其他租户的数据
- 检测方式:(1) 正则匹配——检测手机号、身份证号等 PII;(2) 实体匹配——检查输出中提到的实体(如公司名、人名)是否属于当前租户的授权范围;(3) LLM 检测——用 LLM 判断输出是否可能包含其他用户的信息
- 坑:LLM 可能在生成回复时"记忆"了训练数据中的其他租户信息(如果用了其他租户数据微调)。解法:不同租户的微调数据严格隔离,或使用无微调的基础模型
3️⃣ 答题模板(30 秒电梯版)
"多租户数据隔离四层:存储层——数据库按租户ID/Schema/独立实例隔离,文件系统独立目录,缓存加租户前缀,向量库按租户分区。上下文层——会话上下文完全独立,工具返回值写入前做租户校验,会话结束清理中间状态。工具层——工具绑定租户上下文自动注入tenant_id,工具结果校验数据归属。输出层——输出前扫描敏感信息和其他租户数据。总结一句:多租户隔离不是单点防御而是整条链路隔离——从存储到上下文到工具到输出。"
4️⃣ 高频追问 & 应对
追问 1:共享数据库+租户ID字段的方案,怎么防止 SQL 注入跨租户访问?
三层防御:(1) 参数化查询——所有 SQL 用参数化查询(prepared statement),防止 SQL 注入绕过 tenant_id 过滤;(2) ORM 级别的租户过滤器——在 ORM 层自动注入
WHERE tenant_id = ?,开发者无需手动添加。例如 SQLAlchemy 的 event listener 或 Django 的 manager;(3) 数据库视图——为每个租户创建只包含自己数据的视图,Agent 只能访问视图而非原始表。即使 SQL 注入成功,也只能访问当前租户的数据
追问 2:Agent 用 RAG 时,向量数据库怎么隔离?
两种方案:(1) 分区隔离——Milvus 的 partition 或 Qdrant 的 collection,每个租户一个分区。搜索时指定 partition,只搜索当前租户的向量。性能好但管理复杂(租户多了分区数爆炸);(2) 过滤隔离——所有租户的向量存在同一集合,但每个向量带
tenant_idmetadata。搜索时加 filtertenant_id = "xxx"。管理简单但搜索时需要过滤,性能略差。选择标准:租户数 <1000 用分区隔离,>1000 用过滤隔离。混合方案:大租户用独立分区,小租户共享分区+过滤
追问 3:如果 Agent 被注入成功,尝试访问其他租户的数据,怎么检测和阻断?
检测:(1) 工具结果校验——工具返回数据后,校验
data.tenant_id == current_tenant_id。不匹配则拒绝返回并告警;(2) 行为基线——建立每个租户的正常访问模式(如通常搜索哪些关键词、访问哪些文档),偏离基线时告警;(3) 跨租户访问检测——如果 Agent 在短时间内尝试访问多个不同租户的数据(通过tenant_id参数变化检测),触发告警。阻断:工具层强制注入tenant_id,Agent 无法修改这个参数——即使被注入,工具也只返回当前租户的数据
5️⃣ 避坑 · 常见错误答法
- ❌ "用同一个数据库加 tenant_id 字段就够了" → ✅ "共享数据库+tenant_id 只是最基础的隔离。还需要上下文隔离(防止会话间数据残留)、工具隔离(强制注入 tenant_id)、输出隔离(扫描其他租户数据)。"
- ❌ "Agent 的上下文是独立的,不需要额外隔离" → ✅ "上下文独立性不保证数据隔离——如果工具返回了其他租户的数据,这些数据会写入当前上下文,Agent 可能在输出中泄露。需要工具结果校验+输出过滤。"
- ❌ "LLM 不会泄露其他用户的数据" → ✅ "LLM 可能在训练时见过其他用户的数据(如果用了用户数据训练)。另外,如果缓存跨租户,上下文中可能残留其他用户的信息。需要关闭缓存或私有化部署。"
6️⃣ 简历呼应
- 如果你有多租户 SaaS 项目:从"多租户 Agent 数据隔离"切入,描述你设计的四层隔离方案,给出租户规模(如 1000+ 租户、0 跨租户数据泄露事件)和性能数据
- 如果你只做过数据库安全:用"数据库隔离级别"迁移——共享DB/独立Schema/独立DB 三种模式直接适用,额外需要的是"Agent 上下文隔离"和"工具级隔离"
- 如果你是校招无项目:实现一个多租户 Agent 系统,包含数据库隔离+工具租户注入+输出过滤,测试跨租户攻击场景
- "Multi-Tenant SaaS Architecture" (AWS Whitepaper, 2023)
- "Data Isolation in LLM-based Applications" (Ji et al., 2024)
- "Milvus: Partition-based Data Isolation" (Milvus Docs, 2024)