Skip to main content
CrewAI is a Python framework for building crews of agents that work through tasks with tools. Back an agent’s tools with sandbox.commands.run and sandbox.files so every command the model runs, and every file it writes, stays in an isolated VM instead of on your server. The model API key stays in your app; the sandbox never sees it.

Setup

CrewAI needs Python 3.10 to 3.13. The examples use Anthropic through CrewAI’s native provider, which reads the key from the environment. To use another provider, install its extra if it has one, set its API key, and change llm. For example, set OPENAI_API_KEY and pass "openai/gpt-5.5"; OpenAI needs no extra. See LLMs in the CrewAI docs for the full list, and API keys to create a Superserve API key.

Wire the sandbox into the agent

The highlighted block defines a bash tool backed by the sandbox. Everything else is standard CrewAI usage. The tool looks up sandbox only when the model calls it, so the sandbox is created after the rest of the setup, right before the try block that kills it.
The tool returns the SDK’s CommandResult. CrewAI reads the return annotation and sends the model stdout, stderr, exit_code, and truncated as JSON, so the model sees failed commands as well as their output.

Run code with file tools

Add file tools next to bash to let the model write a script, run it, and read the result. max_iter caps the iterations the agent runs on a task (the default is 25). After that, the agent must give its best answer.
With verbose=True, the crew prints each tool call and its result. Output from a run with claude-haiku-4-5 (trimmed, with the panel borders removed; the model’s wording varies):
sandbox.files paths must be absolute. See Read & write files for binary content and directory downloads.

Stream tool calls

Set stream=True on the crew, and kickoff() returns a CrewStreamingOutput that yields the model’s text as it arrives. To show each command and its result, listen for ToolUsageFinishedEvent on the CrewAI event bus.
kickoff() is typed as CrewOutput | CrewStreamingOutput, so the assert narrows the type for type checkers. Read streaming.result after the loop for the final CrewOutput. The event handler is registered globally, so it runs for every crew in the process. CrewAI runs it on a worker thread, so its output can interleave with the streamed text. A tool call that raises, such as a command that exceeds its timeout, emits ToolUsageErrorEvent instead. See Streaming Crew Execution and Event Listeners in the CrewAI docs, and Streaming to stream a single command’s output.

One sandbox per conversation

The examples above close over one module-level sandbox. To serve many conversations, build the crew for a given sandbox. Store sandbox.id with the conversation, reconnect on each run, and pause between runs so files and installed packages stay available without paying for an idle VM.
Sandbox.connect() resumes a paused sandbox, or one that is still pausing, before it returns. See Lifecycle and Connect. The second run finds the file because it lives in the sandbox, not because the crew remembers the first run. To keep context between runs too, give the crew CrewAI memory scoped to the conversation, for example memory=Memory(llm="anthropic/claude-sonnet-5-5").scope(f"/conversation/{sandbox.id}") with Memory imported from crewai. Memory also needs an embedding model. The default is OpenAI’s, so set OPENAI_API_KEY or pass an embedder to Memory. Do not use memory=True here: crews without a name share one memory scope, so context can leak between conversations.

Good to know

  • The model can call only the tools you define. Keep kill(), pause(), and update() in your application code, not in a tool.
  • To limit what model-written code can reach, create the sandbox with network rules.
  • Pass timeout_seconds to commands.run. Without it, the SDK request times out after 30 seconds, so the tool call fails on longer commands such as package installs.
  • The default sandbox has python3 but no python. Tell the agent in its backstory, or use a template with the tools you need.
  • As a backstop for crashes, set timeout_seconds and auto_delete_seconds when you create the sandbox. See Auto-delete.

Resources

CrewAI docs

Agents, tasks, crews, tools, and flows in CrewAI.

Run commands

Options for commands.run, including environment variables and working directory.