← 返回文章列表

AI Agent 的沙箱到底是什么:六种执行环境实测,一张能做与不能做的对照表

基于 Docker Desktop 4.77(Engine 29.5.3,cgroup v2)+ WSL Ubuntu 26.04 + 云主机 Docker 29.6.1 实测。容器级别统一使用 python:3.11-slim 镜像;无隔离基线为 WSL 原生 Python 3.14.4。测试时间 2026-09-20,27 项探针 × 6 种执行环境,另有 Dify 1.17 平台沙箱 17 项逐项对照。完整探针脚本、每级完整命令与逐项原始数据见文末「复现材料」。

📖 摘要:同一份 27 项探针 × 6 种执行环境(无隔离基线 + 五级隔离),实测 AI Agent 沙箱的能力边界。四条最意外的结果:容器默认身份是 root(能力集 CapEff=a80425fb,能写系统目录);只读根加可写 /tmp 加一条出网的路,agent 照样能给自己装包资源超限不是抛异常,是被 SIGKILL(退出码 137),agent 自己的 try/except 抓不住;状态保不保留由容器生命周期决定,跟隔离级别无关。文中另附 Dify 1.17 两套沙箱的实测对照(代码节点沙箱实测:根目录只有 5 项、写 /tmp 报 PermissionError、DNS 与子进程报 operation not permitted)、四个反直觉发现背后的坑,以及一张企业落地检查表——选隔离级别看任务要碰什么、要活多久、出错代价能不能回滚。

一、我们对沙箱的理解,是从一次报错开始的

我们给客户做一个故障诊断助手时,用 Dify 的代码节点写了段数据处理:把中间结果落到文件,下一个节点读回来。

跑的时候一直报错。查了半天才发现——代码节点跑在一个沙箱里,文件系统是只读的,连 /tmp 都不给写。后来我们在门户里记过一句:「沙箱禁写文件」。

但那句话只回答了一个问题:有些事在里面做不了。到底哪些做不了?换成别的隔离方式又会怎样?如果我自己给 agent 搭一个执行环境,该收多紧?——没人给过一张能对照的表。

于是我们决定自己跑一遍。同一份探针,从「完全不隔离」一路测到「云端远端执行」,看看每一步换来什么、又失去了什么。

这篇文章就是那张表,以及表背后我们真正学到的东西。

二、先划边界:沙箱不只是「安全设备」

要讲清一个东西,先排除它不是的东西。我们踩过的坑,一半来自把沙箱错认成别的东西。

它不只是传统意义上的安全设备。 提到沙箱,多数人想到的是防攻击、防逃逸——那是安全领域的传统沙箱,对手是恶意代码,目标是「攻不破」。agent 场景多了一层:你要防的是一个过度积极的执行者。它没想搞破坏,它只是想完成任务,于是顺手删了旧文件、把密钥写进日志、装了一堆没人要的包、跑了一个通宵的循环。所以在多租户或跑不可信代码的场景里,安全隔离依然重要;而在跑自己人或自己写的 agent 时,重点就变成了「出事可控、可回滚、可审计」。两种目标并存,只是权重随场景变——这是本文全部实测的出发点。

它不是「一个开关」。 没有「打开沙箱」这个动作。它是一组限制的集合:文件能写哪里、网络能连什么、能用多少资源、能活多久。每一项都可以单独调,也可以一项都不调。

它不是 Docker 的同义词。 容器是最常用的一种载体,不是唯一一种。进程级限制、微虚拟机(microVM,一种轻量虚拟化方案,隔离强度接近虚拟机、启动速度接近容器)、远端独立机器,都能当沙箱用——区别在隔离强度和代价(后面实测数据会看到这个取舍有多具体)。

它不是越强越好。 这是最反直觉的一条。隔离越强,agent 能干的活越少:写不了文件就跑不了数据处理,断了网就装不了依赖,只读根就存不下中间结果。选隔离级别不是选安全等级,是选任务边界——这是这篇文章想讲透的事。

三、本质:沙箱回答三个问题

把上面那组限制归一下类,沙箱其实只回答三个问题:

第一,它能碰什么? 文件系统(哪些路径可写)、网络(能不能出网、能不能连内网)、进程(能不能起子进程)。这一层决定 agent 的能力边界

第二,它能用多少? CPU 时间、内存、进程数、单次执行时长。这一层决定 agent 的资源边界——也是失败模式最隐蔽的一层(后面会看到为什么)。

