Hướng dẫn dùng E2B Code Interpreter với Python: Tạo sandbox an toàn cho AI Agent

Artificial Intelligence tutorial - IT technology blog
Artificial Intelligence tutorial - IT technology blog

Hiểm họa khi để LLM tự thực thi mã nguồn

Cho AI quyền chạy code mang lại sức mạnh to lớn. Nhưng nó cũng là cơn ác mộng bảo mật tồi tệ nhất.

Chỉ cần một lỗi logic hoặc prompt injection tinh vi, mô hình có thể vô tình chạy os.system("rm -rf /"). Nguy hiểm hơn, nó có thể đọc sạch biến môi trường chứa database credentials, hoặc tạo vòng lặp vô hạn nuốt trọn 100% CPU máy chủ.

Để cô lập môi trường thực thi, dân kỹ thuật thường cân nhắc ba giải pháp:

  • Tự chạy Docker container: Backend gọi Docker daemon tạo container mới cho mỗi request, đẩy code vào rồi hủy container sau khi xong.
  • Tự vận hành MicroVM (Firecracker / gVisor): Tách biệt kernel hoàn toàn ở tầng ảo hóa phần cứng, giống kiến trúc của AWS Lambda.
  • Cloud Sandbox chuyên dụng (E2B Code Interpreter): Dùng hạ tầng microVM quản lý sẵn qua SDK. Máy ảo Linux khởi động trong khoảng 150-200ms, cài sẵn Python, Jupyter kernel và hỗ trợ upload/download file tức thì qua API.

So sánh thực chiến: Docker, Firecracker hay E2B?

Chúng tôi đã thử nghiệm cả ba phương án trước khi chốt giải pháp cuối cùng.

1. Tự host Docker Engine

Điểm cộng: Miễn phí bản quyền, dùng luôn server hiện có và dễ build image riêng với các thư viện nội bộ.

Điểm trừ: Tốn công quản lý vòng đời. Cold-start của Docker thường mất 1.5 – 3 giây. Nếu 100 người dùng cùng kích hoạt chạy code, disk I/O sẽ nghẽn lập tức. Đáng lo ngại nhất: Docker dùng chung Linux kernel với host. Một lỗ hổng container breakout như CVE-2024-21626 đủ để hacker chiếm toàn bộ máy chủ backend.

2. Tự dựng cụm MicroVM bằng Firecracker

Điểm cộng: An toàn tuyệt đối ở cấp phần cứng. Khởi động siêu nhanh (dưới 50ms).

Điểm trừ: Gánh nặng DevOps rất lớn. Bạn phải tự xử lý virtual networking, cơ chế dọn dẹp ổ đĩa rác, IP pooling và duy trì hệ thống giám sát 24/7. Nếu team bạn dưới 5 người, việc này ngốn quá nhiều thời gian bảo trì.

3. E2B Code Interpreter

Điểm cộng: Tích hợp cực nhanh. Sandbox bật lên sau khoảng 150ms. Môi trường chạy sẵn Jupyter runtime, bóc tách chuẩn xác cả stdout, stderr lẫn hình ảnh biểu đồ (PNG/SVG) dạng base64. Bạn không cần bận tâm chuyện vá lỗi kernel hay scale hạ tầng.

Điểm trừ: Phụ thuộc vào cloud E2B. Nếu xử lý dữ liệu y tế hoặc tài chính bắt buộc on-premise 100%, bạn sẽ cần liên hệ họ để triển khai bản enterprise self-hosted.

Khi nào nên chọn giải pháp nào?

Làm bot nội bộ cho vài đồng nghiệp dùng thử? Một Docker container giới hạn chặt --memory=512m và --cpus=1.0 là đủ dùng.

Nhưng khi mở dịch vụ ra ngoài cho khách hàng trả phí, câu chuyện hoàn toàn khác. Một lỗi bảo mật hay một lần downtime cũng đủ làm mất uy tín dự án. Với trường hợp này, E2B giúp bạn tiết kiệm hàng tuần setup hạ tầng mà vẫn đảm bảo độ trễ thấp và an toàn gần như tuyệt đối.

Từng bước tích hợp E2B Code Interpreter trong Python

Bước 1: Cài đặt SDK và lấy API Key

Tạo tài khoản miễn phí tại e2b.dev để lấy API key. Sau đó, cài đặt SDK vào môi trường làm việc:

pip install e2b-code-interpreter python-dotenv

Tạo file .env tại thư mục gốc dự án:

E2B_API_KEY=e2b_your_actual_api_key_here

Bước 2: Chạy thử đoạn code đầu tiên trong Sandbox

Context manager with Sandbox() sẽ tự động dọn dẹp tài nguyên khi đoạn code hoàn tất:

import os
from dotenv import load_dotenv
from e2b_code_interpreter import Sandbox

load_dotenv()

# Khởi tạo sandbox cách ly
with Sandbox() as sandbox:
    code = """
import math

def calculate_primes(limit):
    primes = []
    for num in range(2, limit):
        if all(num % i != 0 for i in range(2, int(math.sqrt(num)) + 1)):
            primes.append(num)
    return len(primes)

count = calculate_primes(1000)
print(f'Tìm thấy {count} số nguyên tố nhỏ hơn 1000.')
"""
    print("Đang gửi code tới E2B sandbox...")
    execution = sandbox.run_code(code)
    
    # In kết quả stdout
    for log in execution.logs.stdout:
        print("Output:", log)
        
    # Bắt lỗi cú pháp hoặc runtime
    if execution.error:
        print("Lỗi:", execution.error.name, execution.error.value)

Bước 3: Tải file dữ liệu lên và xuất biểu đồ phân tích

AI Agent thường phải đọc file CSV do người dùng upload, tính toán rồi vẽ chart. E2B xử lý việc này rất mượt nhờ hỗ trợ I/O hai chiều:

import base64
from e2b_code_interpreter import Sandbox

with Sandbox() as sandbox:
    # 1. Ghi file CSV trực tiếp vào sandbox
    csv_content = "Thang,DoanhThu\n1,120\n2,150\n3,180\n4,220\n5,210\n6,290"
    sandbox.files.write("data.csv", csv_content)
    
    # 2. Code vẽ biểu đồ bằng matplotlib
    analysis_script = """
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_csv('data.csv')
plt.figure(figsize=(8, 4))
plt.plot(df['Thang'], df['DoanhThu'], marker='o', color='royalblue')
plt.title('Doanh thu 6 tháng đầu năm')
plt.xlabel('Tháng')
plt.ylabel('Triệu VNĐ')
plt.grid(True)
plt.show()
"""
    print("Đang chạy phân tích dữ liệu...")
    execution = sandbox.run_code(analysis_script)
    
    # 3. Lấy ảnh PNG (trả về dưới dạng base64 string) và lưu ra đĩa
    for i, result in enumerate(execution.results):
        if result.png:
            with open(f"chart_{i}.png", "wb") as f:
                f.write(base64.b64decode(result.png))
            print(f"Đã xuất biểu đồ thành công: chart_{i}.png")

Bước 4: Đưa E2B vào vòng lặp Tool Calling của LLM

Để hoàn thiện một Agent thông minh (dùng Claude 3.5 Sonnet hoặc GPT-4o), bạn biến E2B thành một tool thực thi mã nguồn. Luồng hoạt động gồm 5 nhịp:

  1. Người dùng gửi yêu cầu: “Vẽ cho tôi biểu đồ doanh thu theo quý”.
  2. LLM sinh đoạn code Python tương ứng thông qua tool call.
  3. Backend nhận chuỗi code, đẩy vào sandbox.run_code().
  4. Nếu code chạy thành công, kết quả stdout hoặc file ảnh sẽ được gửi ngược lại cho LLM tổng hợp câu trả lời.
  5. Nếu code văng lỗi (traceback), gửi đúng đoạn log lỗi đó cho LLM. Nó sẽ tự đọc traceback, sửa lại code và thử chạy lại (self-debugging).

3 lưu ý sống còn khi đưa lên Production

Đừng vội deploy nếu chưa cấu hình 3 yếu tố sau:

  • Luôn đặt timeout chặt chẽ: Code do AI sinh ra rất dễ dính vòng lặp vô hạn. Hãy luôn truyền run_code(code, timeout=30) để tự động ngắt sau 30 giây, tránh lãng phí chi phí tính toán.
  • Tái sử dụng sandbox theo session: Đừng tạo mới sandbox cho mỗi câu hỏi. Giữ lại sandbox_id trong suốt phiên chat của người dùng. Cách này giúp giữ nguyên trạng thái các biến số, DataFrame và file tạm đã tải lên trước đó.
  • Chủ động kill sandbox: Khi người dùng đóng tab hoặc hết phiên làm việc, hãy gọi sandbox.kill(). Đừng để máy ảo chạy nền không cần thiết gây tiêu hao ngân sách.
Share: