Interactive Worlds
An Interactive World is a causal task environment. The agent observes the current situation, takes an action, and receives the next observation. An accepted action can change later evidence and the final evaluation.
Use this model when a sequence of decisions matters. If one submitted file or bounded workspace is enough, use an artefact task. If the stages are known in advance and the host controls evidence release, use a finite lifecycle.
Find and load a world
Use the aec_bench.worlds facade to discover registered worlds and build provider-neutral tasks:
from aec_bench import worlds
available = worlds.list()
matches = worlds.find("seepage")
dam = worlds.get("dam-seepage-monitoring")
profiles = worlds.profiles(dam.id)
task = worlds.task(
dam.id,
profile="synthetic-rising-seepage",
instruction="Monitor the dam and respond as conditions evolve.",
)
loaded_profile = worlds.load_profile(task)worlds.list() shows every registered world, worlds.find() searches them, and worlds.get() loads an exact world ID. A profile selects one fixed scenario for that world.
The built-in catalogue contains:
| World ID | Profiles | Capabilities |
|---|---|---|
dam-seepage-monitoring | synthetic-rising-seepage | Minimum world contract |
wastewater-pump-station-stewardship.v1 | pump-station-reference-system.asw-8-rs1.v1, pump-station-reference-system.asw-8-rs2.v1 | Branching, host controls, persistence |
Define a world task in files
A WorldTask combines an instruction with an exact registered world build and scenario profile. This keeps the task reproducible even if the world catalogue changes later. Provider settings and live execution state stay outside the task.
For a portable task package, store the objective in instruction.md and the exact references in world.toml:
tasks/civil/dam-monitoring/
├── instruction.md
└── world.toml[world]
task_world_id = "dam-seepage-monitoring"
entry_point = "<registered entry point>"
artifact_sha256 = "<registered world build SHA-256>"
[profile]
task_world_id = "dam-seepage-monitoring"
profile_id = "synthetic-rising-seepage"
profile_content_sha256 = "<registered profile SHA-256>"
[metadata]
domain = "civil"
category = "monitoring"
difficulty = "medium"
lifecycle = "active"
visibility = "public"
tags = ["dam", "monitoring", "seepage", "synthetic"]Load it with worlds.load_world_task(instance_dir, tasks_root). Loading rejects an unknown world, a stale build, a stale profile, or metadata that does not match the registered profile.
What every world owns
A world contribution owns five things:
| Part | Purpose |
|---|---|
| State | One authoritative representation of the current engineering situation |
| Observation | The part of the current situation that the agent is allowed to see |
| Action | A validated task-owned decision or request |
| Transition | A deterministic accepted change or a rejection that leaves state unchanged |
| Evaluation | The task-owned interpretation of final state, trajectory, and verified evidence |
The registered definition binds this behaviour to an exact code build and scenario profile.
The dam and pump worlds share the world core and one Prime actor-session implementation. Each task owner defines its own state, journey, controls, persistence, verification, and evaluation.
Authoring path
- Define exact scenario inputs and one authoritative state.
- Project only actor-visible facts into the observation.
- Implement deterministic initialisation, transitions, rejection, verification, and evaluation.
- Create an exact world build and content-pinned profile loader.
- Register the definition once at the catalogue composition boundary.
- Add the complete trial function only when a supported provider route exists.
- Prove deterministic behaviour, safe rejection, terminal handling, evidence retention, and boundary round trips.
Store episode IDs, step indexes, provider data, repository paths, and content digests as execution or evidence metadata outside domain state. Add host controls, durable recovery, branching, or provider packaging only when the task needs them.
What counts as one trial
A trial covers the complete journey from the selected scenario to verified final evidence. It can contain several actions or provider sessions.
A complete world trial selects the profile, runs the actor journey, closes the provider session, verifies task-owned evidence, evaluates the result, retains referenced artefacts, and returns one TrialRecord. Returned artefact references remain valid after temporary session directories are removed.
The complete public application functions are asynchronous:
run_dam_seepage_trial()for the dam world;run_pump_station_trial()for a Prime pump journey;run_pump_station_harbor_trial()for a Harbor pump journey; andrun_world_experiment()for ordered execution and optional record persistence.
Plan trials directly with the one public planner:
from functools import partial
from pathlib import Path
from aec_bench.harness.world_routing import run_selected_world, validate_world_routes
from aec_bench.harness.world_trials import run_world_experiment
from aec_bench.trials import plan_trials
trials = plan_trials(
"dam-study",
tasks=[task],
agents=[agent],
repetitions=3,
)
validate_world_routes([task], trials)
records = await run_world_experiment(
tasks=[task],
trials=trials,
run_trial=partial(run_selected_world, work_root=Path("artefacts/world-runs")),
)run_world_experiment() preserves the declared trial order and validates that each returned record matches its task and plan. Unsupported world and provider combinations fail before execution begins.
Current complete routes are:
| World | Provider path |
|---|---|
| Dam-seepage monitoring | Prime Agent |
| Pump-station stewardship | Prime Agent |
| Pump-station stewardship | DeepSeek harness through Harbor |
Provider adapters translate execution protocols. The dam and pump task owners define their task-specific behavior.
Who controls the world
The world owns engineering meaning. The actor host owns the provider-facing decision exchange.
| World owner | Actor and execution boundary |
|---|---|
| Domain state and valid actions | Opaque decision association |
| Actor-visible observation | Provider session and transcript |
| Accepted transition or rejection | Recording and accepted-step advancement |
| Domain termination | Limits and runtime truncation |
| Verification and evaluation inputs | Trial construction after the live transition |
An invalid action leaves state unchanged. A stale decision is rejected before it reaches task logic. Domain termination and host truncation are separate facts.
Host controls are separate from agent actions. The host alone can pause, rewind, branch, or otherwise control the run.
Branching
worlds.branch_world() creates child branches through the existing rollout-control boundary and the pump branch port. worlds.tasks_for_branches() maps those branches to tasks for later planning.
Branch creation materialises child branches and leaves the parent unchanged. Separate application operations execute, evaluate, select, or merge those children.
CLI
Discover and inspect worlds:
aec-bench task world list
aec-bench task world find seepage
aec-bench task world show dam-seepage-monitoring
aec-bench task world profiles dam-seepage-monitoringPlan and run one registered task:
aec-bench task world run dam-seepage-monitoring \
--profile synthetic-rising-seepage \
--instruction "Monitor the dam and respond as conditions evolve." \
--model <provider/model> \
--dry-runPump-specific application commands are under one nested path:
aec-bench task world pump-station --help
aec-bench task world pump-station verify --help
aec-bench task world pump-station branch --help
aec-bench task world pump-station evaluate --helpUse top-level aec-bench run for a dataset-backed experiment that can contain artefact and world tasks. See Datasets and the CLI Reference.
See Architecture for ownership and Scoring for evaluation authority.