多用户智能体最典型的线上事故是串号:多个租户共用同一个容器时,写在文件系统上的记忆、配置和会话目录会被下一个租户读到。解决它的办法不是”小心一点”,而是把会话、记忆、工作目录、出站四条边界逐一切开,每条都有对应的可落地配置。
为什么会串:状态默认写在共享的文件系统上
多数智能体运行时默认把三类状态写到容器本地磁盘:会话记录、记忆文件、工作目录产物。开发时单用户跑没问题;一旦上线共用容器,这些路径就是共享的:
- 会话记录:默认落在用户主目录下的项目目录里。
- 记忆文件:写在全局配置目录与工作目录两个层级,会在启动时被加载进提示。
- 全局配置:所有租户共用一个配置文件。
- 工作目录:不显式指定时,会话会继承应用的工作目录,多个会话共用同一片文件系统。
更麻烦的是:这些状态都不在容器重启后存活。也就是说它同时带来了两个问题——跨租户泄露,以及扩容或重启后丢失。这两个问题要用不同的手段解决,混在一起谈会越谈越乱。
四条边界,逐条切开
边界一:会话按 ID 显式管理
不要用”继续最近的会话”这种隐式查找——它在单用户时好用,多用户时必然串。正确做法是为每个用户或每个会话捕获 ID 并显式传入。
顺带一提,会话 ID 还有第二个用途:长会话需要固定到同一个容器时,用它做一致性哈希路由,保证同一会话持续命中同一个容器、同一个运行中的进程,直到被驱逐或重启。
边界二:记忆分区,并关掉自动记忆
记忆是最容易泄露的一层,因为它会无条件加载进系统提示。仅靠”跳过设置来源”是不够的,必须同时做三件事:
- 跳过用户级、项目级、本地级设置的加载。
- 在环境变量里关闭自动记忆。否则记忆目录里的内容仍会被读进提示,无论你是否跳过了设置。
- 把配置目录指向每租户独立的路径,避免共用同一个全局配置文件。
长期记忆本身的设计(语义、情景、程序三层)是另一回事,可以参考 智能体长期记忆怎么做,但要记住:再多层的记忆设计,只要存储路径是共享的,隔离就是漏的。
边界三:每租户独立工作目录
每次调用都显式传入工作目录,不要让它继承应用目录。这条同时解决了三个问题:租户之间不互相看到文件、会话之间不互相覆盖产物、以及可以针对性地设置目录权限。
构造路径时确保每个租户拿到的路径是其他租户不可读的,并在容器层用权限或挂载隔离兜底,不要只靠路径约定。
边界四:出站按租户隔离
这条最容易被忽略。如果所有租户共用同一条出网通道和同一组凭据,一个被攻破的租户就能借另一个租户的出站策略外传数据。做法是在代理层按租户区分:
- 不同的出口 IP 。
- 不同的外部服务凭据。
- 不同的域名白名单。
顺带一个通用原则:外部服务的密钥不要放进智能体的环境,让它在出网之后由代理注入。智能体发起调用,代理补凭据,这样即使会话被注入攻击也拿不到长期有效的令牌。
一个容易漏的细节:环境变量在两种语言里行为不同
并发与容量:隔离之后还得算账
每个会话是一个独立进程,一台机器能跑多少会话,取决于内存能装多少进程。估算公式很简单:
单机会话数 = (主机内存 - 系统开销) / 单会话内存上限
单会话上限不要拍脑袋定,用一次有代表性的真实会话、跑到目标轮次、在预期工具负载下记录峰值内存占用。常见的 1 GiB 是起步值,不是上限。
这里有个反直觉的成本事实:模型调用的花费通常比容器成本高一个数量级以上。一台最低配置的机器一小时大概几美分,而一个长会话的 token 花费可能到几美元。所以优化的重点永远在减少无效轮次和工具调用上,不在省机器上,具体账本见 智能体成本怎么算。
会话模式怎么选
四种模式对应不同的隔离强度与成本:
- 一次性会话:一个任务起一个容器,跑完销毁。隔离最强、最省心,适合批处理型任务,代价是冷启动。
- 长期会话:容器常驻、承载多个会话。性能好,但隔离全靠上面四条边界,必须配齐。
- 预热空闲进程:启动时预先完成初始化握手,用户来了直接接管。能显著削掉冷启动延迟,代价是每个空闲实例常驻占用数百 MB 内存。
- 无状态:不落盘,会话只在调用期间存在于内存。适合不需要上下文延续的任务,也天然避免了落盘带来的泄露面。
- 会话显式化:捕获每个会话的 ID 并在后续调用中显式传入,禁用”继续最近会话”这类隐式查找。
- 关掉自动记忆:在环境变量里关闭,并跳过用户、项目、本地三级设置的加载。
- 配置目录按租户拆分:让每个租户有独立且其他租户不可读的配置路径。
- 工作目录按租户拆分:每次调用显式传入,并在容器层用权限或挂载做兜底。
- 出站按租户隔离:区分出口 IP 、凭据与域名白名单,外部密钥由代理在出网后注入。
- 做串号测试:同一容器连续跑两个不同租户的任务,验证第二个无法获知第一个的任何内容。
和执行沙箱、上下文隔离的关系
这里讲的是租户之间的隔离,和另外两件事不是一回事:子智能体拆分与上下文隔离解决的是单个任务内部怎么控制上下文不膨胀,智能体执行代码怎么隔离解决的是代码执行本身的逃逸风险。三者要同时做——租户隔离防串号,上下文隔离防污染,沙箱隔离防逃逸,缺一个都会出事。
隔离做扎实之后,还需要能证明它一直是有效的。把会话 ID 、租户标识带进追踪链路,出问题时才能定位到具体是哪一次调用、哪个租户,做法见 智能体可观测性怎么做。需要中断恢复能力时,别忘了快照与恢复也要按租户分区,参考 智能体断点续跑。
只用一个容器服务多个租户,风险有多大
为什么关掉了设置加载还是会泄露记忆
会话状态重启就丢,怎么解决
长会话要不要固定到同一台机器
小结
多租户智能体的隔离不是一个开关,是四道独立的边界:会话按 ID 管、记忆分区并关闭自动加载、工作目录按租户拆、出站按租户分。四道都做完之后,再做一次”连跑两个租户互相问”的串号测试来验证。剩下的容量与成本问题,重点放在减少无效轮次上,而不是省机器。
相关阅读:智能体多轮对话怎么管讲的是单会话内部的上下文治理,和这里的租户级隔离是两个层面,需要配合着做。










评论 (0)