Moving from Orgo or E2B

Orgo computers, E2B Desktop sandboxes and Mandala computers do the same basic job. Each is a Linux desktop that your code or your agent can screenshot, click, type into and run commands on. Most code moves over one call at a time. This page maps the calls and then lists the differences that change how you write the code around them.

Install and authenticate

pip install mandala-computer        # Python 3.10+
npm install mandala-computer        # Node 22+, also installs the mandala CLI

Create an API key in Settings → Credentials → API keys and put it in MANDALA_API_KEY, where ORGO_API_KEY or E2B_API_KEY used to be. Or run mandala login once, which saves a profile that both SDKs read.

Orgo to Mandala (Python)

OrgoMandala
Computer()client.computers.launch(template="base")
Computer(ram=4, cpu=2)client.computers.launch(cpu=2, ram_mb=4096), or size="standard"
Computer(computer_id=id)client.computers.get(id)
computer.screenshot() (PIL image)Image.open(io.BytesIO(computer.screenshot()))
computer.screenshot_base64()base64.b64encode(computer.screenshot()).decode()
computer.left_click(x, y)computer.click(x, y)
computer.right_click(x, y), double_click(x, y)computer.right_click(x, y), computer.double_click(x, y)
computer.drag(sx, sy, ex, ey)computer.drag(ex, ey, from_x=sx, from_y=sy)
computer.scroll("down", 3)computer.scroll(direction="down", amount=3)
computer.type("hello")computer.type("hello")
computer.key("Enter"), key("ctrl+c")computer.key("Return"), computer.key("ctrl", "c")
computer.wait(2)computer.wait(2)
computer.bash("ls")computer.exec("ls").stdout_text
computer.exec(python_code)computer.write_file("/tmp/job.py", code) then computer.exec("python3 /tmp/job.py")
computer.prompt("…")computer.agent("…", model_key=ANTHROPIC_API_KEY)
computer.status()computer.refresh().status
computer.restart()computer.restart()
computer.destroy()computer.delete()
computer.start_stream(...)computer.vnc.embed_url, to watch in a browser (or computer.vnc.view_url, a WebSocket for your own noVNC client)

Orgo's project and workspace arguments group computers. In Mandala, a workspace does that job. A key issued for a workspace sees and creates computers only in that workspace, so with one key per workspace the code needs no project argument. An account-wide key can instead pass workspace_id when it creates or lists computers.

E2B Desktop to Mandala (Python)

E2B DesktopMandala
Sandbox.create()client.computers.launch(template="base")
Sandbox.create(resolution=(1920, 1080))client.computers.launch(resolution="1920x1080")
Sandbox.connect(sandbox_id)client.computers.get(computer_id)
desktop.screenshot() (bytes)computer.screenshot(fresh=True)
desktop.left_click(x, y)computer.click(x, y)
desktop.right_click, middle_click, double_clickcomputer.right_click, middle_click, double_click
desktop.move_mouse(x, y)computer.move(x, y)
desktop.drag((x1, y1), (x2, y2))computer.drag(x2, y2, from_x=x1, from_y=y1)
desktop.mouse_press(), mouse_release()computer.mouse_down(), computer.mouse_up()
desktop.scroll("down", 3)computer.scroll(direction="down", amount=3)
desktop.write("hello")computer.type("hello"), or computer.paste(text) for long text
desktop.press("enter"), press(["ctrl", "c"])computer.key("Return"), computer.key("ctrl", "c")
desktop.wait(1000) (milliseconds)computer.wait(1) (seconds)
desktop.get_cursor_position()computer.cursor_position()
desktop.get_screen_size()computer.screen
desktop.open(url)computer.open(url)
desktop.launch("google-chrome")computer.start_exec("chromium", desktop=True)
desktop.commands.run("ls")computer.exec("ls")
desktop.commands.run(cmd, background=True)computer.start_exec(cmd)
desktop.files.write(path, data), files.read(path)computer.write_file(path, data), computer.read_file(path)
desktop.stream.start(), stream.get_url()computer.vnc.embed_url (a watch-only page); for control, computer.vnc.url is a WebSocket for a noVNC client — there is no hosted full-control page, so use the dashboard
desktop.set_timeout(seconds)closest: computer.set_idle_suspend(minutes) (suspends, never deletes)
desktop.pause(), connect()computer.suspend(), computer.start()
desktop.create_snapshot()computer.snapshot()
desktop.kill()computer.delete()

