# CrewAI (/docs/agents/crewai)

<!-- agent-signals: reading_time_min: 3 · est_tokens: 988 · updated: 2026-07-30 -->
Related: [Amp](/docs/agents/amp.md), [Claude Code](/docs/agents/claude-code.md), [Claude Managed Agents](/docs/agents/claude-managed-agents.md), [Codex](/docs/agents/codex.md), [Crabbox with E2B](/docs/agents/crabbox.md), [Devin](/docs/agents/devin.md)

[CrewAI](https://www.crewai.com/) is a framework for building agents and
multi-agent workflows. Its native
[`E2BPythonTool`](https://docs.crewai.com/en/tools/ai-ml/e2bsandboxtools)
runs agent-generated Python in an isolated E2B Code Interpreter sandbox instead
of executing it on your host.

## Install the dependencies [#install-the-dependencies]

Install CrewAI with its E2B tool dependencies:

```bash
pip install "crewai-tools[e2b]" python-dotenv
```

Set API keys for E2B and your model provider:

```bash
export E2B_API_KEY="e2b_..."
export OPENAI_API_KEY="..."
```

## Run a data analysis agent [#run-a-data-analysis-agent]

Create one persistent tool instance and give it to the agent. Persistent mode
lets the Python kernel retain imports and variables if the agent needs to retry
its work.

```python
import os

from crewai import Agent, Crew, Process, Task
from crewai_tools import E2BPythonTool


python_tool = E2BPythonTool(
    persistent=True,
    sandbox_timeout=600,
)

analyst = Agent(
    role="Data Analyst",
    goal="Use sandboxed Python to produce accurate, reproducible analysis",
    backstory=(
        "You verify every numerical answer by running code in an isolated "
        "E2B sandbox."
    ),
    tools=[python_tool],
    llm=os.getenv("MODEL", "openai/gpt-4.1-mini"),
    allow_delegation=False,
    max_iter=8,
    verbose=True,
)

task = Task(
    description="""
Use the E2B Sandbox Python tool to run Python code. Create `random.Random(23)`,
generate 10,000 integers with `randint(1, 1000)`, and return a JSON object with
their count, mean, population standard deviation, p95, and SHA-256 digest.
Inspect the tool result's `error` field and correct and rerun failed code.
Do not estimate the answer yourself.
""",
    expected_output="A JSON object containing the computed statistics.",
    agent=analyst,
)

crew = Crew(
    agents=[analyst],
    tasks=[task],
    process=Process.sequential,
    verbose=True,
)

try:
    result = crew.kickoff()
    print(result)
finally:
    python_tool.close()
```

The complete runnable version, including environment validation and locked
dependencies, is available in the
[E2B cookbook](https://github.com/e2b-dev/e2b-cookbook/tree/main/examples/crewai-python).

## Sandbox lifecycle [#sandbox-lifecycle]

By default, an E2B CrewAI tool creates and closes a sandbox for every tool call.
Use `persistent=True` only when an agent needs state across calls. A persistent
tool creates its sandbox lazily and reuses it until it is closed.

Call `close()` in `finally` so cleanup runs after both successful and failed
crew executions. If you pass an existing `sandbox_id`, your application owns
that sandbox and the tool will not close it.

Keep `sandbox_timeout` as short as the workload allows. CrewAI applies it when
the tool creates or connects to the sandbox and does not refresh it after each
tool call. The tool's per-execution `timeout` separately controls how long an
individual code execution may run.

## Results and errors [#results-and-errors]

`E2BPythonTool` returns structured data:

```json
{
  "text": "...",
  "stdout": [],
  "stderr": [],
  "error": null,
  "results": [],
  "execution_count": 1
}
```

Tell the agent to check `error` before accepting an answer. If code execution
fails, the agent can inspect the error, correct the code, and run it again in
the same persistent sandbox.

## Security considerations [#security-considerations]

E2B isolates agent-generated code from the machine running CrewAI. The sandbox
still processes model-generated inputs and produces untrusted output:

* do not expose API keys or other host secrets to the sandbox unless required;
* use persistent mode only when state must survive between calls;
* explicitly close sandboxes owned by the tool;
* use bounded sandbox and execution timeouts;
* validate tool output before using it in another trusted system.

Learn more about [E2B sandbox lifecycle](/docs/sandbox).
