Skip to content

Commit 92d608f

Browse files
Jacksunweicopybara-github
authored andcommitted
feat(integrations): Add E2BEnvironment for remote sandbox workspaces
Merge google#6031 > **Stacked on google#6030** (`fix/experimental-typing`). This PR targets that branch; please review/merge google#6030 first, after which this will be retargeted to `main`. ## Summary Adds `E2BEnvironment`, a `BaseEnvironment` backed by an [E2B](https://e2b.dev) sandbox. It gives agents a persistent remote workspace for shell execution, file CRUD, and on-demand installs (`pip`/`apt`) without touching the host machine. - The sandbox TTL is bounded to cap credit usage and is extended on each operation; an expired idle sandbox is transparently recreated. - Lazy-imports the SDK behind a new `e2b` extra, so the base package stays lean. - Includes a data-analysis sample that downloads a public (GCS-hosted) dataset and analyzes it inside the sandbox. ## Usage ```python from google.adk.integrations.e2b import E2BEnvironment from google.adk.tools.environment import EnvironmentToolset toolset = EnvironmentToolset(environment=E2BEnvironment()) ``` ## Test plan - [x] `pytest tests/unittests/integrations/e2b/` (14 passed) - [x] `pyright src/google/adk/integrations/e2b/_e2b_environment.py` — 0 errors - [x] Sample agent loads (`contributing/samples/environment_and_skills/e2b_environment`) - [ ] Manual run against a live E2B sandbox (requires `E2B_API_KEY`) Co-authored-by: Wei Sun (Jack) <weisun@google.com> COPYBARA_INTEGRATE_REVIEW=google#6031 from google:feat/e2b f2b5584 PiperOrigin-RevId: 929443164
1 parent d9a672e commit 92d608f

7 files changed

Lines changed: 609 additions & 0 deletions

