reset / step interface.
Create a custom scenario when the existing scenarios do not match your research question—for example, a new geography, a different reward structure, or passive dynamics that no existing scenario implements.
How scenarios relate to components
Scenarios and components have complementary roles:
A scenario lists the components it expects in
component_set and passes them as the components argument when instantiating the environment.
Required abstract methods
EveryBaseEnvironment subclass must implement five abstract methods. The signatures below come directly from base_env.py:
reset_starting_layout()
reset_starting_layout()
self.world.maps to write to the spatial state.reset_agent_states()
reset_agent_states()
reset_starting_layout(). Clear inventories, escrow, and endogenous quantities, then place agents at their starting locations.scenario_step()
scenario_step()
generate_observations()
generate_observations()
{agent_idx: obs_dict}. Observations from the scenario are prefixed with "world-" when merged into the full observation bundle. The structure must remain the same for every call within an episode.compute_reward()
compute_reward()
0.0 for agents whose objectives are not modelled.Step-by-step: implementing a custom scenario
1
Set class attributes and declare entities
required_entities lists the world entities the scenario depends on. Coin and Labor are always present by default. Additional resources, landmarks, and endogenous variables are registered from this list and from each included component’s required_entities.2
Define __init__ with env_config kwargs
Accept scenario-specific parameters before forwarding to After
super().__init__():super().__init__() you can access:self.world—Worldobject wrapping the map, agents, and plannerself.world.agents— list of mobile agent objectsself.world.planner— the planner agent objectself.n_agents— number of mobile agentsself.world_size—[height, width]of the mapself.episode_length— timesteps per episode
3
Implement reset_starting_layout
Populate the world map with resources and landmarks.For a scenario with no spatial resources (like
OneStepEconomy), leave this as a no-op:4
Implement reset_agent_states
Clear agent state and set initial conditions.
5
Implement scenario_step
Define passive world dynamics that run every timestep regardless of agent actions.Leave as a no-op if all dynamics come from components:
6
Implement generate_observations
Produce scenario-level observations. These are prefixed with
"world-" when merged.self.inv_scale is 0.01 when allow_observation_scaling=True and 1 otherwise. Apply it to inventory quantities to keep observation values in a RL-friendly range.7
Implement compute_reward
Return a scalar reward for every agent (including the planner) at every timestep.
8
Add optional customization hooks
Two optional methods let you extend reset and metric reporting:
Registering the scenario
scenario.name (case-insensitive). The scenario is exposed as:
Instantiating the environment
Pass component specs as a list of("ComponentName", {kwargs}) tuples:
OneStepEconomy as a reference
The built-inOneStepEconomy scenario (ai_economist/foundation/scenarios/one_step_economy/one_step_economy.py) is an ideal minimal reference. It has a no-op reset_starting_layout, a clean reset_agent_states, a no-op scenario_step, and well-documented generate_observations and compute_reward implementations.