- Which tasks exist?
- What sandbox does each task run in?
- How is a task set up before the agent starts?
- How is the agent’s work graded, and turned into one score?
Generate the project
create-benchmark-service supplies the web service and the protocol Valkyrie speaks, so you write oneBenchmarkService subclass.
./NAME-benchmark-service/, where NAME is the name you passed it:
Implement the service
ReplaceExampleBenchmark in benchmark_service.py one method at a time. Each method’s
docstring describes what it must do. The examples on this page use these imports:
Load the dataset
load_datasets runs once when the service starts, and its result is kept in
self.datasets. Key it by dataset name, then by task ID. Each task’s value is whatever your
benchmark needs, such as a problem statement, a repository and commit, or an expected answer.
self.get_dataset(dataset). Several datasets are how one service
offers variants, for example a baseline dataset and a with-skills dataset. Runs choose one
with --dataset.
Describe the sandbox
retrieve_task tells Valkyrie how to build one task’s sandbox: the image, the working
directory, where the problem statement goes, the agent’s time limit, and the hardware.
- Image: return the same
ImageSourcefor every task and do per-task work insetup_task, or build one image per task ahead of time and return each task’s own.SnapshotSourcestarts from a provider snapshot instead, andComposeSourceruns the task as Docker Compose services. Build images forlinux/amd64. Private images need registry credentials in your sandbox provider account. - Time limit:
agent_timeoutis the agent’s generation limit in seconds. See Task time limits. - Hardware: request GPUs through
Resources, for exampleResources(vcpu=8, memory=32, disk=50, gpu=1, gpu_type="H100"). - Docker inside the task: Daytona and Modal sandboxes can run Docker. Use an image with
Docker installed and start
dockerdduring setup. - Install order: Valkyrie installs the agent before
setup_taskruns. When setup must prepare the runtime first, setagent_install_order="after_setup".ComposeSourcetasks always run setup first.
egress:
"*" for unrestricted access, [] to block all outbound traffic, or a
list of the hostnames, URLs, IPv4 addresses, and CIDR ranges to allow. Setup and evaluation
default to "*". run defaults to None, which leaves the agent unrestricted unless its
contract asks for an allowlist.
Set up the task
setup_task runs in the live sandbox before the agent starts: write the problem statement,
fetch the repository, install dependencies, or start services. It yields chunks instead of
returning, and they stream to whoever is watching the run.
The sandbox has
upload_file, download_file, exec, which returns an ExecResult with
exit_code and output, and command, which streams output line by line.
stream_command(sandbox, command, cwd) wraps command and raises on a nonzero exit code
unless you pass ignore_error=True.
Grade the result
Implement the hook that matches how your benchmark grades, and keep the other one raising an error, as the generated example does:evaluate_instancegrades the agent’s live sandbox: upload the tests, run them, and parse the output. It yields chunks, and itsStreamResultChunkis the task’s result.evaluate_responsegrades a text answer without a sandbox, and returns the result.
Compute the score
calculate_final_score receives {task_id: result} for every task and returns the run’s
score, plus any metadata worth reporting. A task that didn’t finish arrives as None.
Check for reward hacking
Before the first real run, confirm that:- Tests are uploaded in
evaluate_instance, never insetup_task. - Reference solutions, patches, and answer keys never enter the sandbox.
- The problem statement holds no grading criteria or expected output.
- Hints, skills, or scaffolding appear only in the datasets meant to have them.
- A live sandbox’s working directory, listed mid-run, contains nothing grading-related.
Test it with Valkyrie
You don’t need to deploy to test. Run the service on your machine, expose it with a reverse tunnel, and point Valkyrie at the tunnel.-
Start the service.
make devprints the address it serves on: -
Start a tunnel to that port, and save the tunnel’s address for the benchmark:
-
Run one task, and watch it stream your setup and grading messages:
valkyrie benchmark service remove swebench.
Publish the service
A port is finished when it’s listed in the public benchmark services registry: the service lives in its own repository, named likeswebench-benchmark-service, added to the
registry as a Git submodule with a matching services.yaml entry.