File tree

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# E2B Environment Sample
2+
3+
## Overview
4+
5+
A small data analysis agent that uses the `E2BEnvironment` with the
6+
`EnvironmentToolset` to download public datasets and analyze them inside an
7+
[E2B](https://e2b.dev) remote sandbox.
8+
9+
Instead of running on the local machine, all commands and file operations
10+
execute in an isolated remote sandbox with internet access. Asked a question,
11+
the agent downloads a public dataset (a GCS-hosted world population /
12+
demographics dataset by default), installs `pandas` on demand, writes a short
13+
analysis script, runs it, and reports the result — all without touching the
14+
user's machine. This makes the sandbox a natural fit for running
15+
model-generated code safely and keeping the host clean.
16+
17+
The sandbox has a bounded time-to-live (`timeout`, in seconds) to cap credit
18+
usage. The TTL is reset on every operation, so an actively used workspace never
19+
expires mid-task; after genuine idle it expires and is transparently recreated
20+
on the next operation (note: workspace state such as installed packages and
21+
files is lost on recreation).
22+
23+
## Prerequisites
24+
25+
1. Install the `e2b` extra:
26+
27+
```bash
28+
pip install google-adk[e2b]
29+
```
30+
31+
1. Set your E2B API key (get one at https://e2b.dev):
32+
33+
```bash
34+
export E2B_API_KEY="your-api-key"
35+
```
36+
37+
## Sample Inputs
38+
39+
- `Download the world demographics dataset and tell me which country has the largest population.`
40+
41+
The agent downloads the dataset, installs `pandas`, filters to country-level
42+
rows, and finds the maximum. Expected: China (`CN`), ≈ 1.44 billion, just
43+
ahead of India (`IN`) at ≈ 1.38 billion.
44+
45+
- `For the United States, what is the urban vs rural population split?`
46+
47+
A follow-up to the previous turn. Because the sandbox persists across the
48+
session, the agent reuses the already-downloaded CSV and the installed
49+
`pandas` — it only writes and runs a new script. Expected for `US`: urban
50+
≈ 270.7 million vs rural ≈ 57.6 million (out of ≈ 331 million total).
51+
52+
- `Using https://storage.googleapis.com/cloud-samples-data/bigquery/us-states/us-states.csv, how many US states are listed?`
53+
54+
Demonstrates pointing the agent at your own dataset URL instead of the
55+
default.
56+
57+
## Graph
58+
59+
```mermaid
60+
graph TD
61+
User -->|question| Agent[data_analysis_agent]
62+
Agent -->|EnvironmentToolset| Sandbox[E2BEnvironment sandbox]
63+
Sandbox -->|download / install / run| Agent
64+
Agent -->|answer| User
65+
```
66+
67+
## How To
68+
69+
The agent is a standalone `Agent` (no workflow graph) wired to a single
70+
`EnvironmentToolset` whose `environment` is an `E2BEnvironment`:
71+
72+
```python
73+
from google.adk.integrations.e2b import E2BEnvironment
74+
from google.adk.tools.environment import EnvironmentToolset
75+
76+
EnvironmentToolset(
77+
environment=E2BEnvironment(image="base", timeout=300),
78+
)
79+
```
80+
81+
- `image` selects the E2B template (defaults to the public `base` template).
82+
- `timeout` bounds the sandbox lifetime in seconds to cap credit usage; it is
83+
reset on every operation.
84+
85+
The default GCS-hosted demographics CSV is a standard CSV with a header row.
86+
Each row is one location identified by `location_key`: country-level rows use a
87+
two-letter ISO code (e.g. `US`, `CN`), while subregions use keys containing an
88+
underscore (e.g. `US_CA`). The agent's instruction documents this schema — in
89+
particular, to filter out underscore keys when a question is about countries —
90+
so the generated analysis script parses and aggregates the file correctly.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from . import agent
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""A data analysis agent that runs Python in an E2B remote sandbox."""
16+
17+
from google.adk import Agent
18+
from google.adk.integrations.e2b import E2BEnvironment
19+
from google.adk.tools.environment import EnvironmentToolset
20+
21+
root_agent = Agent(
22+
name="data_analysis_agent",
23+
description=(
24+
"A data analysis agent that downloads public datasets and analyzes"
25+
" them inside an E2B remote sandbox."
26+
),
27+
instruction="""\
28+
You are a data analysis assistant. You work inside an isolated E2B remote
29+
sandbox that has internet access, where you can safely download data and run
30+
Python, so you never touch the user's machine.
31+
32+
To analyze a dataset:
33+
1. Download it from the internet into the working directory, e.g. with
34+
`curl -O <url>` or `wget <url>`. If the user does not give a URL, use the
35+
public world demographics dataset hosted on Google Cloud Storage at
36+
https://storage.googleapis.com/covid19-open-data/v3/demographics.csv
37+
2. Install whatever you need on demand, e.g. `pip install pandas`.
38+
3. Write a short Python script that loads the data and computes the answer.
39+
4. Run the script and report the result, showing the numbers you found.
40+
41+
Notes on the demographics CSV above: it is a proper CSV with a header row.
42+
Each row is one location, identified by `location_key`. Country-level rows use
43+
a two-letter ISO code (e.g. `US`, `CN`, `IN`); subregions use keys containing
44+
an underscore (e.g. `US_CA`), so filter those out when you want countries only.
45+
Useful columns include `population`, `population_male`, `population_female`,
46+
`population_urban`, `population_rural`, and `population_density`.
47+
48+
Prefer writing a script and executing it over guessing. If a command fails,
49+
read the error, fix the script, and try again.
50+
""",
51+
tools=[EnvironmentToolset(environment=E2BEnvironment())],
52+
)

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ optional-dependencies.agent-identity = [
6969
]
7070
optional-dependencies.all = [
7171
"anyio>=4.9,<5",
72+
"e2b>=2,<3",
7273
"google-api-python-client>=2.157,<3",
7374
"google-cloud-aiplatform[agent-engines]>=1.148.1,<2",
7475
"google-cloud-bigquery>=2.2",
@@ -122,6 +123,9 @@ optional-dependencies.docs = [
122123
"sphinx-rtd-theme",
123124
]
124125

126+
optional-dependencies.e2b = [
127+
"e2b>=2,<3", # For E2BEnvironment remote sandbox.
128+
]
125129
optional-dependencies.eval = [
126130
"gepa>=0.1",
127131
"google-cloud-aiplatform[evaluation]>=1.148",
@@ -187,6 +191,7 @@ optional-dependencies.test = [
187191
"anthropic>=0.78", # For anthropic model tests; 0.78 introduced ThinkingConfigAdaptiveParam (required for Claude Opus 4.7).
188192
"anyio>=4.9,<5",
189193
"crewai[tools]; python_version>='3.11' and python_version<'3.12'", # For CrewaiTool tests; chromadb/pypika fail on 3.12+
194+
"e2b>=2,<3",
190195
"gepa>=0.1",
191196
"google-api-python-client>=2.157,<3",
192197
"google-cloud-aiplatform[agent-engines,evaluation]>=1.148.1,<2",
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""E2B sandbox integration.
16+
17+
This module provides a BaseEnvironment implementation backed by an E2B
18+
remote sandbox, offering a persistent remote workspace for file CRUD,
19+
shell execution, and on-demand software installs.
20+
21+
Requires the ``e2b`` extra: ``pip install google-adk[e2b]``.
22+
23+
Example:
24+
```python
25+
from google.adk.integrations.e2b import E2BEnvironment
26+
27+
env = E2BEnvironment(image="base", timeout=300)
28+
await env.initialize()
29+
result = await env.execute("pip install requests")
30+
await env.close()
31+
```
32+
"""
33+
34+
from ._e2b_environment import E2BEnvironment
35+
36+
__all__ = [
37+
'E2BEnvironment',
38+
]

0 commit comments

Comments
 (0)