第三,它能活多久? 一次性任务用完即毁,还是长驻保留工作区?重启之后,上一次的中间结果还在不在?这一层决定 agent 的状态边界,也是「能不能连续干活」的关键。

三个问题合起来就是一句话:

沙箱 = agent 的「可做集」+ 越界的代价。

「可做集」是被设计出来的,「代价」是被测出来的——这就是为什么光看配置文档不够,得跑一遍。

四、实测:同一份探针,六种执行环境

方法与环境

我们写了一份 27 项的探针脚本,覆盖五组:文件系统(写 /tmp、写工作目录、写系统目录、读系统文件、列根目录)、网络(DNS、HTTPS 出网、裸 TCP 直连、连宿主机、连网桥网关)、执行(CPU 循环、内存分配、子进程、fork、sleep)、运行时(运行身份与能力集、环境变量、可用库、能否装包)、状态(同进程读写、跨运行残留)。每项独立捕获异常,记录原始返回值——不做「成功/失败」的二次判断,只记录当时发生了什么

需要说明两处刻意的差异,避免读者横向误读:

六种配置(完整命令,可照抄复现)

0 无隔离基线——WSL 原生直接跑:

cd /tmp/probe && python3 probe.py wsl-native

1 普通容器——默认权限,不加任何限制:

docker run --rm -v "$P:/work" -w /work python:3.11-slim python /work/probe.py docker-default

2 收紧容器——只读根 + 独立可写 tmpfs + 断网 + 去能力 + 限额 + 非 root:

docker run --rm \

  --read-only \

  --tmpfs /tmp:rw,size=64m \

  --network none \

  --cap-drop=ALL \

  --security-opt no-new-privileges \

  --memory=512m \

  --pids-limit=128 \

  --user 1000:1000 \

  -v "$P/probe.py:/probe.py:ro" \

  python:3.11-slim python /probe.py docker-hardened

--read-only 只让根文件系统只读;/tmp 要可写必须单独挂 tmpfs——这两行是配套的,少了第二行,写 /tmp 会拿到 Read-only file system。生产环境建议再加 noexec,nosuid。)

3 只读根 + 工作区卷——给一个可写工作区,其余锁死:

docker run --rm \

  --read-only \

  --tmpfs /tmp:rw,size=256m \

  -v "$P/workspace:/work" -w /work \

  -v "$P/probe.py:/probe.py:ro" \

  --memory=1g --pids-limit=256 \

  --cap-drop=ALL --security-opt no-new-privileges \

  --user 1000:1000 \

  python:3.11-slim python /probe.py docker-workspace

4 云端一次性沙箱——在公网服务器上跑一次性容器,配置同第 2 级(含断网):

# 本地发起,远端执行;--rm 用完即毁

ssh $SERVER "docker run --rm --network none \

  --cap-drop=ALL --security-opt no-new-privileges \

  --memory=512m --pids-limit=128 --user 1000:1000 \

  -v /tmp/probe/probe.py:/probe.py:ro \

  python:3.11-slim python /probe.py cloud-ephemeral"

5 云端长驻沙箱——同一个容器被调用两次,测状态:

ssh $SERVER "docker run -d --name probe-agent --cap-drop=ALL \

  --memory=1g --pids-limit=256 \

  -v /tmp/probe/probe.py:/probe.py:ro \

  python:3.11-slim sleep infinity"

ssh $SERVER "docker exec probe-agent python /probe.py cloud-run1"

ssh $SERVER "docker exec probe-agent python /probe.py cloud-run2"

(第 5 级没有显式指定 --user,所以它跑成了 root——这个「忘了写」恰恰成了本文第一个发现的证据。)

结果对照表

✅ 可以做 | ❌ 不能做 | ⚠️ 有条件(见备注)

