## Summary Follow-up to #1688. Three fixes on the `network.egressProxy` / `network["egress_proxy"]` paths a caller reaches by bypassing the types, plus the one changelog snippet that does not run. **The guards disagreed.** Python raised `InvalidArgumentException` for a proxy without a string `address`; JS had none, and since `buildEgressProxyBody` rebuilds the body from the known fields, an address that isn't there simply vanished and the caller got an API error about a `{}` they never wrote. Nothing leaked — `address` is `required` in the spec, so all of these already failed closed at the API — but the error named the wrong thing. ```ts function buildEgressProxyBody(egressProxy: SandboxEgressProxyOpts) { + if (!isPlainObject(egressProxy) || typeof egressProxy.address !== 'string') { + throw new InvalidArgumentError( + `network egressProxy must be an object with a string 'address' (e.g. 'proxy.example.com:1080').` + ) + } ``` | caller passes | JS before | JS now | Python | |---|---|---|---| | `{}` | `{"egressProxy":{}}` | `InvalidArgumentError` | `InvalidArgumentException` | | `{address: 1080}` | `{"egressProxy":{"address":1080}}` | `InvalidArgumentError` | `InvalidArgumentException` | | `'proxy.example.com:1080'` | `{"egressProxy":{}}` — address dropped | `InvalidArgumentError` | `InvalidArgumentException` | **`null` credentials reached the wire.** Both SDKs checked `!== undefined` / `in`, so a `null` / `None` username or password serialized as a JSON null the API rejects (`type: string`). Reading a credential out of an unset environment variable is the way to land there, and it is the one case where the caller means "this proxy takes no credentials" — both now skip a nullish credential (`!= null` in JS, `.get(...) is not None` in Python). ```ts await Sandbox.create({ network: { egressProxy: { address: 'proxy.example.com:1080', // Unset in the environment; the proxy takes no credentials. username: process.env.PROXY_USER, }, }, }) ``` ```python Sandbox.create( network={ "egress_proxy": { "address": "proxy.example.com:1080", "username": os.environ.get("PROXY_USER"), }, }, ) ``` **The published `get_info` snippet.** The 2.41.0 entry in both changelogs printed `info.network["egress_proxy"]`, but `SandboxInfo.network` is `Optional` and `egress_proxy` is `NotRequired` — pyright rejects it (`reportOptionalSubscript`, `reportTypedDictNotRequiredAccess`) and it raises at runtime for a sandbox without a proxy, unlike the TS line right above it (`info.network?.egressProxy`). It now reads `print((info.network or {}).get("egress_proxy"))`. Tests cover the three rejected JS shapes and the null credentials in both SDKs. Link to Devin session: https://app.devin.ai/sessions/216bb02ad7924e4ba5f2968aaadc7938 Requested by: @mishushakov --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: mish@e2b.dev <mish@e2b.dev>
What is E2B?
E2B is an open-source infrastructure that allows you to run AI-generated code in secure isolated sandboxes in the cloud. To start and control sandboxes, use our JavaScript SDK or Python SDK.
Run your first Sandbox
1. Install SDK
pip install e2b
2. Get your E2B API key
E2B_API_KEY=e2b_***
3. Start a sandbox and run commands
from e2b import Sandbox
with Sandbox.create() as sandbox:
result = sandbox.commands.run('echo "Hello from E2B!"')
print(result.stdout) # Hello from E2B!
4. Bind the configuration to a client
The top-level Sandbox, AsyncSandbox, Volume, AsyncVolume, Template, AsyncTemplate and Secret exports read their configuration from the environment variables. To use an explicit configuration — e.g. several API keys or domains in one process — create an E2B client and use the resource classes it exposes:
from e2b import E2B
client = E2B(api_key="e2b_***", domain="e2b.dev")
sandbox = client.Sandbox.create()
volume = client.Volume.create("my-volume")
exists = client.Template.exists("my-template")
secret = client.Secret.create("openai-api-key", "sk-***")
# The async variants are exposed as well.
async_sandbox = await client.AsyncSandbox.create()
# The classes can be assigned and used like the top-level ones.
Sandbox = client.Sandbox
paginator = Sandbox.list()
Per-call params still take precedence over the client's params, and clients are isolated from each other and from the env-configured top-level exports.
5. Code execution with Code Interpreter
If you need run_code(), install the Code Interpreter SDK:
pip install e2b-code-interpreter
from e2b_code_interpreter import Sandbox
with Sandbox.create() as sandbox:
execution = sandbox.run_code("x = 1; x += 1; x")
print(execution.text) # outputs 2
6. Check docs
Visit E2B documentation.
7. E2B cookbook
Visit our Cookbook to get inspired by examples with different LLMs and AI frameworks.
