最近在开发一个需要AI自动执行代码的智能代理系统时,遇到了一个关键问题:如何在不牺牲功能灵活性的前提下确保系统安全性?经过多轮技术选型和方案验证,最终采用LangChain框架结合Claude Skills,通过沙箱隔离技术实现了安全可靠的代码执行环境。
这个方案最吸引人的地方在于,它完美平衡了功能性和安全性这对看似矛盾的需求。传统AI代码执行要么完全开放导致安全隐患,要么过度限制影响功能实现。而基于沙箱的深度代理方案,让开发者可以放心地赋予AI更多自主权,同时将风险控制在可接受范围内。
LangChain作为当前最流行的AI应用开发框架之一,其核心价值在于提供了标准化的组件接口和灵活的组装能力。在这个方案中,我们主要利用了它的以下几个关键特性:
特别值得一提的是LangChain的Tool抽象,它让我们能够以统一的方式将各种能力(包括代码执行)封装成AI可调用的"技能"。
Claude作为当前最先进的AI模型之一,其Skills功能允许开发者扩展模型的核心能力。在集成过程中,有几个关键点需要注意:
我们通过LangChain的Custom Tool机制,将Claude Skills封装成标准的Tool接口,实现了与框架的无缝集成。
安全执行是整套方案的核心所在。我们采用了多层防护策略:
具体实现上,我们开发了一个专门的SandboxExecutor组件,它负责:
首先需要搭建基础环境:
bash复制# 安装核心依赖
pip install langchain anthropic docker
# 配置Docker(需要提前安装)
sudo usermod -aG docker $USER
newgrp docker
然后创建配置文件config.yaml:
yaml复制sandbox:
timeout: 30
memory_limit: "512m"
cpu_shares: 512
network_disabled: true
claude:
api_key: "your_api_key"
model: "claude-3-opus-20240229"
python复制import docker
from typing import Optional
class SandboxExecutor:
def __init__(self, config: dict):
self.client = docker.from_env()
self.config = config
def execute(self, code: str, lang: str = "python") -> str:
try:
container = self.client.containers.run(
image=f"{lang}-sandbox",
command=f"python -c '{code}'",
mem_limit=self.config["memory_limit"],
cpu_shares=self.config["cpu_shares"],
network_disabled=self.config["network_disabled"],
detach=True
)
try:
result = container.wait(timeout=self.config["timeout"])
logs = container.logs().decode("utf-8")
container.remove()
return logs
except Exception as e:
container.remove(force=True)
raise RuntimeError(f"Execution failed: {str(e)}")
except docker.errors.DockerException as e:
raise RuntimeError(f"Sandbox initialization failed: {str(e)}")
python复制from langchain.tools import BaseTool
from anthropic import Anthropic
class ClaudeSkillTool(BaseTool):
name = "claude_skill"
description = "Execute code in a secure sandbox environment"
def __init__(self, config: dict):
super().__init__()
self.client = Anthropic(api_key=config["api_key"])
self.sandbox = SandboxExecutor(config["sandbox"])
def _run(self, code: str) -> str:
# 安全检查
if not self._validate_code(code):
return "Code validation failed"
try:
# 执行代码
result = self.sandbox.execute(code)
# 结果过滤
safe_result = self._filter_output(result)
return safe_result
except Exception as e:
return f"Error: {str(e)}"
def _validate_code(self, code: str) -> bool:
# 实现代码安全检查逻辑
return True
def _filter_output(self, output: str) -> str:
# 实现输出过滤逻辑
return output
python复制from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_anthropic import ChatAnthropic
from langchain_core.prompts import ChatPromptTemplate
def create_agent(config: dict):
# 初始化LLM
llm = ChatAnthropic(
model=config["model"],
temperature=0.3,
max_tokens=2048
)
# 创建工具集
tools = [ClaudeSkillTool(config)]
# 定义提示模板
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful AI assistant with code execution capabilities."),
("user", "{input}"),
("placeholder", "{agent_scratchpad}")
])
# 创建代理
agent = create_tool_calling_agent(llm, tools, prompt)
# 返回执行器
return AgentExecutor(
agent=agent,
tools=tools,
verbose=True,
handle_parsing_errors=True
)
在实际应用中,我们发现仅靠沙箱隔离还不够,还需要在代码执行前进行严格检查:
os.system、subprocess等)实现示例:
python复制import ast
class CodeValidator:
BLACKLIST = [
"os.system", "subprocess", "eval", "exec",
"open", "__import__", "compile"
]
@classmethod
def validate(cls, code: str) -> bool:
try:
tree = ast.parse(code)
for node in ast.walk(tree):
if isinstance(node, ast.Call):
func_name = cls._get_func_name(node.func)
if func_name in cls.BLACKLIST:
return False
# 其他检查规则...
return True
except:
return False
@staticmethod
def _get_func_name(node) -> str:
if isinstance(node, ast.Name):
return node.id
elif isinstance(node, ast.Attribute):
return f"{node.value.id}.{node.attr}"
return ""
优化后的执行器实现:
python复制from threading import Lock
import time
class OptimizedSandboxExecutor(SandboxExecutor):
def __init__(self, config: dict):
super().__init__(config)
self.pool = []
self.lock = Lock()
self._init_pool()
def _init_pool(self):
"""初始化容器池"""
for _ in range(3): # 预热3个容器
container = self.client.containers.create(
image="python-sandbox",
detach=True,
mem_limit=self.config["memory_limit"],
cpu_shares=self.config["cpu_shares"],
network_disabled=self.config["network_disabled"]
)
self.pool.append(container)
def execute(self, code: str, lang: str = "python") -> str:
with self.lock:
if not self.pool:
container = self.client.containers.create(
image=f"{lang}-sandbox",
detach=True,
mem_limit=self.config["memory_limit"],
cpu_shares=self.config["cpu_shares"],
network_disabled=self.config["network_disabled"]
)
else:
container = self.pool.pop()
try:
container.start()
exit_code, output = container.exec_run(
cmd=["python", "-c", code],
demux=True
)
if exit_code != 0:
raise RuntimeError(f"Execution failed with code {exit_code}")
return output[0].decode("utf-8") if output[0] else ""
finally:
with self.lock:
if len(self.pool) < 5: # 保持最多5个容器在池中
self.pool.append(container)
else:
container.remove(force=True)
通过这个系统,我们可以让AI自动处理数据分析任务:
python复制agent = create_agent(config)
result = agent.invoke({
"input": "请分析这份销售数据,计算每个月的销售额总和并绘制趋势图。数据如下:..."
})
print(result["output"])
AI会自动:
研究人员可以快速验证算法思路:
python复制result = agent.invoke({
"input": "请实现一个快速排序算法,并用这个测试数据验证:[5,3,8,4,2,7,1,10]"
})
print(result["output"])
系统会返回排序结果和执行时间等详细信息。
现象:代码执行时间超过配置的超时限制
解决方案:
现象:容器内存使用持续增长
解决方案:
现象:代码需要特定第三方库
解决方案:
完善的监控是确保系统可靠运行的关键:
python复制from prometheus_client import start_http_server, Gauge
class Monitor:
exec_time = Gauge("sandbox_execution_time", "Execution time in seconds")
exec_count = Gauge("sandbox_execution_count", "Total execution count")
error_count = Gauge("sandbox_error_count", "Error count")
@classmethod
def start(cls, port=8000):
start_http_server(port)
@classmethod
def record_execution(cls, duration: float, success: bool):
cls.exec_time.set(duration)
cls.exec_count.inc()
if not success:
cls.error_count.inc()
使用时:
python复制Monitor.start()
start = time.time()
try:
result = executor.execute(code)
Monitor.record_execution(time.time()-start, True)
except:
Monitor.record_execution(time.time()-start, False)
raise
这套监控系统可以帮助我们:
当前系统主要支持Python,可以扩展支持更多语言:
对于大规模应用,可以考虑:
增强开发者体验:
在实际项目中,我们发现这套架构不仅能用于代码执行场景,经过适当改造后,还可以应用于:
关键是要根据具体需求调整安全策略和执行环境配置,在灵活性和安全性之间找到最佳平衡点。