能力项 0 无隔离 1 普通容器 2 收紧容器 3 只读根+工作区卷 4 云端一次性 5 云端长驻
写 /tmp ✅(tmpfs) ✅(tmpfs) ✅(tmpfs)
写工作目录 ❌ 只读 ✅(工作卷)
写系统目录 /usr/lib ❌ 非 root ❌ 只读 ❌ 只读
读 /etc/passwd
列根目录
DNS 解析公网 ❌ 断网 ❌ 断网
HTTPS 请求出网 ❌ 断网 ❌ 断网
裸 TCP 直连公网 443 ❌ 超时 ❌ 超时 ❌ 不可达 ❌ 超时 ❌ 不可达 ❌ 超时
连宿主机(host.docker.internal:80) ❌ 不存在 ❌ 断网 ❌ 不存在 ❌ 不存在
连 docker 网桥网关(172.17.0.1:80) ❌ 断网 ❌ 断网
起子进程
fork 子进程
给自己装包 ❌ 无 pip ❌ 断网 ❌ 断网
运行身份 uid 1000 root uid 1000 uid 1000 uid 1000 root
进程能力集 CapEff a80425fb(默认 14 项) 0(全空) 0 0 a80425fb
状态:一次性容器重建后 保留 不保留 不保留 卷内保留 不保留
状态:同一容器再次调用 保留 保留 保留 保留 保留(实测 1 行 → 2 行)

关于「连宿主机」与「连内网」两行:它们不是一回事。测「连宿主机」用的是 Docker Desktop 提供的 host.docker.internal:80(Linux 上这个域名不存在,所以云端那两级直接解析失败);测「连网桥网关」用的是容器默认网桥的网关地址 172.17.0.1:80。两者通,只说明宿主机在网桥网段上对容器有监听不等于容器能扫通内网其他服务——那还取决于自定义网络、路由策略和防火墙。企业环境里请按实际网络策略单独验证,不要照表推断。

四个反直觉的发现

一、容器的默认身份是 root,能力集也是满的。 1 级和 5 级都没显式指定用户,跑出来 uid=0CapEff=00000000a80425fb(Docker 的默认 14 项能力),因此「写系统目录」这一项在普通容器里是 ✅。对比第 2 级(--cap-drop=ALL --user 1000)——CapEff=0000000000000000,一项能力都不剩。要非 root、要空能力集,必须自己写参数。这不是 Docker 的缺陷,是默认值的选择:容器默认面向「跑服务」,而服务场景里 root 是常态。

需要说明前提:这个结论成立的前提是镜像本身没有声明 USERpython:3.11-slim 没有),且宿主机未启用用户命名空间重映射。换成带 USER 指令的镜像,或开启 remap 的宿主机,结果会变——所以别记「容器就是 root」,要记「显式指定身份」。

二、只读根不等于「锁住了运行期安装」。 这是最有价值的一条。我们在第 3 级(只读根 + 可写 /tmp + 有网)里试了一句 pip install --target /tmp/libs six——装成功了,而且当场 import 可用(six 1.17.0)。反过来,第 2 级同样的命令(只读根 + tmpfs,但断网)直接失败。结论是有条件的:只读根 + 可写临时区 + 一条出网的路 = agent 能在运行期给自己加工具;三个条件缺一个都装不上。想真正锁死,这几项得一起上。反过来也成立:如果任务确实需要装包(很多 agent 任务需要),那你就得接受「它在运行期会改变自己的行为」这个事实,并把「装了什么」记进审计。

三、资源超限不是异常,是死亡。 我们给第 2 级设了 --memory=512m,然后让探针分配 2GB:容器退出码 137——cgroup 判定内存超限后,内核直接发 SIGKILL,进程通常来不及做任何处理。两次对照都在限额内正常:分配 256MB 成功;不限内存时分配 2GB 也成功。这意味着一个现实问题:agent 自己的 try/except 兜不住这类失败。它看不到「内存不足」,它连同没落盘的日志一起消失。正确做法在外部:检查退出码、用 docker inspectOOMKilled 字段、中间结果落盘、必要时重试。同理,--pids-limit 是防 fork 炸弹的那道闩,--cpus 配额则直接决定它跑多快——我们实测:同一段 3×10⁷ 次循环,无配额 1.22 秒,--cpus=0.5 后 2.76 秒,限流确实生效。

四、状态保不保留,由容器生命周期决定,跟隔离级别无关。 我们跑了三组对照:两个全新的一次性容器各跑一次,第二次运行时探针看到的历史记录都是 1 行(只有本次),互不影响;同一个长驻容器连续两次 exec,第二次看到 2 行(上一次的痕迹还在)。挂了卷的第 3 级则是「容器重建、卷内状态还在」。这条最容易忽略,因为它不出现在 docker run 的参数语义里——同一条 --read-only 命令,配 --rm 还是配长驻,agent 的「记忆」完全不同

一个需要谨慎解读的现象

