Skip to content
Guides · Integrations

Give a CrewAI Agent a Code Interpreter That Runs in a MicroVM

Updated October 27, 2026 .md

Short answer: Write a CrewAI BaseTool whose _run sends the agent's Python to a Sandboxer microVM through sandboxer-sdk, then pass it in the agent's tools list. The sandbox starts on the first call and keeps files and packages between calls. CrewAI's own CodeInterpreterTool has been removed, and CrewAI now points you to a sandbox service.

What changed in CrewAI#

CrewAI used to ship a built-in CodeInterpreterTool. Per CrewAI's documentation, it ran code in a Docker container (image code-interpreter:latest), fell back to a restricted Python environment when Docker wasn't available, and had an unsafe_mode that ran code directly on the host. The same page notes that the container can see the current working directory. That page now says the tool has been removed from crewai-tools, that the agent's allow_code_execution and code_execution_mode settings are deprecated, and that you should use a dedicated sandbox service instead.

We checked in crewai 1.15.30: the Agent fields allow_code_execution and code_execution_mode describe themselves as "Deprecated. CodeInterpreterTool is no longer available."

Old CodeInterpreterTool The tool on this page
Where code runs Docker on your machine, or a restricted Python, or the host in unsafe_mode A Sandboxer microVM with its own kernel
What you install locally Docker Nothing beyond crewai and sandboxer-sdk
Can it see your files? The container can see the working directory No; only what you write into the sandbox
Packages libraries_used; not allowed in the restricted fallback libraries_used, installed with pip in the VM
State between calls Not covered in its docs Files and packages stay until you delete the sandbox
Status in current CrewAI Removed A custom BaseTool, the documented extension point

Install#

We used Python 3.12, crewai 1.15.30 and sandboxer-sdk 0.1.1.

python3.12 -m venv venv && . venv/bin/activate
pip install crewai sandboxer-sdk
export SANDBOXER_API_KEY=sbx_live_…

Install sandboxer-sdk, not sandboxer: that PyPI name belongs to an unrelated project. The package imports as sandboxer.

The tool#

This follows CrewAI's custom tool pattern: a BaseTool subclass with a pydantic args_schema and a _run method. The argument names match the old tool's (code, libraries_used), so prompts written for it still fit.

sandbox_tool.py
import shlex
import uuid
from typing import List, Optional, Type

from crewai.tools import BaseTool
from pydantic import BaseModel, Field, PrivateAttr
from sandboxer import Sandbox, Sandboxer


class RunPythonInput(BaseModel):
    code: str = Field(..., description="Python 3 code to run. Print what you want to see.")
    libraries_used: List[str] = Field(
        default_factory=list,
        description="PyPI packages the code needs, installed with pip before it runs.",
    )


class SandboxerCodeInterpreterTool(BaseTool):
    name: str = "sandboxer_code_interpreter"
    description: str = (
        "Runs Python 3 code in an isolated cloud microVM (Ubuntu). "
        "Files and installed packages persist between calls. Returns exit code, stdout and stderr."
    )
    args_schema: Type[BaseModel] = RunPythonInput

    sandbox_name: str = "crewai-code"
    sandbox_type: str = "small"
    ttl_seconds: int = 1800
    timeout_seconds: int = 300

    _client: Optional[Sandboxer] = PrivateAttr(default=None)
    _sandbox: Optional[Sandbox] = PrivateAttr(default=None)

    def _get_sandbox(self) -> Sandbox:
        if self._sandbox is None:
            self._client = Sandboxer()  # reads SANDBOXER_API_KEY
            self._sandbox = self._client.create(
                type=self.sandbox_type, ttl_seconds=self.ttl_seconds, name=self.sandbox_name
            )  # waits until ready
        return self._sandbox

    def _run(self, code: str, libraries_used: Optional[List[str]] = None) -> str:
        sandbox = self._get_sandbox()
        if libraries_used:
            pkgs = " ".join(shlex.quote(p) for p in libraries_used)
            install = sandbox.exec(
                f"pip install -q --break-system-packages {pkgs}", timeout_seconds=self.timeout_seconds
            )
            if install.exit_code != 0:
                return f"pip install failed (exit {install.exit_code})\n{install.stderr[-2000:]}"
        path = f"crewai/{uuid.uuid4().hex[:8]}.py"
        sandbox.files.write(path, code)
        result = sandbox.exec(["python3", path], timeout_seconds=self.timeout_seconds)
        out = f"exit code {result.exit_code}\n{result.stdout}"
        if result.stderr:
            out += f"\nstderr:\n{result.stderr}"
        return out[-8000:]

    def close(self, delete: bool = False) -> None:
        if self._sandbox is not None:
            self._sandbox.delete() if delete else self._sandbox.stop()
            self._sandbox = None

A few choices worth knowing:

  • The code goes in as a file (files.write) and runs as python3 <file>, so it is never pasted into a shell command.
  • A non-zero exit is returned to the agent as text, not raised. The model sees the traceback and can fix its code.
  • ttl_seconds=1800 makes the sandbox stop itself after 30 minutes if your program never calls close().
  • The output is cut to the last 8,000 characters so a noisy script doesn't flood the model's context.

