Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/salesforce/ai-economist/llms.txt

Use this file to discover all available pages before exploring further.

Foundation is a multi-agent economic simulation framework. Every simulation is an instance of a Scenario class—a subclass of BaseEnvironment—that composes Components, Agents, and Entities into a runnable environment with a standard Gym-style API.

Core building blocks

Scenarios

Subclasses of BaseEnvironment that define passive world dynamics, observations, and reward functions.

Components

Pluggable modules that add action spaces and active dynamics on top of a scenario.

Agents

Stateful actors—mobile agents and a social planner—that act inside the world.

Entities

Resources, Landmarks, and Endogenous variables that make up the world state.

Architecture overview

At the top sits BaseEnvironment (base_env.py). Concrete scenario classes inherit from it and are registered in scenario_registry. Each scenario instantiates:
  • A World object (the 2-D map plus agent objects)
  • One BasicPlanner and n_agents BasicMobileAgent instances
  • One component object per entry in the components constructor argument
All four kinds of building blocks—Scenarios, Components, Agents, and Entities—are registered via the same Registry utility and looked up by name at construction time.
foundation.scenarios   # scenario_registry  → BaseEnvironment subclasses
foundation.components  # component_registry → BaseComponent subclasses
foundation.agents      # agent_registry     → BaseAgent subclasses
foundation.resources   # resource_registry  → Resource subclasses
foundation.landmarks   # landmark_registry  → Landmark subclasses
foundation.endogenous  # endogenous_registry→ Endogenous subclasses

Episode data flow

Each episode follows a fixed sequence:
env.reset()
  └── reset_starting_layout()     # scenario: place resources & landmarks
  └── reset_agent_states()        # scenario: set agent locations & inventories
  └── component.reset()           # each component resets internal state
  └── _generate_observations()    # collect obs from scenario + components
  └── returns obs

env.step(actions)
  └── parse_actions(actions)      # dispatch actions into agent buffers
  └── component.component_step()  # each component applies its dynamics
  └── scenario_step()             # passive scenario dynamics (e.g. resource regen)
  └── _generate_observations()    # obs from scenario + components
  └── compute_reward()            # scenario computes per-agent rewards
  └── returns obs, rew, done, info
Observations are assembled from two sources: generate_observations() on the scenario, and generate_observations() on each component. The environment merges them and optionally flattens them into a single "flat" numpy array per agent.

Registry-based plugin system

Every building block registers itself with a @registry.add decorator. The Registry class (base/registrar.py) stores a {name.lower(): class} lookup and enforces that every entry is a subclass of the corresponding base class.
from ai_economist.foundation.base.base_component import (
    BaseComponent,
    component_registry,
)

@component_registry.add
class MyComponent(BaseComponent):
    name = "MyComponent"
    component_type = "Custom"
    agent_subclasses = ["BasicMobileAgent"]
    required_entities = ["Coin"]
    ...
The same pattern applies to scenarios, agents, and entities:
from ai_economist.foundation.base.base_env import BaseEnvironment, scenario_registry

@scenario_registry.add
class MyScenario(BaseEnvironment):
    name = "my/scenario"
    agent_subclasses = ["BasicMobileAgent", "BasicPlanner"]
    required_entities = ["Wood", "Stone"]
    ...
Registered names must be unique within each registry and must not contain a . character. Look up a class by name with registry.get(name), and check existence with registry.has(name).

Constructing an environment

from ai_economist import foundation

env = foundation.scenarios.get("uniform/simple_wood_and_stone")(
    components=[
        ("Build", {"payment": 20}),
        ("Gather", {"move_labor": 1.0, "collect_labor": 2.0}),
    ],
    n_agents=10,
    world_size=[25, 25],
    episode_length=1000,
)

obs = env.reset()
actions = {agent.idx: agent.get_random_action() for agent in env.all_agents}
obs, rew, done, info = env.step(actions)
The components argument is an ordered list of ("ComponentName", {kwargs}) tuples. The order matters: component_step() and generate_observations() are called in the listed order every timestep.
Coin and Labor are always included in every environment. Coin is added to resources automatically; Labor is added to endogenous variables automatically.