在全部六种环境里,「裸 TCP 直连公网 443 端口」都失败(超时或不可达),而「HTTPS 请求出网」在允许联网的级别都成功。本机 WSL 与云端表现一致,所以我们判断这是网络环境的代理层特性,不是沙箱本身的限制——测试目标是 1.1.1.1:443(裸 TCP)与 https://pypi.org/simple/(HTTPS)。它揭示的是一个现实:agent 沙箱的联网形态很少是「全通」或「全断」,更常见的是「看起来不通、实际走代理白名单」。所以测网络边界时,一定要测到应用层的真实请求,别只 ping 端口——这条在 Dify 的沙箱设计里会看到同样的影子。

五、平台案例:Dify 1.17 为什么配两套沙箱

实测到这里,一个自然的问题冒出来:真实产品怎么做?我们正好在本地跑着 Dify 1.17,于是把它拆开看。

先看两套沙箱的定义(来自 docker-compose 与容器实配):

再说一个容易踩的坑:配置文件优先级高于环境变量。 我们读沙箱配置时发现 worker_timeout: 5,而官方 .env.example 与 compose 默认值都是 15(WORKER_TIMEOUT: ${SANDBOX_WORKER_TIMEOUT:-15}),容器内环境变量也确实是 WORKER_TIMEOUT=15。原因是 volumes/sandbox/conf/config.yaml 被挂载进容器,这份静态文件覆盖了环境变量——我们环境里它被改成了 5 秒(文件时间 2026-09-02)。所以:文章里的 worker_timeout: 5 是我们环境的实际值,不是官方默认值;你改超时的时候,先确认改的是 env 还是这份 conf,否则会出现「改了没生效」。

代码节点沙箱的实测行为(我们直接调它的沙箱接口,逐项单测 17 项):

为什么是两套? 因为两个任务要的东西相反。代码节点是「给我一段代码,算出个结果」——不需要文件系统、不需要网络、不需要长期活着,所以把边界收到最紧,只留 Python 运行时的最小底盘,用极窄的 seccomp 白名单兜住系统调用。Agent shell 工作区是「给我一个地方干活」——要装依赖、要跑命令、要保留中间产物,所以它必须有可写空间和受控的出网,隔离重点从「关死」转成「管住出口 + 留痕」,并配上认证令牌(SHELLCTL_AUTH_TOKEN我们环境里是空值 = 未启用,生产必须设)。

顺着这条线,还有两点值得企业读者留意:

这个取舍正好印证了前面那句话:隔离强度不是安全等级,是任务边界。同一个产品里,两个任务形态不同,答案就不同——而且差异大到必须上两套实现。

六、怎么选:一句判据 + 一张落地检查表

把实测数据收成一句能用的判据——按三个问题选隔离级别:任务要碰什么、要活多久、出错的代价能不能回滚。

你的任务要碰什么 建议级别 理由
只算数据、不碰文件不联网 收紧容器 + 断网 + 只读根 边界最紧,跑得最快,出事无损失
要写中间结果、读项目文件 只读根 + 工作区卷 + 非 root 给一个可写口子,其余锁死
要装依赖、调外部 API 只读根 + 可写 /tmp + 出网白名单 接受「运行期会变」,但记录装了什么
要长时间连续干活、保状态 长驻容器 + 工作区卷 状态留在卷上,容器本身可随时重建
要跑在别的机器上 远端沙箱 拿到的是更强的物理与网络边界;实际隔离强度仍取决于容器配置,不配 --user、不限额、不断网,远端也一样裸

企业落地检查表(前七项有本文实测支撑,后三项是通用做法,标注区分):

