Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ limitations under the License.

✨ **Simplicity**: the logic for agents fits in ~1,000 lines of code (see [agents.py](https://github.com/huggingface/smolagents/blob/main/src/smolagents/agents.py)). We kept abstractions to their minimal shape above raw code!

🧑‍💻 **First-class support for Code Agents**. Our [`CodeAgent`](https://huggingface.co/docs/smolagents/reference/agents#smolagents.CodeAgent) writes its actions in code (as opposed to "agents being used to write code"). To make it secure, we support executing in sandboxed environments via [E2B](https://e2b.dev/), [Modal](https://modal.com/), Docker, or Pyodide+Deno WebAssembly sandbox.
🧑‍💻 **First-class support for Code Agents**. Our [`CodeAgent`](https://huggingface.co/docs/smolagents/reference/agents#smolagents.CodeAgent) writes its actions in code (as opposed to "agents being used to write code"). To make it secure, we support executing in sandboxed environments via [Blaxel](https://blaxel.ai), [E2B](https://e2b.dev/), [Modal](https://modal.com/), Docker, or Pyodide+Deno WebAssembly sandbox.

🤗 **Hub integrations**: you can [share/pull tools or agents to/from the Hub](https://huggingface.co/docs/smolagents/reference/tools#smolagents.Tool.from_hub) for instant sharing of the most efficient agents!

Expand Down Expand Up @@ -228,7 +228,7 @@ Writing actions as code snippets is demonstrated to work better than the current

Especially, since code execution can be a security concern (arbitrary code execution!), we provide options at runtime:
- a secure python interpreter to run code more safely in your environment (more secure than raw code execution but still risky)
- a sandboxed environment using [E2B](https://e2b.dev/) or Docker (removes the risk to your own system).
- a sandboxed environment using [Blaxel](https://blaxel.ai), [E2B](https://e2b.dev/), or Docker (removes the risk to your own system).

Alongside [`CodeAgent`](https://huggingface.co/docs/smolagents/reference/agents#smolagents.CodeAgent), we also provide the standard [`ToolCallingAgent`](https://huggingface.co/docs/smolagents/reference/agents#smolagents.ToolCallingAgent) which writes actions as JSON/text blobs. You can pick whichever style best suits your use case.

Expand All @@ -254,7 +254,7 @@ This comparison shows that open-source models can now take on the best closed mo
## Security

Security is a critical consideration when working with code-executing agents. Our library provides:
- Sandboxed execution options using [E2B](https://e2b.dev/), [Modal](https://modal.com/), Docker, or Pyodide+Deno WebAssembly sandbox
- Sandboxed execution options using [Blaxel](https://blaxel.ai), [E2B](https://e2b.dev/), [Modal](https://modal.com/), Docker, or Pyodide+Deno WebAssembly sandbox
- Best practices for running agent code securely

For security policies, vulnerability reporting, and more information on secure agent execution, please see our [Security Policy](SECURITY.md).
Expand Down
2 changes: 1 addition & 1 deletion docs/source/en/guided_tour.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ This could also be authorized by using `numpy.*`, which will allow `numpy` as we

The execution will stop at any code trying to perform an illegal operation or if there is a regular Python error with the code generated by the agent.

You can also use [E2B code executor](https://e2b.dev/docs#what-is-e2-b) or Docker instead of a local Python interpreter. For E2B, first [set the `E2B_API_KEY` environment variable](https://e2b.dev/dashboard?tab=keys) and then pass `executor_type="e2b"` upon agent initialization. For Docker, pass `executor_type="docker"` during initialization.
You can also use [Blaxel](https://blaxel.ai), [E2B](https://e2b.dev/docs#what-is-e2-b), or Docker instead of a local Python interpreter. For Blaxel, first [set the `BL_API_KEY` and `BL_WORKSPACE` environment variables](https://app.blaxel.ai/profile/security) and then pass `executor_type="blaxel"` upon agent initialization. For E2B, first [set the `E2B_API_KEY` environment variable](https://e2b.dev/dashboard?tab=keys) and then pass `executor_type="e2b"`. For Docker, pass `executor_type="docker"`.


> [!TIP]
Expand Down
2 changes: 1 addition & 1 deletion docs/source/en/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Key features of `smolagents` include:

✨ **Simplicity**: The logic for agents fits in ~thousand lines of code. We kept abstractions to their minimal shape above raw code!

🧑‍💻 **First-class support for Code Agents**: [`CodeAgent`](reference/agents#smolagents.CodeAgent) writes its actions in code (as opposed to "agents being used to write code") to invoke tools or perform computations, enabling natural composability (function nesting, loops, conditionals). To make it secure, we support [executing in sandboxed environment](tutorials/secure_code_execution) via [E2B](https://e2b.dev/) or via Docker.
🧑‍💻 **First-class support for Code Agents**: [`CodeAgent`](reference/agents#smolagents.CodeAgent) writes its actions in code (as opposed to "agents being used to write code") to invoke tools or perform computations, enabling natural composability (function nesting, loops, conditionals). To make it secure, we support [executing in sandboxed environment](tutorials/secure_code_execution) via [Blaxel](https://blaxel.ai), [E2B](https://e2b.dev/), or Docker.

📡 **Common Tool-Calling Agent Support**: In addition to CodeAgents, [`ToolCallingAgent`](reference/agents#smolagents.ToolCallingAgent) supports usual JSON/text-based tool-calling for scenarios where that paradigm is preferred.

Expand Down
16 changes: 12 additions & 4 deletions docs/source/en/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,24 +180,32 @@ Extras for handling different types of media and input:
Extras for executing code remotely:
<hfoptions id="installation">
<hfoption id="pip">
- **docker**: Add support for executing code in Docker containers.
- **blaxel**: Add support for Blaxel sandboxes - fast-launching VMs with hibernation (recommended).
```bash
pip install "smolagents[docker]"
pip install "smolagents[blaxel]"
```
- **e2b**: Enable E2B support for remote execution.
```bash
pip install "smolagents[e2b]"
```
- **docker**: Add support for executing code in Docker containers.
```bash
pip install "smolagents[docker]"
```
</hfoption>
<hfoption id="uv">
- **docker**: Add support for executing code in Docker containers.
- **blaxel**: Add support for Blaxel sandboxes - fast-launching VMs with hibernation (recommended).
```bash
uv pip install "smolagents[docker]"
uv pip install "smolagents[blaxel]"
```
- **e2b**: Enable E2B support for remote execution.
```bash
uv pip install "smolagents[e2b]"
```
- **docker**: Add support for executing code in Docker containers.
```bash
uv pip install "smolagents[docker]"
```
</hfoption>
</hfoptions>

Expand Down
4 changes: 4 additions & 0 deletions docs/source/en/reference/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ Smolagents use memory to store information across multiple steps.

[[autodoc]] smolagents.remote_executors.RemotePythonExecutor

#### BlaxelExecutor

[[autodoc]] smolagents.remote_executors.BlaxelExecutor

#### E2BExecutor

[[autodoc]] smolagents.remote_executors.E2BExecutor
Expand Down
40 changes: 37 additions & 3 deletions docs/source/en/tutorials/secure_code_execution.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,13 +118,46 @@ When working with AI agents that execute code, security is paramount. There are

![Sandbox approaches comparison](https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/smolagents/sandboxed_execution.png)

1. **Running individual code snippets in a sandbox**: This approach (left side of diagram) only executes the agent-generated Python code snippets in a sandbox while keeping the rest of the agentic system in your local environment. It's simpler to set up using `executor_type="e2b"`, `executor_type="modal"`, or
1. **Running individual code snippets in a sandbox**: This approach (left side of diagram) only executes the agent-generated Python code snippets in a sandbox while keeping the rest of the agentic system in your local environment. It's simpler to set up using `executor_type="blaxel"`, `executor_type="e2b"`, `executor_type="modal"`, or
`executor_type="docker"`, but it doesn't support multi-agents and still requires passing state data between your environment and the sandbox.

2. **Running the entire agentic system in a sandbox**: This approach (right side of diagram) runs the entire agentic system, including the agent, model, and tools, within a sandbox environment. This provides better isolation but requires more manual setup and may require passing sensitive credentials (like API keys) to the sandbox environment.

This guide describes how to set up and use both types of sandbox approaches for your agent applications.

### Blaxel setup

#### Installation

1. Create a Blaxel account at [blaxel.ai](https://blaxel.ai)
2. Install the required packages:
```bash
pip install 'smolagents[blaxel]'
```

#### Running your agent with Blaxel: quick start

We provide a simple way to use a Blaxel Sandbox: simply add `executor_type="blaxel"` to the agent initialization, as follows:

```py
from smolagents import InferenceClientModel, CodeAgent

with CodeAgent(model=InferenceClientModel(), tools=[], executor_type="blaxel") as agent:
agent.run("Can you give me the 100th Fibonacci number?")
```

> [!TIP]
> Using the agent as a context manager (with the `with` statement) ensures that the Blaxel sandbox is cleaned up immediately after the agent completes its task.
> Alternatively, you can manually call the agent's `cleanup()` method.

This solution sends the agent state to the server at the start of each `agent.run()`.
Then the models are called from the local environment, but the generated code will be sent to the sandbox for execution, and only the output will be returned.

Blaxel provides fast-launching virtual machines that start from hibernation in under 25ms and scale back to zero after inactivity while maintaining memory state, making it an excellent choice for agent applications that require quick, secure code execution.

> [!TIP]
> For even stronger security isolation, you can host your entire agent remotely on Blaxel. This provides complete sandboxing of the agent, model, and tools. See the [Blaxel agent hosting documentation](https://docs.blaxel.ai/Agents/Develop-an-agent-py) for details.

### E2B setup

#### Installation
Expand Down Expand Up @@ -423,7 +456,7 @@ agent.run("Can you give me the 100th Fibonacci number?")

### Best practices for sandboxes

These key practices apply to both E2B and Docker sandboxes:
These key practices apply to Blaxel, E2B, and Docker sandboxes:

- Resource management
- Set memory and CPU limits
Expand All @@ -449,9 +482,10 @@ As illustrated in the diagram earlier, both sandboxing approaches have different

### Approach 1: Running just the code snippets in a sandbox
- **Pros**:
- Easier to set up with a simple parameter (`executor_type="e2b"` or `executor_type="docker"`)
- Easier to set up with a simple parameter (`executor_type="blaxel"`, `executor_type="e2b"`, or `executor_type="docker"`)
- No need to transfer API keys to the sandbox
- Better protection for your local environment
- Fast execution with Blaxel's hibernation technology (<25ms startup)
- **Cons**:
- Doesn't support multi-agents (managed agents)
- Still requires transferring state between your environment and the sandbox
Expand Down
5 changes: 5 additions & 0 deletions examples/sandboxed_execution.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@

model = InferenceClientModel()

# Blaxel executor example
with CodeAgent(tools=[WebSearchTool()], model=model, executor_type="blaxel") as agent:
output = agent.run("How many seconds would it take for a leopard at full speed to run through Pont des Arts?")
print("Blaxel executor result:", output)

# Docker executor example
with CodeAgent(tools=[WebSearchTool()], model=model, executor_type="docker") as agent:
output = agent.run("How many seconds would it take for a leopard at full speed to run through Pont des Arts?")
Expand Down
5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ dependencies = [
bedrock = [
"boto3>=1.36.18"
]
blaxel = [
"blaxel>=0.2.19",
]
torch = [
"torch",
"torchvision",
Expand Down Expand Up @@ -85,7 +88,7 @@ vllm = [
"torch"
]
all = [
"smolagents[audio,docker,e2b,gradio,litellm,mcp,mlx-lm,modal,openai,telemetry,toolkit,transformers,vision,bedrock]",
"smolagents[audio,blaxel,docker,e2b,gradio,litellm,mcp,mlx-lm,modal,openai,telemetry,toolkit,transformers,vision,bedrock]",
]
quality = [
"ruff>=0.9.0",
Expand Down
9 changes: 5 additions & 4 deletions src/smolagents/agents.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
LogLevel,
Monitor,
)
from .remote_executors import DockerExecutor, E2BExecutor, ModalExecutor, WasmExecutor
from .remote_executors import BlaxelExecutor, DockerExecutor, E2BExecutor, ModalExecutor, WasmExecutor
from .tools import BaseTool, Tool, validate_tool_arguments
from .utils import (
AgentError,
Expand Down Expand Up @@ -1490,7 +1490,7 @@ class CodeAgent(MultiStepAgent):
prompt_templates ([`~agents.PromptTemplates`], *optional*): Prompt templates.
additional_authorized_imports (`list[str]`, *optional*): Additional authorized imports for the agent.
planning_interval (`int`, *optional*): Interval at which the agent will run a planning step.
executor_type (`Literal["local", "e2b", "modal", "docker", "wasm"]`, default `"local"`): Type of code executor.
executor_type (`Literal["local", "blaxel", "e2b", "modal", "docker", "wasm"]`, default `"local"`): Type of code executor.
executor_kwargs (`dict`, *optional*): Additional arguments to pass to initialize the executor.
max_print_outputs_length (`int`, *optional*): Maximum length of the print outputs.
stream_outputs (`bool`, *optional*, default `False`): Whether to stream outputs during execution.
Expand All @@ -1508,7 +1508,7 @@ def __init__(
prompt_templates: PromptTemplates | None = None,
additional_authorized_imports: list[str] | None = None,
planning_interval: int | None = None,
executor_type: Literal["local", "e2b", "modal", "docker", "wasm"] = "local",
executor_type: Literal["local", "blaxel", "e2b", "modal", "docker", "wasm"] = "local",
executor_kwargs: dict[str, Any] | None = None,
max_print_outputs_length: int | None = None,
stream_outputs: bool = False,
Expand Down Expand Up @@ -1556,7 +1556,7 @@ def __init__(
"Caution: you set an authorization for all imports, meaning your agent can decide to import any package it deems necessary. This might raise issues if the package is not installed in your environment.",
level=LogLevel.INFO,
)
if executor_type not in {"local", "e2b", "modal", "docker", "wasm"}:
if executor_type not in {"local", "blaxel", "e2b", "modal", "docker", "wasm"}:
raise ValueError(f"Unsupported executor type: {executor_type}")
self.executor_type = executor_type
self.executor_kwargs: dict[str, Any] = executor_kwargs or {}
Expand All @@ -1583,6 +1583,7 @@ def create_python_executor(self) -> PythonExecutor:
if self.managed_agents:
raise Exception("Managed agents are not yet supported with remote code execution.")
remote_executors = {
"blaxel": BlaxelExecutor,
"e2b": E2BExecutor,
"docker": DockerExecutor,
"wasm": WasmExecutor,
Expand Down
Loading