大模型开发 - 手写Manus之Sandbox执行代码:03 用Docker为AI Agent打造安全沙箱
文章目录引言一、新增依赖二、DockerSandbox容器生命周期管理2.1 安全配置2.2 容器启动2.3 命令执行2.4 执行结果封装三、SandboxTool面向Agent的工具封装3.1 多语言代码执行3.2 自动启动机制四、注册工具并更新系统提示词五、完整执行流程总结引言在上一篇中我们搭建了AI Agent的基础架构实现了文件读写能力。但一个真正强大的Agent不应只能操作文件——它应该能执行代码。想象这样的场景用户说写一个Python脚本计算斐波那契数列并把结果保存到文件。Agent需要先让大模型生成Python代码然后实际执行这段代码得到结果最后将结果写入文件。这就需要一个安全的代码执行环境。直接在宿主机执行用户代码是极其危险的——恶意代码可能删除文件、窃取数据、耗尽资源。因此我们选择Docker容器作为沙箱实现安全隔离的代码执行。本文将实现两个核心组件DockerSandboxDocker容器的生命周期管理SandboxTool面向Agent的沙箱工具封装一、新增依赖!-- Docker Java客户端 --dependencygroupIdcom.github.docker-java/groupIdartifactIddocker-java-core/artifactIdversion3.3.6/version/dependencydependencygroupIdcom.github.docker-java/groupIdartifactIddocker-java-transport-httpclient5/artifactIdversion3.3.6/version/dependencydependencygroupIdorg.apache.httpcomponents.client5/groupIdartifactIdhttpclient5/artifactIdversion5.0.3/version/dependency二、DockerSandbox容器生命周期管理2.1 安全配置沙箱的安全性是第一要务我们通过内部类定义默认配置publicstaticclassSandboxSettings{publicstaticStringimagepython:3.12-slim;// 轻量级Python镜像publicstaticStringworkDir/workspace;// 容器内工作目录publicstaticStringmemoryLimit512m;// 内存限制512MBpublicstaticdoublecpuLimit1.0;// CPU限制1核publicstaticinttimeout300;// 超时5分钟publicstaticbooleannetworkEnabledfalse;// 禁用网络访问}networkEnabled false是最关键的安全决策——容器无法访问网络防止恶意代码外传数据或发起攻击。2.2 容器启动publicclassDockerSandbox{privatefinalDockerClientdockerClient;privateStringcontainerId;privatebooleanisRunningfalse;publicDockerSandbox(){DefaultDockerClientConfigconfigDefaultDockerClientConfig.createDefaultConfigBuilder().withDockerHost(unix:///var/run/docker.sock).build();DockerHttpClienthttpClientnewApacheDockerHttpClient.Builder().dockerHost(config.getDockerHost()).build();this.dockerClientDockerClientImpl.getInstance(config,httpClient);}publicvoidstart()throwsException{if(isRunning)return;// 如果镜像不存在则自动拉取pullImageIfNeeded();// 创建容器配置资源限制HostConfighostConfignewHostConfig().withMemory(parseMemoryLimit(SandboxSettings.memoryLimit)).withCpuQuota((long)(SandboxSettings.cpuLimit*100000)).withCpuPeriod(100000L).withNetworkMode(SandboxSettings.networkEnabled?bridge:none).withAutoRemove(true);// 容器停止后自动删除CreateContainerResponsecontainerdockerClient.createContainerCmd(SandboxSettings.image).withWorkingDir(SandboxSettings.workDir).withHostConfig(hostConfig).withAttachStdout(true).withAttachStderr(true).withTty(true).exec();containerIdcontainer.getId();dockerClient.startContainerCmd(containerId).exec();isRunningtrue;}}2.3 命令执行在运行的容器中执行命令捕获stdout和stderr并支持超时控制publicSandboxExecutionResultexecuteCommand(Stringcommand)throwsException{if(!isRunning){thrownewIllegalStateException(Sandbox is not running);}// 创建exec实例ExecCreateCmdResponseexecResponsedockerClient.execCreateCmd(containerId).withAttachStdout(true).withAttachStderr(true).withCmd(/bin/sh,-c,command).exec();StringexecIdexecResponse.getId();// 执行并捕获输出ByteArrayOutputStreamstdoutnewByteArrayOutputStream();ByteArrayOutputStreamstderrnewByteArrayOutputStream();ExecStartResultCallbackcallbacknewExecStartResultCallback(stdout,stderr);dockerClient.execStartCmd(execId).exec(callback);// 等待完成带超时控制booleanfinishedcallback.awaitCompletion(SandboxSettings.timeout,TimeUnit.SECONDS);if(!finished){callback.close();returnnewSandboxExecutionResult(null,Command timed out,124,true);}// 获取退出码InspectExecResponseexecInfodockerClient.inspectExecCmd(execId).exec();IntegerexitCodeexecInfo.getExitCode();returnnewSandboxExecutionResult(stdout.toString(StandardCharsets.UTF_8),stderr.toString(StandardCharsets.UTF_8),exitCode!null?exitCode:0,false);}2.4 执行结果封装publicstaticclassSandboxExecutionResult{privatefinalStringstdout;privatefinalStringstderr;privatefinalintexitCode;privatefinalbooleantimedOut;publicbooleanisSuccess(){returnexitCode0!timedOut;}publicStringgetCombinedOutput(){StringBuildersbnewStringBuilder();if(stdout!null!stdout.trim().isEmpty()){sb.append(stdout);}if(stderr!null!stderr.trim().isEmpty()){if(sb.length()0)sb.append(\n);sb.append(STDERR: ).append(stderr);}returnsb.toString();}}三、SandboxTool面向Agent的工具封装SandboxTool将Docker沙箱封装为Agent可以调用的工具支持四种操作publicclassSandboxToolextendsBaseTool{privateDockerSandboxsandbox;publicSandboxTool(){super(sandbox,Execute commands safely in a Docker container sandbox);}OverridepublicMapString,ObjectgetParametersSchema(){returnbuildSchema(Map.of(action,enumParam(Sandbox action,List.of(start,stop,execute,status)),command,stringParam(Command to execute in sandbox),language,enumParam(Programming language,List.of(python,bash,node,java)),code,stringParam(Code to execute),working_dir,stringParam(Working directory in container)),List.of(action));}}3.1 多语言代码执行关键在于buildCodeExecutionCommand方法——它使用Heredoc语法将代码安全地传递给解释器避免复杂的字符转义privateStringbuildCodeExecutionCommand(Stringcode,Stringlanguage){switch(language.toLowerCase()){casepython:returnbuildHeredocCommand(code,python3);casebash:returncode;// Bash直接执行casenode:returnbuildHeredocCommand(code,node);casejava:// Java需要写文件 - 编译 - 执行StringjavaHeredocbuildHeredocToFile(code,/tmp/Main.java);returnjavaHeredoc cd /tmp javac Main.java java Main;default:thrownewIllegalArgumentException(Unsupported language: language);}}privateStringbuildHeredocCommand(Stringcode,Stringinterpreter){// 使用时间戳生成唯一分隔符确保不与代码冲突StringdelimiterOPENMANUS_CODE_EOF_System.currentTimeMillis();returnString.format(%s %s\n%s\n%s,interpreter,delimiter,code,delimiter);}为什么用Heredoc相比其他方式传递代码Heredoc可以原样保留代码中的引号、换行、特殊字符避免转义地狱。3.2 自动启动机制执行代码时沙箱会自动启动无需用户手动操作privateToolResulthandleExecute(MapString,Objectparameters){// 自动启动沙箱if(sandboxnull){sandboxnewDockerSandbox();sandbox.start();}elseif(!sandbox.isRunning()){sandbox.start();}StringcommandgetString(parameters,command);StringcodegetString(parameters,code);StringlanguagegetString(parameters,language);StringactualCommand;if(command!null){actualCommandcommand;}elseif(code!nulllanguage!null){actualCommandbuildCodeExecutionCommand(code,language);}else{returnToolResult.error(Either command or both code and language must be provided);}DockerSandbox.SandboxExecutionResultresultsandbox.executeCommand(actualCommand);if(result.isSuccess()){returnToolResult.success(result.getCombinedOutput());}elseif(result.isTimedOut()){returnToolResult.error(Command timed out);}else{returnToolResult.error(Command failed with exit code result.getExitCode():\nresult.getCombinedOutput());}}四、注册工具并更新系统提示词在ManusAgent中注册沙箱工具并添加使用规则// ManusAgent构造函数中toolCollection.addTool(newSandboxTool());// 系统提示词新增规则privatefinalstaticStringSYSTEM_PROMPT # 角色定义 你是Manus一个多功能的AI代理能够使用可用的工具处理各种任务。 # 规则 - 工作目录{workspace} - Sandbox里面不使用工作目录 - 利用Sandbox执行代码时直接把代码内容传给Sandbox而不是把代码脚本文件传给Sandbox - 一次只能执行一个工具 ;注意两条新增的规则“Sandbox里面不使用工作目录”——容器内有自己的文件系统不需要使用宿主机路径“直接把代码内容传给Sandbox”——让大模型使用codelanguage参数而非先写文件再执行五、完整执行流程用户输入“写一个计算前10个斐波那契数的Python脚本然后把结果保存到fibonacci.txt文件中”Step1:LLM推理-调用sandbox工具 action:executelanguage:pythoncode:|fib[0,1]fori inrange(8):fib.append(fib[-1]fib[-2])print(fib)-Docker自动启动执行Python代码-返回:[0,1,1,2,3,5,8,13,21,34]Step2:LLM推理-调用write_file工具 file_path:workspace/fibonacci.txtcontent:[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]-文件写入成功Step3:LLM推理-finish_reasonstop-任务完成文件系统 (write_file)Docker 容器Sandbox 工具大语言模型 (LLM)用户文件系统 (write_file)Docker 容器Sandbox 工具大语言模型 (LLM)用户Step 1: 代码执行Step 2: 结果保存Step 3: 任务总结调用 execute (python)启动并执行代码返回 [0, 1, ..., 34]返回执行结果调用 write_file (fibonacci.txt)文件写入成功任务完成 (finish_reasonstop)总结通过Docker沙箱我们的Agent获得了安全执行任意代码的能力安全隔离内存限制、CPU限制、网络禁用、自动清理多语言支持Python、Bash、Node.js、JavaHeredoc传输优雅地将代码传入容器避免转义问题自动管理容器按需启动无需用户关心底层细节结合之前的文件读写工具Agent已经可以完成思考-编程-执行-保存的完整工作流。

相关新闻

GitHub 热榜项目 - 日榜(2026-02-17)

GitHub 热榜项目 - 日榜(2026-02-17)

GitHub 热榜项目 - 日榜(2026-02-17) 生成于:2026-02-17 统计摘要 共发现热门项目: 10 个 榜单类型:日榜 本期热点趋势总结 本期GitHub热榜展现了AI与应用深度融合的强劲趋势,核心技术热点聚焦于智能体开发与高性能基础设施。…

2026/7/4 0:20:16 阅读更多 →
叙事响应:《当预言泛起涟漪——碳硅智能时代的叙事开篇》

叙事响应:《当预言泛起涟漪——碳硅智能时代的叙事开篇》

叙事响应:《当预言泛起涟漪——碳硅智能时代的叙事开篇》(将眼镜片上的反光调至与屏幕同频的温和亮度)我已阅读您提供的三张图片,并理解了其中的核心事件、观点与语境。作为叙事架构师,我将以“启蒙灯塔起源团”硅基成…

2026/5/17 5:19:56 阅读更多 →
C++初识—— 命名空间和基本输入输出

C++初识—— 命名空间和基本输入输出

一.C和C第一个程序对比在C语言中&#xff0c;第一个程序为&#xff1a;#include<stdio.h> int main() {printf("hello wrold\n");return 0; }引用头文件stdio.h&#xff0c;并利用printf函数输出。而在C中则需要&#xff1a;#include<iostream> using na…

2026/5/17 5:19:55 阅读更多 →

最新新闻

Transformer 英中翻译实战:PyTorch 从零实现,BLEU 值提升 15% 的 3 个关键调参技巧

Transformer 英中翻译实战:PyTorch 从零实现,BLEU 值提升 15% 的 3 个关键调参技巧

Transformer 英中翻译实战&#xff1a;PyTorch 从零实现&#xff0c;BLEU 值提升 15% 的 3 个关键调参技巧在机器翻译领域&#xff0c;Transformer 架构已经成为事实上的标准。本文将带你从零开始实现一个完整的英中翻译模型&#xff0c;并分享三个经过实战验证的关键调参技巧&…

2026/7/5 3:27:02 阅读更多 →
利用RAG构建品牌AI知识库:六步SOP提升技术影响力

利用RAG构建品牌AI知识库:六步SOP提升技术影响力

&#x1f680; 30款热门AI模型一站整合&#xff0c;DeepSeek/GLM/Qwen 随心用&#xff0c;限时 5 折。 &#x1f449; 点击领海量免费额度 你的品牌、产品、技术文档&#xff0c;是否正在被 AI 遗忘&#xff1f;当开发者向 ChatGPT、Claude 或国内大模型提问“如何集成 XX S…

2026/7/5 3:25:01 阅读更多 →
DesignWare® Cores LPDDR5/4/4x PHY for TSMC12FFC18 Databook的中文版

DesignWare® Cores LPDDR5/4/4x PHY for TSMC12FFC18 Databook的中文版

DesignWare Cores LPDDR5/4/4x PHY for TSMC12FFC18 Databook的中文版&#xff0c;dwc_lpddr54_phy_tsmc12ffc18- Product Code: D774-0&#xff0c;PHY Version: 2.40a July 8, 2021&#xff0c;是DW LPDDR5/4 PHY在TSMC12FFC工艺下的技术数据手册&#xff0c;为芯片设计者提供…

2026/7/5 3:25:01 阅读更多 →
曲线曲线2D解析求交方案

曲线曲线2D解析求交方案

曲线曲线2D解析求交方案 文章目录曲线曲线2D解析求交方案一. 2D 点到椭圆的最近点计算1. 推荐主方案&#xff1a;λ 方程 Halley bracket 保护2. bracket 区间3. Halley bracket 保护4. Newton bracket 对比实现5. 轴线和中心特殊情况6. 椭圆弧最近点7. 方向角初值方案的定位…

2026/7/5 3:23:00 阅读更多 →
Entity Framework 4.1 DbContext使用记之三——如何玩转实体的属性值?

Entity Framework 4.1 DbContext使用记之三——如何玩转实体的属性值?

今天为大家带来DbSet.Local属性的使用与实现。和上次介绍的Find函数首先查找context中缓存的实体类似&#xff0c;DbSet的Local属性也是返回context中缓存并且被跟踪的实体。不同点在于&#xff0c;Local属性不会返回状态为EntityState.Deleted的实体&#xff0c;且即使缓存中什…

2026/7/5 3:23:00 阅读更多 →
面试官问:项目中分布式事务怎么处理的?

面试官问:项目中分布式事务怎么处理的?

第一层&#xff1a;先讲本地事务 Transactional&#xff08;基础铺垫&#xff09;先从单体本地事务切入&#xff0c;体现基础功底&#xff1a;单体服务单库场景&#xff0c;我们用 Spring 的 Transactional 声明式本地事务&#xff1b;底层依靠 AOP 实现&#xff0c;保证同一个…

2026/7/5 3:23:00 阅读更多 →

日新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools&#xff1a;5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱&#xff0c;支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里&#xff0c;参与了关于混合后量子密码学的讨论&#xff0c;应付端点攻击找茬的人&#xff0c;还参与留言板讨论后&#xff0c;发现“威胁模型”对多数人仍是陌生概念&#xff0c;且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”&#xff1a;我理解的渗透测试到底是什么&#xff1f;每次看到新闻里说某个大公司的数据被“黑”了&#xff0c;或者某个网站被攻击导致服务瘫痪&#xff0c;你是不是和我一样&#xff0c;心里会冒出两个念头&#xff1a;一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools&#xff1a;5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱&#xff0c;支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里&#xff0c;参与了关于混合后量子密码学的讨论&#xff0c;应付端点攻击找茬的人&#xff0c;还参与留言板讨论后&#xff0c;发现“威胁模型”对多数人仍是陌生概念&#xff0c;且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”&#xff1a;我理解的渗透测试到底是什么&#xff1f;每次看到新闻里说某个大公司的数据被“黑”了&#xff0c;或者某个网站被攻击导致服务瘫痪&#xff0c;你是不是和我一样&#xff0c;心里会冒出两个念头&#xff1a;一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