Skip to content

Get started

Quickstart

From an empty terminal to a first verified rollout: an API key, the Python SDK, one desktop, one action, one checker result.

You will create an API key, install the Python SDK, start one desktop with an OSWorld task, take a screenshot, act, run the task's checker and close the desktop. Every command and script on this page was run as written against the production gateway before it was published.

1. Create an API key

  1. Sign in at console.drums.run and open API Keys in your workspace.
  2. Choose Create key. Give it a name (for example laptop), keep the default scopes computers:read, computers:write, runs:read and usage:read, and keep the default expiry of 90 days.
  3. Copy the key from the dialog. It starts with drums_sk_ and is shown only once; Drums stores only a hash of it.

The key acts as you, limited to its scopes and to your role in the workspace. See Authentication.

2. Install the Python SDK

The SDK is the drums-sdk package on PyPI (version 0.3.0); the import name is drums, and it installs the drums command (drums version, drums mcp). It uses only the Python standard library and needs Python 3.9 or later.

Terminal
python3 -m venv drums-venv
drums-venv/bin/pip install drums-sdk

3. Point it at the gateway

Terminal
export DRUMS_URL=https://beta.drums.run/gw
export DRUMS_TOKEN=drums_sk_...   # the key from step 1

The SDK sends the key over HTTPS only. A plain http:// URL is refused before any request unless it is loopback (a local drumsd) or you opt in with connect(allow_insecure_http=True) or DRUMS_ALLOW_INSECURE_HTTP=1; see Python SDK.

Check the connection. Both forms call GET /v1/health and print the runtime version:

import drums

client = drums.connect()                 # reads DRUMS_URL and DRUMS_TOKEN
print(client.health()["version"])

A 401 (AuthError in Python) means the key is mistyped, revoked or expired.

4. Run a first verified rollout

Save this as quickstart.py and run it with drums-venv/bin/python quickstart.py. It starts a desktop with OSWorld task e0df059f ("rename the folder todo_list_Jan_1 on the Desktop to todo_list_Jan_2"), waits until every gate of the episode has passed, saves a screenshot, performs the task with one action, runs the task's checker and closes the desktop.

quickstart.py
import drums

# the client closes every desktop it created when the block ends
with drums.connect() as client:
    print("drumsd", client.health()["version"])
    # an OSWorld task id; ttl is the desktop's lifetime in seconds
    with client.create(task="e0df059f", ttl=900) as env:
        env.wait_valid()                   # every gate of this episode passed
        obs = env.observe()                # PNG screenshot plus metadata
        open("screen.png", "wb").write(obs.png)
        print("task:", obs.meta["instruction"])
        print("screenshot bytes", len(obs.png))
        env.step({"type": "execute", "shell": True,
                  "command": "mv ~/Desktop/todo_list_Jan_1 ~/Desktop/todo_list_Jan_2"})
        reward = env.verify(strict=False)  # the task's checker plus episode validity
        print("score", reward.score, "valid", reward.valid, reward.invalid_reasons)
    print("live computers left", len(client.envs()))

Expected output (your ids and byte counts differ):

Output
drumsd 0.4.2
task: I have a directory named "todo_list_Jan_1". Can you help me change its name into "todo_list_Jan_2"?
screenshot bytes 1671333
score 1 valid True []
live computers left 0

What happened:

  • client.create(task=...) fetched the task's JSON, started a desktop from the osworld-ubuntu image and ran the task's setup (which creates the folder). While it runs, the desktop is listed under Computers in the console, with a live screenshot view.
  • env.wait_valid() waited about 5 seconds for the last gate (every restored process still alive). Acting before that is allowed, but an action that ends a process in those seconds makes the episode invalid.
  • The action used execute, a shell command inside the desktop, to keep this page short. A GUI agent acts with pyautogui instead, for example env.step("pyautogui.click(960, 540)"); see Actions.
  • verify(strict=False) returned the checker's score and valid. Use a score only when valid is True. With the default strict=True, an invalid episode raises InvalidEpisode instead.

5. Next steps