An agent represents a single decision-maker in the simulation. Foundation ships with two built-in agent types that cover the most common research patterns. This page explains their design and shows when and how to create your own agent type.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.
The two built-in agent types
BasicMobileAgent
Represents an embodied individual actor. Has a
loc (2D grid position), inventory, escrow, and endogenous quantities. Can navigate the world map and interact with resources.BasicPlanner
Represents a social planner. Has no physical location—
loc is removed from its state. Its index is always "p" regardless of the idx argument passed at construction. Intended to be unique (one per environment).When to create a custom agent type
The built-in agents cover most use cases. Create a new agent type only when you need structural differences that cannot be expressed through component state fields, such as:- A second class of mobile agent with different physical rules (e.g. a firm agent versus a household agent)
- An agent that should never appear in
world.agents(Foundation currently places all non-planner agents there) - An agent where
locsemantics differ from the 2D grid (e.g. a multi-dimensional position)
If you only need agents to carry extra data, use
BaseComponent.get_additional_state_fields() instead of creating a new agent type. Those fields are merged directly into agent.state without any subclassing.Agent state layout
BaseAgent.__init__ initialises agent.state as:
| Field | Type | Populated by | Description |
|---|---|---|---|
loc | [row, col] | World constructor | 2D grid position. Removed by BasicPlanner. |
inventory | {resource: float} | agent.register_inventory(resources) | Quantities the agent directly holds. |
escrow | {resource: float} | agent.register_inventory(resources) | Reserved quantities (e.g. pending trade orders). |
endogenous | {name: float} | agent.register_endogenous(endogenous) | Non-inventory quantities such as Labor. |
get_additional_state_fields) are merged directly into agent.state by agent.register_components().
Agent indexing conventions
Mobile agents are indexed with integers starting from0. The planner is always indexed as the string "p".
str(agent.idx), so mobile agent keys are "0", "1", etc., and the planner key is "p".
The idx passed to the constructor is stored as an int for numeric values and as-is for strings:
Step-by-step: implementing a custom agent type
Subclass BaseAgent and set the name attribute
The If no further customisation is needed—just a new named type—this is the complete definition, mirroring
name attribute is the registry key. It must be a non-empty string containing no . characters.BasicMobileAgent.Override __init__ to adjust state structure
Modify
agent.state in __init__ to add, remove, or rename fields. Always call super().__init__() first.Override the loc property if needed
BaseAgent.loc reads from self.state["loc"]. If you deleted that key, override the property to prevent confusing KeyError messages—following the pattern in BasicPlanner:Register the agent type
The
@agent_registry.add decorator does all the work. After it runs, the agent is retrievable via:Complete minimal example
firm_agent.py
FirmAgent in a scenario and component:
Key BaseAgent API reference
Once constructed, agent objects expose the following API used by components and scenarios:| Method / Property | Description |
|---|---|
agent.idx | Unique index. Integer for mobile agents, "p" for the planner. |
agent.loc | [row, col] position. Raises AttributeError if removed. |
agent.inventory | Dict of {resource_name: float} quantities held. |
agent.escrow | Dict of reserved resource quantities. |
agent.endogenous | Dict of endogenous quantities (e.g. {"Labor": 3.5}). |
agent.total_endowment(resource) | Sum of inventory[resource] and escrow[resource]. |
agent.inventory_to_escrow(resource, amount) | Move quantity from inventory to escrow. |
agent.escrow_to_inventory(resource, amount) | Move quantity from escrow to inventory. |
agent.get_component_action(component_name) | Return the current action index for a component. |
agent.reset_actions() | Reset all action buffers to NO-OP (0). |
agent.action_spaces | Total action count (single-action mode) or array of per-subspace counts (multi-action mode). |