The TypeScript SDK uses camelCase for most of these (rightClick, mouseDown, writeFile, and so on), but two differ in name: Python's start_exec(cmd) is computer.execBackground(cmd) in TypeScript (with { desktop: true } where the Python call passes desktop=True), and Python's set_idle_suspend(minutes) is computer.update({ idleSuspendMin: minutes }).

What behaves differently

A computer lasts until you delete it. An E2B sandbox ends when its timeout runs out. A Mandala computer keeps its disk, files and installed software through stops, restarts and suspends, and is billed while it runs. When nobody has used it for the idle window, it suspends itself, and the next input or command resumes it. The window is 30 minutes by default, but the operator can set a host's window differently, or turn it off; to be sure of a computer's window, set idle_suspend_min on it with computer.set_idle_suspend(minutes). Delete computers you no longer need, or use client.computers.ephemeral(...), which deletes the computer when the with block ends.

Launch waits for readiness. launch() creates the computer, starts it and returns once its guest agent answers, typically in a few seconds for a size from client.sizes.list(). A custom CPU and RAM shape boots from cold and takes longer. create() returns straight away if you want to manage the waits yourself.

Commands run as root, without a display. exec() runs as root in a login shell with no DISPLAY. That is right for installing packages. A program with a window needs exec(..., desktop=True) or start_exec(..., desktop=True), which run as the desktop user inside the graphical session. open(url) opens the desktop's browser.

Commands wait, up to a limit. exec() waits for the command, 30 seconds by default and at most 600. On the hosted service a request with no answer for about two minutes can be cut off by the proxy, so start anything slower with start_exec() and poll it.

Screenshots can be cached. screenshot() may return a frame up to 1.5 seconds old (up to 30 seconds while the computer is busy), which is cheap enough for thumbnails. Pass fresh=True whenever the image feeds a decision.

Key names are X11 names. Return, BackSpace, Page_Down and ctrl+c style chords all work, and so do the common spellings enter, esc and CTRL. An unknown key is refused by name rather than skipped.

Text over 400 characters needs a split or a paste. type() takes up to 400 characters. paste() takes up to 8 KB, and is much faster.

The resolution is fixed at create time. Choose it with resolution= when you create the computer. It is the coordinate space for every click and the size of every screenshot.

A ported script

An Orgo or E2B script that opens a page, reads a value with a command and saves a screenshot looks like this on Mandala:

from mandala_computer import Client

client = Client()  # reads MANDALA_API_KEY

with client.computers.ephemeral(template="base", name="ported-script") as computer:
    computer.wait_for_guest()
    width, height = computer.screen

    # A command, as root, without a display.
    kernel = computer.exec("uname -r")
    print("kernel:", kernel.stdout_text.strip())

    # Files in and out.
    computer.write_file("/tmp/hello.txt", "hello from the SDK\n")
    print(computer.read_text_file("/tmp/hello.txt").strip())

    # A program with a window, on the desktop.
    computer.start_exec("xfce4-terminal", desktop=True)
    computer.wait(3)
    computer.click(width // 2, height // 2)
    computer.type("echo typed on the desktop > /tmp/typed.txt")
    computer.key("Return")
    computer.wait(1)
    print(computer.read_text_file("/tmp/typed.txt").strip())

    with open("screen.png", "wb") as f:
        f.write(computer.screenshot(fresh=True))
    print("saved screen.png", width, "x", height)

Agents and MCP

See also: Troubleshooting and the API reference.