Skip to content

Concepts

Tasks and verifiers

OSWorld tasks set a desktop up and score it. Every score comes with the episode's validity.

Tasks

A task is an OSWorld task JSON: an instruction for the agent, config setup steps (open a file, create a folder, start an app), and an evaluator that scores the final desktop. The host serves the 369 tasks of its pinned OSWorld checkout:

Python
import collections
import drums

with drums.connect() as client:
    tasks = client.tasks()
    supported = sum(t["supported"] for t in tasks)
    print(len(tasks), "tasks;", supported, "supported on this host")
    print(collections.Counter(t["domain"] for t in tasks).most_common(3))
    t = client.task("e0df059f")  # id, or a unique prefix of 8+ characters
    print(t["instruction"], "|", t["evaluator"]["func"])
  • Create a desktop with a task (client.create(task=...)) and its setup runs at create and after every reset. Fork children inherit the set-up state.
  • supported: false marks the 3 tasks that need the agent itself to act as root. Desktops never give the agent root, so creating one with such a task raises TaskUnsupported (HTTP 422) and nothing starts. A task whose setup alone needs root is supported: the runtime runs that step as trusted provisioning, never as the agent.
  • Some tasks have "evaluator": {"func": "infeasible"} (no solution exists), and some download files during setup or checking. Read a task's JSON before you rely on it.

Verifiers

env.verify() (HTTP POST /v1/slots/{id}/verify) runs the task's checker on the current desktop and returns a Reward:

FieldMeaning
scoreThe checker's result, usually 0.0 or 1.0. None when the checker did not run
validTrue only when every gate of the episode passed and the desktop was never quarantined
invalid_reasonsWhy it is not valid, in words (empty when valid)
verdict, bad_gatespending, valid or invalid, and the gates that failed
checker_errorSet when the checker raised; there is no score
checker_skippedWhy the checker did not run (e.g. quarantined: <reason>)

valid says the episode ran in a correctly restored, isolated desktop. It does not say the task was solved; that is score. A valid episode with score 0.0 is a valid failure. Train or report only on rewards with valid == True. With the default strict=True, verify() raises InvalidEpisode instead of returning any other reward, and CheckerError when the checker failed.

Some OSWorld checkers run a postconfig step (save a document, close a window) that changes the desktop, so verify at the end of an episode.

Gates

Every create, reset and fork child starts an episode with a gate report. A gate is a check the runtime makes so a broken restore can never pass as a valid result:

GateChecks
lock_applied, lock_pre_resumeThe file locks restored equal the ones dumped
cgroupThe desktop's processes are in its own cgroup with its CPU, memory and swap limits
init_identityExactly one init, pid 1 of its own pid namespace
mount_table, netnsThe mount table and network namespace equal the dumped ones
guest_readyThe desktop's guest server answers
state_hashThe home directory listing and file hashes equal the checkpoint's
isolationpid, mount, net, ipc and uts namespaces differ from the host's and every other desktop's
alive_after_resumeEvery restored process is still running 5 s after the desktop answered
no_oom_killAdded as failed when the out-of-memory killer took a process of the desktop
no_app_crashAdded as failed when a process died of a crash signal (SIGSEGV, SIGILL, SIGABRT, …)
not_quarantinedAdded as failed when the desktop was quarantined

The verdict is pending for about 5 seconds after create, reset or fork (until alive_after_resume resolves). verify() waits for it. If your first actions may end a process, call env.wait_valid() first: a process that exits in those seconds cannot be told apart from a bad restore, so the episode would be flagged invalid.

Python
import drums

with drums.connect() as client:
    with client.create(task="e0df059f", ttl=600) as env:
        env.wait_valid()
        g = env.gates()
        failed = [x["gate"] for x in g["gates"]["gates"] if x["status"] != "pass"]
        print(g["validity"]["verdict"], failed)
        env.quarantine("harness detected a broken page")
        r = env.verify(strict=False)
        print(r.valid, r.score, r.invalid_reasons)

Quarantine

A quarantined desktop refuses steps, resets and saves, and its episode is invalid. Quarantine one yourself (env.quarantine(reason)) when your harness detects a broken episode. To reuse it, env.release() (it becomes down) and then env.reset() for a new, judged episode; or close it and create another.

Your own verifiers

The runtime can also score a task with a lab-provided Python verifier installed on the host by the operator (an evaluator of the form {"func": "drums_verifier", "verifier": NAME, "function": FN}). Tasks name a verifier and never carry code. Installing verifiers is an operator step on your worker host; ask your platform operator.