@env.template,
the shape that prompts the agent and scores what happens. Calling that template mints a Task: a
plain data row (an env name, a template id, bound args) that travels over the wire and runs anywhere.
The agent loop and grading happen in the gap between the generator’s two yields, and a call to
run() executes one row and returns a Job.
Defining a task
A task is an async generator with exactly two yields. The first yield is the prompt; the generator pauses while the agent works; the agent’s answer comes back into the generator; the second yield is the reward (0.0-1.0).
tasks.py
float, an EvaluationResult,
or a dict with a numeric score; the env layer normalizes any of them to the reward.
Template
@env.template() registers the generator as a template: a callable that mints a concrete Task
without running anything.
Declare
returns=T and the answer arrives as a parsed Answer[T]
(.content parsed, .raw the original string); without it, answer is the raw string the agent
submitted.
One template spans a space of tasks. Call it with different arguments and a single function becomes a
whole dataset, with no separate artifact per task:
tasks.py
Task
ATask is a Pydantic model - one portable, validated row of data. It holds no live environment: env
is a name, the join key between the row and whatever brings that environment up at run time. So a task
runs anywhere without an env object in-process - the prompt and reward arrive over the wire from the
substrate that placement brings up.
When you don’t have the template in hand (data pipelines, generated rows), build the model directly -
the model is the row, so
task.model_dump() and Task.model_validate(data) are the whole codec:
Grading
The second yield is the reward. Return a float inline, or reach for the comparison helpers, async graders, and composed grades documented in graders. For how to design a reward that separates good work from bad and resists hacking, see designing tasks. When authoritative grading belongs in another environment, setTask.verifier
to a second task row. Its declaration, placement order, and phase boundary are
documented in Verifier environments.
Tasksets
ATaskset is a named collection of task rows. Build one in code, or load it from a source:
ts.to_file("tasks.json") (or .jsonl). Tasksets are also ordered
collections:
Running
taskset.run(agent, ...) executes every task and returns a Job.
task.run(...) is the same call over a taskset of one, with identical semantics.
agent_config.timeout_seconds bounds only the agent phase. If it expires, the
run is marked as timed out but grading still runs against any completed work.
rollout_timeout instead bounds submission, queueing, startup, the agent, and grading together.
It is not a wall-clock bound on Task.run or Taskset.run returning: after expiry, local execution
may wait up to two seconds for cancellation and still reports the trace, and Taskset.run can spend
up to 120 seconds flushing telemetry. Runtime cleanup may finish in the background. When both are
set, the agent timeout must be less than the rollout timeout and any explicit actor
run_timeout_s. Limits imposed by the selected runtime still apply when rollout_timeout is
omitted. Grader-specific limits, such as BashGrader.timeout_seconds, remain local to that grader.
A crashed rollout comes back as a failed Run inside the job rather than
raising, so one bad rollout never collapses a batch. For the end-to-end workflow see
running an eval.
Syncing
Sync publishes a locally-authored taskset to hud.ai so you can run it there, compare models on it, and browse its traces; local runs never need it. Thehud sync tasks <name> command
uploads a taskset and only what changed, a workflow covered in
creating an environment. In code,
diff(local, remote) returns a SyncPlan describing the comparison:
To create the taskset outside the team default Project, select a directory Project first or pass an
explicit destination:
Once a reward separates good work from bad, designing tasks covers the
difficulty and spread that make a taskset worth training on, and graders the
scoring that produces each reward.