Run Anthropic’s computer use demo in a Modal Sandbox
This example demonstrates how to run Anthropic’s Computer Use demo in a Modal Sandbox.
Sandbox Setup
All Sandboxes are associated with an App.
We start by looking up an existing App by name, or creating one if it doesn’t exist.
import time
import urllib.request
import modal
import modal.experimental
app = modal.App.lookup("example-computer-use", create_if_missing=True)
The Computer Use quickstart provides a prebuilt Docker image. We use this hosted image to create our sandbox environment.
sandbox_image = (
modal.experimental.raw_registry_image(
"ghcr.io/anthropics/anthropic-quickstarts:computer-use-demo-latest",
)
.env({"WIDTH": "1920", "HEIGHT": "1080"})
.workdir("/home/computeruse")
.entrypoint([])
)
We’ll provide the Anthropic API key via a Modal Secret which the sandbox can access at runtime.
secret = modal.Secret.from_name("anthropic-secret", required_keys=["ANTHROPIC_API_KEY"])
Now, we can start our Sandbox.
We use modal.enable_output()
to print the Sandbox’s image build logs to the console.
We’ll also expose the ports required for the demo’s interfaces:
- Port 8501 serves the Streamlit UI for interacting with the agent loop
- Port 6080 serves the VNC desktop view via a browser-based noVNC client
with modal.enable_output():
sandbox = modal.Sandbox.create(
"sudo",
"--preserve-env=ANTHROPIC_API_KEY,DISPLAY_NUM,WIDTH,HEIGHT,PATH",
"-u",
"computeruse",
"./entrypoint.sh",
app=app,
image=sandbox_image,
secrets=[secret],
encrypted_ports=[8501, 6080],
timeout=60 * 60, # stay alive for one hour, maximum one day
)
print(f"🏖️ Sandbox ID: {sandbox.object_id}")
After starting the sandbox, we retrieve the public URLs for the exposed ports.
tunnels = sandbox.tunnels()
for port, tunnel in tunnels.items():
print(f"Waiting for service on port {port} to start at {tunnel.url}")
We can check on each server’s status by making an HTTP request to the server’s URL and verifying that it responds with a 200 status code.
def is_server_up(url):
try:
response = urllib.request.urlopen(url)
return response.getcode() == 200
except Exception:
return False
timeout = 60 # seconds
start_time = time.time()
up_ports = set()
while time.time() - start_time < timeout:
for port, tunnel in tunnels.items():
if port not in up_ports and is_server_up(tunnel.url):
print(f"🏖️ Server is up and running on port {port}!")
up_ports.add(port)
if len(up_ports) == len(tunnels):
break
time.sleep(1)
else:
print("🏖️ Timed out waiting for server to start.")
You can now open the URLs in your browser to interact with the demo!
Note: The sandbox logs may mention localhost:8080
.
Ignore this and use the printed tunnel URLs instead.
When finished, you can terminate the sandbox from your Modal dashboard or by running Sandbox.from_id(sandbox.object_id).terminate()
.
The Sandbox will also spin down after one hour.