{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# E2B Python SDK\n", "The E2B Python SDK provides an interface for managing cloud environments for AI agents.\n", "\n", "This SDK gives your agent a full cloud development environment that's sandboxed. That means:\n", "\n", "- Access to Linux OS\n", "- Using filesystem (create, list, and delete files and dirs)\n", "- Run processes\n", "- Sandboxed - you can run any code\n", "- Access to the internet\n", "\n", "These cloud environments are meant to be used for agents. Like a sandboxed playgrounds, where the agent can do whatever it wants.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Installation" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "vscode": { "languageId": "shellscript" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Collecting e2b==0.1.4\n", " Downloading e2b-0.1.4-py3-none-any.whl (71 kB)\n", "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m71.3/71.3 kB\u001b[0m \u001b[31m3.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", "\u001b[?25hRequirement already satisfied: aenum>=3.1.11 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (3.1.15)\n", "Requirement already satisfied: aiohttp>=3.8.4 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (3.8.4)\n", "Requirement already satisfied: jsonrpcclient<5.0.0,>=4.0.3 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (4.0.3)\n", "Requirement already satisfied: pydantic<2.0.0,>=1.10.5 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (1.10.7)\n", "Requirement already satisfied: python-dateutil>=2.8.2 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (2.8.2)\n", "Requirement already satisfied: urllib3>=1.25.3 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (1.26.16)\n", "Requirement already satisfied: websockets<12.0.0,>=11.0.3 in /opt/homebrew/lib/python3.11/site-packages (from e2b==0.1.4) (11.0.3)\n", "Requirement already satisfied: attrs>=17.3.0 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (23.1.0)\n", "Requirement already satisfied: charset-normalizer<4.0,>=2.0 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (3.1.0)\n", "Requirement already satisfied: multidict<7.0,>=4.5 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (6.0.4)\n", "Requirement already satisfied: async-timeout<5.0,>=4.0.0a3 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (4.0.2)\n", "Requirement already satisfied: yarl<2.0,>=1.0 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (1.9.2)\n", "Requirement already satisfied: frozenlist>=1.1.1 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (1.3.3)\n", "Requirement already satisfied: aiosignal>=1.1.2 in /opt/homebrew/lib/python3.11/site-packages (from aiohttp>=3.8.4->e2b==0.1.4) (1.3.1)\n", "Requirement already satisfied: typing-extensions>=4.2.0 in /opt/homebrew/lib/python3.11/site-packages (from pydantic<2.0.0,>=1.10.5->e2b==0.1.4) (4.5.0)\n", "Requirement already satisfied: six>=1.5 in /opt/homebrew/lib/python3.11/site-packages (from python-dateutil>=2.8.2->e2b==0.1.4) (1.16.0)\n", "Requirement already satisfied: idna>=2.0 in /opt/homebrew/lib/python3.11/site-packages (from yarl<2.0,>=1.0->aiohttp>=3.8.4->e2b==0.1.4) (3.4)\n", "Installing collected packages: e2b\n", " Attempting uninstall: e2b\n", " Found existing installation: e2b 0.1.3\n", " Uninstalling e2b-0.1.3:\n", " Successfully uninstalled e2b-0.1.3\n", "Successfully installed e2b-0.1.4\n", "\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m23.2.1\u001b[0m\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpython3.11 -m pip install --upgrade pip\u001b[0m\n", "Note: you may need to restart the kernel to use updated packages.\n" ] } ], "source": [ "pip install e2b==0.1.4" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Usage" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "from e2b import Session\n", "\n", "id = \"Nodejs\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Initialization" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# You can use some of the predefined environments by using specific id:\n", "# 'Nodejs', 'Bash', 'Python3', 'Java', 'Go', 'Rust', 'PHP', 'Perl', 'DotNET'\n", "session = await Session.create(id)\n", "\n", "# Close the session after you are done\n", "await session.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Filesystem" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello World!\n" ] } ], "source": [ "# Create, read and delete file\n", "\n", "session = await Session.create(id)\n", "\n", "await session.filesystem.write(\"/tmp/test.txt\", \"Hello World!\")\n", "\n", "content = await session.filesystem.read(\"/tmp/test.txt\")\n", "print(content)\n", "\n", "await session.filesystem.remove(\"/tmp/test.txt\")\n", "\n", "await session.close()" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[]\n", "['test']\n", "[]\n" ] } ], "source": [ "# List files in a directory, create a new directory and remove a directory\n", "\n", "session = await Session.create(id)\n", "\n", "ls = await session.filesystem.list(\"/\")\n", "print([x.name for x in ls if x.name.startswith(\"test\")])\n", "\n", "await session.filesystem.make_dir(\"/test/new\")\n", "\n", "ls = await session.filesystem.list(\"/\")\n", "print([x.name for x in ls if x.name.startswith(\"test\")])\n", "\n", "await session.filesystem.remove(\"/test\")\n", "\n", "ls = await session.filesystem.list(\"/\")\n", "print([x.name for x in ls if x.name.startswith(\"test\")])\n", "\n", "await session.close()" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Event {'path': '//test.txt', 'name': 'test.txt', 'operation': 'Create', 'timestamp': 1691532768257138654, 'isDir': False}\n", "Event {'path': '//test.txt', 'name': 'test.txt', 'operation': 'Write', 'timestamp': 1691532768259136251, 'isDir': False}\n" ] } ], "source": [ "# Watch directory for changes (WIP)\n", "\n", "session = Session(id)\n", "await session.open()\n", "\n", "watcher = await session.filesystem.watch_dir(\"/\")\n", "watcher.add_event_listener(lambda event: print(\"Event\", event))\n", "await watcher.start()\n", "\n", "await session.filesystem.write(\"/test.txt\", \"Hello World!\")\n", "\n", "await watcher.stop()\n", "\n", "await session.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Process" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "tags": [ "process" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Process session ID wI6N300SFSvq\n", "Current output []\n", "Stdout line='/code' error=False timestamp=1691532768326208600\n", "Exit\n", "Output [ProcessMessage(line='/code', error=False, timestamp=1691532768326208600)]\n", "Stdout /code\n", "Stderr \n" ] } ], "source": [ "# Execute a command and get the output\n", "\n", "session = await Session.create(id)\n", "\n", "proc = await session.process.start(\n", " \"pwd\",\n", " # If you add a callback for stdout you will get the stderr data as it comes in. \n", " # You can still access the stdout after `output = await proc` as `output.stdout` or anytime as `proc.output.stdout`.\n", " on_stdout=lambda data: print(\"Stdout\", data),\n", " # If you add a callback for stderr you will get the stderr data as it comes in.\n", " # You can still access the stderr after `output = await proc` as `output.stderr` or anytime as `proc.output.stderr`.\n", " on_stderr=lambda data: print(\"Stderr\", data),\n", " on_exit=lambda: print(\"Exit\"),\n", " rootdir=\"/code\",\n", ")\n", "print(\"Process session ID\", proc.process_id)\n", "\n", "# You can access `proc.output...` even before the process finishes\n", "print(\"Current output\", proc.output.messages)\n", "\n", "# You can directly await the started process to wait for exit\n", "output = await proc\n", "\n", "# List of all output messages\n", "print(\"Output\", output.messages)\n", "# Concatenated stdout\n", "print(\"Stdout\", output.stdout)\n", "# Concatenated stderr\n", "print(\"Stderr\", output.stderr)\n", "await session.close()" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "tags": [ "process", "stdin", "kill" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Stdout line='marco' error=False timestamp=1691532768254368795\n", "Exit\n", "Output [ProcessMessage(line='marco', error=False, timestamp=1691532768254368795)]\n", "Stdout marco\n", "Stdout \n" ] } ], "source": [ "# Start command, send stdin to it and then kill it\n", "\n", "session = await Session.create(id)\n", "\n", "proc = await session.process.start(\n", " \"while IFS= read -r line; do echo \\\"$line\\\"; sleep 1; done\",\n", " # If you add a callback for stdout you will get the stderr data as it comes in. \n", " # You can still access the stdout after `output = await proc` as `output.stdout` or anytime as `proc.output.stdout`.\n", " on_stdout=lambda data: print(\"Stdout\", data),\n", " # If you add a callback for stderr you will get the stderr data as it comes in.\n", " # You can still access the stderr after `output = await proc` as `output.stderr` or anytime as `proc.output.stderr`.\n", " on_stderr=lambda data: print(\"Stderr\", data),\n", " on_exit=lambda: print(\"Exit\"),\n", " rootdir=\"/code\",\n", ")\n", "await proc.send_stdin(\"marco\\n\")\n", "await proc.kill()\n", "\n", "print(\"Output\", proc.output.messages)\n", "print(\"Stdout\", proc.output.stdout)\n", "print(\"Stdout\", proc.output.stderr)\n", "\n", "await session.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Terminal" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Terminal session ID FSSpmurO9BNP\n", "\u001b[?2004h\n", "/code $ \n", "ls -a\n", "\u001b[?2004l\n", "\u001b[0m\u001b[01;34m.\u001b[0m \u001b[01;34m..\u001b[0m package.json\n", "\n", "\u001b[?2004h/code $ \n", "Exit\n" ] } ], "source": [ "# Start and interact with a terminal session\n", "\n", "session = await Session.create(id)\n", "\n", "term = await session.terminal.start(\n", " on_data=lambda data: print(data),\n", " on_exit=lambda: print(\"Exit\"),\n", " cols=80,\n", " rows=24,\n", " rootdir=\"/code\",\n", ")\n", "print(\"Terminal session ID\", term.terminal_id)\n", "await term.resize(80, 30)\n", "\n", "await term.send_data(\"ls -a\\n\")\n", "\n", "await term.kill()\n", "\n", "await session.close()" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Data: Hello World\n", "\n", "Exit\n" ] } ], "source": [ "# Execute one command inside of a terminal session\n", "\n", "session = await Session.create(id)\n", "\n", "term = await session.terminal.start(\n", " on_data=lambda data: print(\"Data:\", data),\n", " on_exit=lambda: print(\"Exit\"),\n", " cols=80,\n", " rows=24,\n", " rootdir=\"/code\",\n", " # If you specify a command, the terminal will be closed after the command finishes.\n", " cmd=\"echo Hello World\",\n", ")\n", "\n", "await term\n", "\n", "await session.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ports and hostnames - connecting to environment" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "tags": [ "process", "ports", "hostname" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hostname: https://8000-s2t6u9y1-fce131d5.ondevbook.com\n", "Open ports: [49982, 22, 53, 49982]\n", "Open ports: [22, 49982, 8000, 49982, 53]\n", "Open ports: [49982, 49982, 22, 8000, 53]\n", "Open ports: [49982, 49982, 22, 8000, 53]\n", "Open ports: [22, 53, 49982, 49982, 8000]\n", "Open ports: [49982, 8000, 49982, 53, 22]\n", "Open ports: [22, 49982, 8000, 53, 49982]\n", "Open ports: [49982, 53, 49982, 8000, 22]\n", "Open ports: [49982, 49982, 22, 8000, 53]\n", "Open ports: [49982, 49982, 8000, 22, 53]\n" ] } ], "source": [ "# Get notified when a port opens and how to get a public hostname for an open port in the cloud environment\n", "\n", "import asyncio\n", "\n", "session = await Session.create(\n", " id,\n", " on_scan_ports=lambda ports: print(\"Open ports:\", [port.port for port in ports]),\n", ")\n", "\n", "port = 8000\n", "proc = await session.process.start(f\"python3 -m http.server {port}\")\n", "\n", "hostname = session.get_hostname(port)\n", "print(f\"Hostname: https://{hostname}\")\n", "\n", "await asyncio.sleep(10)\n", "\n", "await proc.kill()\n", "\n", "await session.close()" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Current output []\n", "Output [ProcessMessage(line='/code', error=False, timestamp=1691532768216519914)]\n", "Stdout /code\n", "Stderr \n" ] } ], "source": [ "# One line initialization\n", "session = await Session.create(id)\n", "\n", "proc = await session.process.start(\n", " \"pwd\",\n", " rootdir=\"/code\",\n", ")\n", "\n", "# You can access `proc.output...` even before the process finishes\n", "print(\"Current output\", proc.output.messages)\n", "\n", "# You can directly await the started process to wait for exit\n", "output = await proc\n", "\n", "# List of all output messages\n", "print(\"Output\", output.messages)\n", "# Concatenated stdout\n", "print(\"Stdout\", output.stdout)\n", "# Concatenated stderr\n", "print(\"Stderr\", output.stderr)\n", "\n", "await session.close()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.3" }, "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 }