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 organises world state into three categories of entity: Resources, Landmarks, and Endogenous variables. Each category has its own registry, base class, and role in the simulation.
Resources
Defined in entities/resources.py. A Resource is anything that can sit in an agent’s inventory.
class Resource:
name = None
color = None # RGB array, values in [0, 1]
collectible = None # True → exists on the world map and can be gathered
When collectible=True, the framework automatically creates a paired {Name}SourceBlock Landmark (see below) and allocates two world-map channels: one for the source block locations and one for the resource amounts currently on the ground.
Built-in resources
# entities/resources.py
@resource_registry.add
class Wood(Resource):
"""Wood resource. collectible."""
name = "Wood"
color = np.array([107, 143, 113]) / 255.0
collectible = True
@resource_registry.add
class Stone(Resource):
"""Stone resource. collectible."""
name = "Stone"
color = np.array([241, 233, 219]) / 255.0
collectible = True
@resource_registry.add
class Coin(Resource):
"""Coin resource. Included in all environments by default. Not collectible."""
name = "Coin"
color = np.array([229, 211, 82]) / 255.0
collectible = False # Coin is earned/spent, never gathered from the map
Coin is added to every environment automatically—you do not need to declare it in required_entities.
Registering a custom resource
from ai_economist.foundation.entities.resources import Resource, resource_registry
import numpy as np
@resource_registry.add
class Iron(Resource):
name = "Iron"
color = np.array([180, 140, 100]) / 255.0
collectible = True
Include "Iron" in your scenario’s or component’s required_entities list to activate it.
Landmarks
Defined in entities/landmarks.py. A Landmark exists exclusively in the world map—it is never part of an agent’s inventory. Landmarks control whether a tile is passable and who (if anyone) owns it.
class Landmark:
name = None
color = None
ownable = None # Does a specific agent own each instance?
solid = True # Does this landmark block movement?
Three derived properties are set at construction time:
| Property | Condition | Meaning |
|---|
blocking | solid and not ownable | No agent can pass through |
private | solid and ownable | Only the owning agent can pass through |
public | not solid and not ownable | All agents can occupy freely |
Built-in landmarks
# entities/landmarks.py
@landmark_registry.add
class House(Landmark):
"""House landmark. Ownable. Solid."""
name = "House"
color = np.array([220, 20, 220]) / 255.0
ownable = True
solid = True # private: only the owner can stand on it
@landmark_registry.add
class Water(Landmark):
"""Water Landmark. Not ownable. Solid."""
name = "Water"
color = np.array([50, 50, 250]) / 255.0
ownable = False
solid = True # blocking: no agent can cross it
For every collectible resource, a source-block landmark is generated automatically:
# Executed at module load for each collectible resource
@landmark_registry.add
class SourceBlock(Landmark):
"""Special Landmark for generating resources. Not ownable. Not solid."""
name = "WoodSourceBlock" # or "StoneSourceBlock", etc.
ownable = False
solid = False # public: agents move freely over it
So the landmark registry always contains at least WoodSourceBlock, StoneSourceBlock, House, and Water in a typical wood-and-stone scenario.
Endogenous variables
Defined in entities/endogenous.py. Endogenous variables capture the internal state of an agent—quantities that are conceptually private to the agent and not directly observable by others.
class Endogenous:
name = None
Built-in endogenous variable
# entities/endogenous.py
@endogenous_registry.add
class Labor(Endogenous):
"""Labor accumulated through working. Included in all environments by default."""
name = "Labor"
Labor is added to every environment automatically and is accessible on each mobile agent:
agent.endogenous["Labor"] # → float, e.g. 30.25
Registering a custom endogenous variable
from ai_economist.foundation.entities.endogenous import Endogenous, endogenous_registry
@endogenous_registry.add
class Stress(Endogenous):
name = "Stress"
Then declare "Stress" in your component’s required_entities to have it registered on agents.
How entities compose the World state
During environment construction, BaseEnvironment.__init__ collects all entity names from the scenario’s required_entities and from each component’s required_entities. It classifies each name against the three registries:
# base_env.py (simplified)
self._entities = {
"resources": ["Coin"], # always present
"landmarks": [],
"endogenous": ["Labor"], # always present
}
self._register_entities(self.required_entities)
for component_cls in component_classes:
self._register_entities(component_cls.required_entities)
The resulting entity lists are then passed to World, which allocates:
- One numpy map channel per collectible resource — tracks ground-level resource amounts
- One numpy map channel per source-block landmark — tracks where resources regenerate
- One numpy map channel per non-ownable landmark (e.g. Water) — tracks blocking tiles
- One per-cell
(owner, health) pair per ownable landmark (e.g. House)
Each mobile agent’s inventory is populated with a {resource_name: 0} entry for every registered resource, and its endogenous dict with a {endogenous_name: 0} entry for every registered endogenous variable.
# Accessing entity maps at runtime
env.world.maps.get("Wood") # 2-D numpy array of wood on the ground
env.world.maps.get("WoodSourceBlock") # 2-D array of source block locations
env.world.maps.get("House") # dict with 'owner' and 'health' arrays
# Entity lists on the environment
env.resources # → ['Coin', 'Stone', 'Wood']
env.landmarks # → ['House', 'StoneSourceBlock', 'Water', 'WoodSourceBlock']
env.endogenous # → ['Labor']