Call it directly#

This is the part we ran on a real small sandbox, without a model: three calls to the tool, the way CrewAI would make them.

tool = SandboxerCodeInterpreterTool()
try:
    print(tool._run(code="import platform, os\nprint(platform.platform())\nprint('user', os.getuid())\nopen('notes.txt','w').write('42')"))
    print(tool.run(code="import os, humanize\nprint(open('notes.txt').read())\nprint(humanize.naturalsize(os.path.getsize('/usr/bin/python3')))", libraries_used=["humanize"]))
    print(tool.run(code="1/0"))
finally:
    tool.close(delete=True)
exit code 0
Linux-6.18.56-sandboxer-x86_64-with-glibc2.39
user 1000

exit code 0
42
8.0 MB

exit code 1

stderr:
Traceback (most recent call last):
  File "/home/user/crewai/e1650c80.py", line 1, in <module>
    1/0
    ~^~
ZeroDivisionError: division by zero

In our single run on October 27, 2026, the first call took 4.7 seconds, including creating the sandbox. The second, which installed humanize and read the file the first call wrote, took 1.9 seconds. The kernel line shows the code ran in the VM, not on the machine running CrewAI.

Attach it to an agent#

Pass the tool in tools=[...] as in CrewAI's tools docs:

from crewai import Agent, Crew, Task
from sandbox_tool import SandboxerCodeInterpreterTool

code_tool = SandboxerCodeInterpreterTool(sandbox_name="crewai-analyst")
analyst = Agent(
    role="Data analyst",
    goal="Answer questions by writing and running Python",
    backstory="You check every number by running code.",
    tools=[code_tool],
)
task = Task(
    description="Compute the 30th Fibonacci number and the sum of primes below 10,000.",
    expected_output="Both numbers, with the code you ran.",
    agent=analyst,
)
crew = Crew(agents=[analyst], tasks=[task])

try:
    print(crew.kickoff())
finally:
    code_tool.close()   # stop: snapshot the disk and stop billing

We built this agent, task and crew with crewai 1.15.30 and confirmed the tool is registered, and that no sandbox is created until the tool is first called. We did not run crew.kickoff(), because it needs a model API key. So there's no model transcript here. The tool calls the model would make are the ones shown above.

Share one sandbox or give each agent its own#

One tool instance means one sandbox. Give two agents the same instance and they share files: one can write data.csv and the other can read it. Give each agent its own instance, with its own sandbox_name, when their work must stay apart.

For a crew that runs again later, keep tool._sandbox.id, and next time reopen it with Sandboxer().get(sandbox_id), calling resume() first if it has stopped. The files and installed packages are still there.

FAQ#

Do I need Docker for this?#

No. The code runs in a Sandboxer microVM in the cloud, so the machine running CrewAI only needs Python and the two packages.

What does a sandbox cost while the crew runs?#

A small sandbox is $0.018/hour, billed per second while it runs. A stopped sandbox costs nothing, so call close() when the crew finishes or let the TTL stop it.

Can the agent install packages?#

Yes. List them in libraries_used and the tool installs them with pip in the VM before it runs the code. They stay installed for later calls to the same sandbox.

Can the agent run shell commands, not just Python?#

Not with this tool as written. Add a second BaseTool that calls sandbox.exec(command), or connect the Sandboxer MCP server for the full tool set.

Does it work with the async API?#

Yes. sandboxer-sdk has AsyncSandboxer with the same methods, and BaseTool has an _arun method you can implement with it.

More guides

Top AI sandbox platforms for code execution in 2026, ranked

For running AI-written code we rank Sandboxer, Freestyle and E2B first: each gives code its own VM with an API or SDK and can pause with memory. Pick Daytona for Windows or GPUs, Modal or Northflank for GPUs at scale, E2B or Northflank to run in your own cloud, and Vercel Sandbox if your app lives on Vercel.

Read the guide
Best sandboxes for running coding agents (Claude Code, Codex, Gemini CLI) in 2026, ranked

For coding agents we rank Sandboxer first: a full Ubuntu VM with Claude Code and Codex preinstalled, Docker, and stop-and-resume that keeps the agent's session in memory. Freestyle and Amp Orbs also keep memory across pauses. Pick E2B for prebuilt agent templates on open source, Docker Sandboxes for free local runs, and Codespaces if you live in GitHub.

Read the guide
Best Daytona sandbox alternatives in 2026, ranked

The best Daytona alternatives depend on why you're switching. For a full Linux microVM on every sandbox with memory-saving stop and Docker, we rank Sandboxer first. E2B suits open source and self-hosting, Modal massive short-job fleets, Northflank bring-your-own-cloud with GPUs, and Vercel Sandbox apps on Vercel.

Read the guide
Best E2B alternatives in 2026, ranked

If you're leaving E2B for longer sessions or a fuller machine, we rank Sandboxer first, then Freestyle: both give each sandbox a full Linux VM that keeps memory across pauses, with Docker and no short session cap. Pick Daytona for Windows or GPUs, Northflank for bring-your-own-cloud, and stay on E2B if you need open source.

Read the guide