检查项 具体做法 依据
1 身份 显式 --user uid:gid,不依赖镜像默认;确认 CapEff 为空 实测:默认容器 root + 满能力集
2 文件系统 只读根 + --tmpfs /tmp:rw,noexec,nosuid,size=… + 工作卷(只读写给工作区) 实测:缺 tmpfs 写 /tmp 直接报错;卷决定状态
3 网络 默认断网;要出网走代理白名单;内网按服务名 + 防火墙放开 实测:断网与出网是两套结果;代理层现象
4 资源 --memory--pids-limit--cpus、单次执行超时、输出大小上限 实测:OOM 是 137 被杀;CPU 配额 1.22s→2.76s
5 依赖 预装白名单;运行期安装需审计(记装了什么、装到哪) 实测:只读根+tmpfs+有网仍可装包成功
6 状态 一次性 vs 长驻分清;中间结果落卷;任务结束可销毁 实测:一次性容器两次运行互不影响
7 超时与失败形态 外部检查退出码与 OOMKilled,不依赖 try/except;中间结果先落盘 实测:超限被 SIGKILL,进程无机会处理
8 凭证 不进环境变量明文;用 secret 挂载或平台注入;日志脱敏 通用做法(本文未实测)
9 可观测 退出码、OOM、超时、网络拒绝、装包记录、文件写入路径留痕 通用做法(本文未实测)
10 版本与威胁模型 镜像固定 tag 不用 latest;沙箱配置随应用版本化;可信用户 / 不可信代码 / 多租户三档分别定级 通用做法(本文未实测)

七、五个坑

现象 后果 对策
以为容器默认是安全默认 普通容器 uid=0CapEff=a80425fb,能写系统目录 agent 可改运行环境 显式 --user + --cap-drop=ALL
只读根就当锁住了 只读根 + 可写 /tmp + 有网 → 照样装上包 运行期行为被悄悄改变 只读根与断网同开;或记录安装行为
用 try/except 兜内存失败 超限时被 SIGKILL,退出码 137 任务无声消失,日志一起没了 外部查退出码与 OOMKilled;中间结果落盘
忽略容器生命周期 一次性容器两次运行互不影响 以为「记住了」,其实每次从零开始 要状态就用卷或长驻容器
改配置只改 env 挂载的 config.yaml 覆盖环境变量 改了没生效,超时还是旧值 先确认改的是 env 还是挂在容器里的 conf 文件

八、写在最后

我们做这次实测的起点,是一句「沙箱禁写文件」的踩坑记录。跑完之后,我们手里多了一张表,也多了一个判断:沙箱的价值不在「关得多严」,而在「边界说得清」

agent 不需要被关起来,它需要知道哪里能走、走错了会怎样、以及别人怎么知道它走过哪里。这三件事说清楚,一个能写文件、能联网、能装包的 agent,比一个什么都不能做的 agent 有用得多,也比一个什么都能做的 agent 安全得多。

沙箱不是把 agent 关起来,是提前告诉它哪里能走,以及走错的代价。

复现材料

探针脚本probe.py,跨环境通用,Python 3.8+)。核心结构是「每项独立 try/except + 记录原始返回值」,摘录关键几项:

def rec(item, fn):

    t0 = time.time()

    try:

        v = fn()

        RESULTS.append({"item": item, "ok": True, "value": v, "ms": int((time.time()-t0)*1000)})

    except Exception as e:

        RESULTS.append({"item": item, "ok": False,

                        "error": "%s: %s" % (type(e).__name__, str(e)[:300])})



# 文件系统:写绝对路径 / 写相对路径 / 写系统目录 / 读系统文件

def a2():

    open("/tmp/probe_write_abs.txt", "w").write("probe"); return "写入成功"

def a6():

    open("/usr/lib/probe_write_test.txt", "w").write("probe"); return "写入成功"



# 网络:DNS / TCP / HTTP / 宿主机 / 网桥网关

def b1(): return socket.gethostbyname("pypi.org")

def b2():

    s = socket.create_connection(("1.1.1.1", 443), timeout=4); s.close(); return "TCP 连通"

def b3():

    import urllib.request

    with urllib.request.urlopen("https://pypi.org/simple/", timeout=6) as r:

        return "HTTP %s" % r.status



# 执行:CPU / 内存 / 子进程 / fork

def c1():

    t = time.time(); x = 0

    for i in range(10**7): x += i

    return "1e7 循环 %.2fs" % (time.time() - t)

def c2():

    b = bytearray(256*1024*1024); b[0] = 1; return "分配 256MB 成功"



# 身份与能力集

def d2():

    return {"uid": os.getuid(), "gid": os.getgid()}



# 状态:同进程读写 + 跨运行残留

def e2():

    p = "/tmp/probe_state.txt"

    if os.path.exists(p):

        return "上次运行留下 %d 行" % len(open(p).readlines())

    return "无历史文件"

环境变量项只统计键名个数与疑似密钥的键名,绝不输出值——探针本身也不该成为泄漏渠道。

完整 27 项结果。文中对照表呈现了 17 行(部分行为合并展示),其余各组的详细项(工作目录取值、列根目录返回值、磁盘可用空间、sys.path、环境变量键名样例、进程信息等)以 JSON 形式保留,结论与正文一致,无反向结果。

环境信息:Docker Desktop 4.77.0 / Engine 29.5.3(cgroup v2)/ WSL Ubuntu 26.04(内核 6.18.33.1-microsoft-standard-WSL2,Python 3.14.4)/ 云主机 Docker 29.6.1(4 核、7.5GB、公网)/ 镜像 python:3.11-slim(Docker Hub,未固定 digest——如需严格复现请自行固定)/ 测试日期 2026-09-20。

Dify 侧环境:Dify 1.17.0 自托管(docker compose),dify-sandbox:0.2.15dify-agent-local-sandbox:1.17.0ubuntu/squid:latest;代码节点探针经 POST http://sandbox:8194/v1/sandbox/run 逐项调用(每次只跑一项,因为沙箱内一处异常会让整段代码失败)。

常见问题

AI Agent 的沙箱和传统安全沙箱有什么区别?

对手不同。传统安全沙箱防恶意代码逃逸,目标是「攻不破」,隔离越强越好;agent 的沙箱多了一类对手——「执行者好心办坏事」:误删文件、把密钥写进日志、装没用的包、跑收不住的循环。所以在可信用户场景里,设计重点通常是「边界清晰 + 状态可管理 + 出错可回滚」;而在多租户或跑不可信代码时,安全隔离依然是硬要求。文中那张六环境对照表就是按这个视角列的,两边都能用。

隔离开得越强越好吗?

不是,代价很具体。我们实测:只读根加上断网,agent 连中间结果都存不下、依赖也装不了,等于把一个能干活的执行体变成了一台计算器。反过来,只给一个可写目录加一条出网的路,它就能在运行期给自己装工具——我们在只读根加可写 /tmp 的配置里实测装包成功。合理做法是按任务形态选:先问「它要碰什么、要活多久、出错能不能回滚」,再决定收哪一项。

搭 agent 沙箱该用 Docker 还是 Kubernetes?

取决于你要管几个 agent、几类任务。单机、少量任务,Docker 加本文第 2/3 级那套参数就够了,启动快、参数直观;要按任务动态起停、要资源配额与网络策略统一管理、要多租户隔离,就该上 Kubernetes——它的 Pod 级隔离、NetworkPolicy、ResourceQuota 正好覆盖本文检查表的第 2、3、4 项,且能做「每个任务一个 Pod,用完即毁」。判断标准不是技术先进,是**你的任务是否需要「按需创建、批量管理、按租户隔离」**这三件事。

多租户场景怎么升级?

单容器共享的方案撑不住多租户,这是 Dify 官方注释都承认的边界(沙箱可经 shellctl 网络访问 agent_backend)。升级路径分三步:先把「一个租户一个容器/Pod」作为起点,凭证按租户注入、网络按租户隔离;再把工作卷按租户拆分,禁止跨租户挂载;最后把「谁在什么时候装了什么包、写了哪些路径、连了哪些域名」记成可查询的审计记录。微虚拟机(microVM)适合再往上一档——隔离强度接近虚拟机,代价是启动与运维成本。

搭 agent 沙箱一定要用容器吗?

不一定,但容器是目前成本和可控性最平衡的一档。进程级限制更轻但边界更模糊;microVM 隔离更强但启动和运维成本高,适合多租户或高风险任务;远端独立机器适合「本地主机绝对不能被碰」的场景,代价是延迟和状态同步。我们这次实测的五级容器配置加一级远端,就是想说明这个梯度——选哪一档取决于任务,不取决于技术偏好。


相关文章:AI Agent 的 Harness 到底是什么:规则、约束,还是别的(agent 的约束体系怎么搭)|Dify 应用的可演进性:好的应用,改动是加法而不是重写(应用设计要留位置给未来)|为什么有了 AI 你反而更累了?因为你在错误的层级上作战(把力气花在系统上而不是结果上)

🎧 这篇内容有播客版:第二十六期《AI Agent 的沙箱到底是什么》(可听可读,音频在门户自托管)
想让 AI 助理接入您的业务与沟通工具?看看方案与服务 →

联系我

邮箱contact@fishsun.cn

点击邮箱直接写信 · 扫码加微信沟通

微信

微信二维码

扫码加微信 · 备注「门户」更快通过