给每个用户新建一段对话,并不能保证代码与文件也被隔离。托管Agent至少有两条安全轴:请求代表谁,决定能访问谁的数据;代码在哪个沙箱继续运行,决定旧文件和进程可能被谁复用。把两者绑成一个“session”字段,看似省事,实际上最容易制造跨用户泄露。
发生了什么
Microsoft Agent Framework团队9月22日发布Foundry托管Agent隔离说明。官方明确区分user identity与agent_session_id:前者可由调用者的Microsoft Entra身份解析,或由可信中间层传递稳定的委托身份;后者代表虚拟机隔离沙箱及其中持续存在的代码和文件。来源为微软官方技术文章。
官方还提醒:Foundry hosted session不是conversation。对话保存消息与工具调用历史;托管会话保存沙箱计算环境和持久文件。二者可以一对一,也可以由应用显式选择不同映射。
为什么要解耦
假设同一员工同时做“财务分析”和“公开资料整理”。身份可以相同,但两个任务不应共享临时文件。反过来,一个受控团队可能共用计算沙箱,却为每次对话保存不同历史。是否允许共享,应该由业务规则决定,而不是被某个SDK对象的生命周期偷偷决定。
技术上,可信中间层先认证自己的用户,再把稳定、不可猜测的委托标识随请求传给托管服务;应用另行创建或选择沙箱会话ID。用户身份必须每次校验,沙箱ID必须在服务端授权后才能复用。前端传来的任意agent_session_id不能直接当作访问票据。

最小实践:先把映射规则写成测试
这个纯Python示例不调用云服务,只验证“同用户不同任务不串沙箱、跨用户不能复用”的核心策略。保存后运行python isolation_policy.py:
from dataclasses import dataclass
import hashlib
@dataclass(frozen=True)
class Binding:
user_identity: str
task_id: str
sandbox_id: str
def stable_sandbox(user: str, task: str, secret: str) -> str:
raw = f"{secret}:{user}:{task}".encode()
return "sbx_" + hashlib.sha256(raw).hexdigest()[:20]
def authorize(binding: Binding, caller: str, task: str) -> bool:
return binding.user_identity == caller and binding.task_id == task
SECRET = "server-side-test-secret"
finance = Binding("u-42", "finance", stable_sandbox("u-42", "finance", SECRET))
public = Binding("u-42", "public", stable_sandbox("u-42", "public", SECRET))
assert finance.sandbox_id != public.sandbox_id
assert authorize(finance, "u-42", "finance")
assert not authorize(finance, "u-99", "finance")
assert not authorize(finance, "u-42", "public")
print("isolation policy: 4 checks passed")
代码把身份、任务和沙箱绑定保存为服务端记录;真实系统应使用随机ID与数据库唯一约束,不要靠示例哈希生成安全凭据。这个示例已在本次任务中用Python 3实际运行,四项断言全部通过。真实Foundry调用未运行,因为环境没有Azure项目、Entra权限与预发布SDK;不能把本地策略测试冒充云端隔离验证。
三个最容易踩的坑
第一,把对话ID直接当沙箱ID。删除聊天不一定删除文件,恢复聊天也不一定恢复同一运行环境。第二,相信前端传来的用户标识。委托身份只能由已经验证用户的可信中间层生成,且要防止日志与缓存泄露。第三,为省冷启动把所有人放进共享沙箱。共享池可以提高利用率,但必须证明进程、文件、环境变量和临时凭据都在任务间清理;否则成本优化会变成横向越权。
还有一个细节:官方说明Foundry托管Agent已正式可用,但AgentServer SDK和Agent Framework的Foundry托管包仍是预发布版本。接口、头字段和恢复行为上线前应按锁定版本复核,并用真实租户测试拒绝路径,而不只测成功路径。
日志也是隔离面的一部分。即使计算沙箱完全分开,如果追踪系统把不同租户的Prompt、工具参数和文件名写进同一个可搜索索引,运维人员或调试Agent仍可能跨边界看到数据。日志应带租户标签、访问控制和保留期,敏感值默认脱敏;排障导出也要经过同一授权规则。沙箱销毁后,快照、缓存和日志副本是否同步过期,需要单独验证。
同样要限制沙箱可获得的短期凭据范围,任务结束立即失效,而不是随文件一起长期保留。
适用边界与行动建议
双轴隔离适合运行用户上传文件、生成代码、安装依赖或复用沙箱缓存的多租户Agent。不涉及代码执行、没有持久文件的简单问答,也仍要做数据权限,但可以不引入复杂沙箱池。
上线前至少回答五个问题:谁认证用户;谁创建沙箱;谁能恢复它;沙箱多久销毁;删除用户数据时哪些对象要级联清理。再补三类测试:用户A枚举不到用户B的会话;旧沙箱不能读取新任务凭据;中间层伪造或缺失身份时默认拒绝。
我的判断
“谁的数据”和“哪台工作空间”是两个维度,不是两个字段名。 真正的安全改进来自服务端授权映射、生命周期和失败测试,而不是把session改成更长的ID。微软这次最有价值的贡献,是让一个常被SDK抽象遮住的边界变得可讨论、可测试。
你的Agent产品里,谁有权决定复用旧沙箱:终端用户、业务服务,还是平台策略?
关注「蜗牛聊AI」,一起看懂技术变化背后的真正机会。
本文首发于 java4u.cn,转载请注明出处。

