自托管 Dify 的 New Agent 把 shell 与代码执行跑在自家 compose 里的 sandbox 容器上——单机验证没问题,但往生产走会遇到三个现实烦恼:沙箱镜像要自己维护,多副本部署时本地沙箱成了绑定单机的负担,Agent 在会话里装的依赖重建后说没就没。Dify 1.17.x 系列把这层执行环境抽象了出去:用 DIFY_AGENT_RUNTIME_BACKEND 环境变量把执行后端从本地沙箱切到 E2B 云沙箱(官方随版本发布专用的 docker-compose.e2b.yaml,云端流量走鉴权,E2B 模板随版本发布同步);再配套两个关键特性——Build-time Home Snapshots(发布 Agent 时把沙箱 home 目录打成快照,之后的运行从快照恢复:装过的包、准备的文件、工作状态都在)与上下文感知历史压缩(按模型有效窗口分层压缩长对话)。本篇把「切后端 → 验证 → 快照 → 压缩 → 回退」完整跑一遍。
先理解:执行后端是一层可插拔的抽象
切换前先把模型搞清楚:Dify 的 Agent 执行环境 = backend 抽象层 + 具体实现。默认实现是 local——代码在自托管 compose 里的 sandbox 服务容器中执行;新的实现是 e2b——代码在 E2B(e2b.dev)的云端沙箱里执行,Dify 与 E2B 之间的流量走鉴权,官方在发布流程里同步维护 E2B 模板(沙箱的基础镜像),你不需要手工建模板。这个抽象带来的选择自由是:重依赖、长任务的 Agent 放云端跑(环境强、不占自托管资源),轻量敏感的留在本地(数据不出内网)。配套的 Home Snapshots 解决的是「云端沙箱是无状态的,Agent 装的包怎么留下来」——答案是把快照挂在发布这个动作上:构建期准备好的环境,随发布固化、随运行恢复。
版本与变量名以你所用版本为准。本篇基于 1.17.x 的官方 Release Notes(E2B 后端、Home Snapshots、历史压缩均在该系列落地,附带的 compose 文件与模板同步机制以仓库对应 tag 为准);低版本自托管实例先升级,再动后端配置。
Step 1:版本确认与 E2B 账号准备
# 确认自托管版本(页面右上角「关于」,或看 api 容器日志)
docker compose logs api | grep -i version
# 升级到 1.17.x(先备份数据库,按官方升级文档走)
git pull origin main
docker compose pull
docker compose up -d
# e2b.dev 控制台注册并生成 API Key,记下来备用
动手前两件事要确认:一是版本——E2B 后端是 1.17.x 系列的新能力,低版本升级后再切,升级流程按官方文档走并先备份数据库;二是 E2B 账号——注册后在控制台生成 API Key,免费额度足够本篇全部验证步骤,生产用量另算(Step 6 讲成本)。顺便在 Dify 里确认当前 Agent 的代码执行正常(建个测试 Agent 跑一行 python),留一个「切换前」的基线行为,后面对照。
E2B 是第三方云服务。切到 e2b 后端后,Agent 执行的代码、安装的依赖、生成的文件都会出现在 E2B 的云端沙箱里——数据敏感、合规要求内网闭环的场景,评估清楚再切,或继续用 local 后端。
Step 2:切执行后端到 e2b,拉起专用 compose 栈
# 1) 编辑 .env:指定执行后端(变量名以该版本 .env.example 为准)
DIFY_AGENT_RUNTIME_BACKEND=e2b
# 2) 按 .env.example 与 docker-compose.e2b.yaml 内的注释,
# 填入 E2B 凭证(API Key 等相关变量)
# 3) 官方随版本发布 e2b 专用 compose 栈,用它拉起
docker compose -f docker-compose.e2b.yaml up -d
# 4) 重启让 api/worker 的环境变量生效
docker compose up -d --force-recreate api worker
切换动作本身不复杂:backend 变量、E2B 凭证、compose 栈三件套。两个容易踩的点:其一,.env 改完必须重建(--force-recreate)相关容器,只 restart 不一定重读环境变量——这是「改了没生效」的头号原因;其二,e2b 栈与主栈的关系、是否需要与其他 compose 文件叠加,以你版本的仓库内 compose 目录说明为准,别凭感觉自由组合。预期效果:容器全部健康,Dify 正常登录,Agent 应用还能打开——此时执行后端已在云端,但还没验证,下一步做对照实验。
Step 3:验证 Agent 真的跑在云上,做一次对照实验
# 在 New Agent 的对话框里让它执行(构建模式):
# 安装 rich 并用它打印一行带颜色的字
# Agent 会执行类似:
pip install rich
python -c "import rich; rich.print('hello from sandbox')"
# 预期:代码执行成功并输出结果;
# 同时登录 e2b.dev 控制台,能看到对应的 sandbox 活动
「切换成功」要有证据,不能靠感觉。双重验证:一是功能面——Agent 里执行代码正常返回;二是控制台面——E2B 控制台出现对应的 sandbox 会话记录,这才是代码真的跑在云上的直接证据。再补一个对照实验增强信心:临时把 backend 切回 local 重启,跑同样的代码,观察 E2B 控制台不再新增活动——一来一回,你就对这层抽象的行为边界有了实感,也排除了「env 没生效、其实还在本地跑」的假成功。
Step 4:Home Snapshots——把「装好的环境」固化进发布
# Build by Chatting 流程里,构建期让 Agent 准备环境:
# 「安装 pandas 和 openpyxl,并在 data/ 下生成一份 seed.csv」
# 确认环境就绪后,点 Apply(发布):
# → 此刻沙箱 home 目录(已装包、文件、工作状态)被打成快照
# 验证:发布后开一个新会话,直接让 Agent:
# 「用 pandas 读 data/seed.csv 并展示前五行」
# 预期:不再重新安装 pandas,直接执行成功
这是本篇最有价值的一步。过去每次运行都是干净沙箱,Agent 每个会话都要重装依赖——慢、贵、还可能因为网络问题失败;Home Snapshots 把环境固化的时机定在发布:构建期你(或 Agent)把环境折腾到位,点 Apply 的瞬间 home 目录被打成快照,之后这个已发布 Agent 的所有运行都从快照恢复起点。预期效果:新会话冷启动即有完整依赖,装包等待消失,行为确定性大幅提升。对「数据分析 Agent」「报表生成 Agent」这类依赖固定、文件常驻的场景,这一项就值回升级票价。
快照是 home 目录的完整镜像,发布前清理敏感残留。构建期留下的临时密钥、内部数据样本、调试文件都会进快照并随每次运行恢复;发布前让 Agent「列出 home 目录全部文件并逐个确认用途」。另外版本回滚连着沙箱状态走——回退到旧版本前,确认那个版本对应的快照内容是否符合预期。
Step 5:上下文感知历史压缩,长对话不再顶穿窗口
# 实操观察:让 Agent 做一个长链路任务,例如
# 「抓取 10 个页面的内容,逐个总结,最后汇总成一份报告」
# 过程中打开 Dify 的追踪面板,观察每轮 LLM 调用的
# prompt token 曲线:
# 压缩生效时,较早的工具结果被替换为摘要,
# 曲线回落而不是单调上涨;近期上下文保持完整
长对话 Agent 的经典死法:工具结果又长又多,上下文一路涨到顶穿模型窗口。1.17.x 的 compaction 是上下文感知的——框架解析所用模型的有效窗口大小,按分层策略压缩:先清理较旧的工具结果(这类内容占空间最大、时效性最低),再对更早的对话历史做摘要,近期的关键上下文保持原样。观察方法就是上面代码块里的 token 曲线:压缩触发时曲线回落。这套机制与 E2B 后端相互独立——不管你用哪种执行后端,长对话都受益。
Step 6:运维清单与回退路径,稳字当头
# 回退本地后端:.env 改回并重建容器
DIFY_AGENT_RUNTIME_BACKEND=local
docker compose up -d --force-recreate api worker
# 上线检查单:
# 1) E2B 用量与配额告警(控制台配置)
# 2) api/worker 日志里 sandbox 调用失败率的监控
# 3) 明确哪些工作区/Agent 允许云执行(敏感空间留在 local)
# 4) 快照清理节奏:废弃 Agent 的快照随应用一起下线
生产化的最后一步是把「切换」变成「运维」:E2B 的用量与费用要有告警(按 sandbox 用量计费,免费额度适合验证不适合长期生产,规模化前到定价页算账);自托管侧监控 api/worker 日志里执行失败的占比,云上偶发抖动时能感知;治理上明确哪些工作区允许云执行——数据敏感的空间继续 local,重计算的空间上 e2b,混合部署本来就是这个抽象层的意义。回退路径永远保持可用:改回 local、重建容器,两分钟回到切换前状态,这也是敢于尝鲜的底气。
网络与费用两个隐藏成本。出站受限的内网部署切 e2b 前先打通到 E2B 端点的出站访问,否则执行请求会静默超时;费用随并发与时长线性增长,批量跑任务的 Agent 记得设并发上限。
常见问题速查
| 你遇到的现象 | 大概率原因 和 解决 |
|---|---|
| 改了 .env 还是本地执行 | 容器没重建,环境变量没重读。docker compose up -d --force-recreate api worker |
| E2B 调用报鉴权失败 | API Key 没填或填错位置。按该版本 .env.example 与 docker-compose.e2b.yaml 的注释逐项核对 |
| 发布后新会话找不到已装的包 | 快照在 Apply 时才打。构建期装完依赖后再 Apply;已发布的用新版本重走构建与发布 |
| 执行请求超时 | 内网出站没打通到 E2B 端点,或代理拦截。放行出站后重试 |
| 长对话后期回答质量下降 | 压缩摘要丢了关键约束。在指令里把硬约束重复进近期消息,或拆分任务降低单会话长度 |
| E2B 账单超预期 | 按 sandbox 用量计费。给 Agent 设并发上限,非生产时段关闭定时任务,用量告警配好 |