Agent Lifecycle
ABMForge agents have a small but explicit lifecycle contract.
The goal is to make agent creation, removal, event cancellation, spatial removal, and lifecycle recording predictable and reproducible.
Lifecycle statuses
ABMForge currently defines two agent lifecycle statuses:
| Status | Meaning |
|---|---|
active |
The agent is alive and can participate in simulation |
removed |
The agent has been removed from the model |
New agents start as:
agent.lifecycle_status == "active"
agent.is_alive is True
When an agent is removed:
agent.lifecycle_status == "removed"
agent.is_alive is False
Creating agents
Agents are normally created through the model's agent collection:
agent = model.agents.create(MyAgent, wealth=10)
or in batches:
agents = model.agents.create(MyAgent, n=100, wealth=10)
Each agent receives a stable unique_id.
Removing agents
Agents can remove themselves:
agent.remove()
This calls:
model.remove_agent(agent)
Agents can also be removed directly by id:
model.remove_agent(agent.unique_id)
Removal guarantees
When an agent is removed, ABMForge guarantees the following behaviour:
agent.remove()
-> agent.is_alive = False
-> agent.lifecycle_status = "removed"
-> agent is removed from model.agents
-> agent is removed from model.world, if a world is attached
-> pending events owned by the agent are cancelled
-> lifecycle_records receives an "agent_removed" record
-> event_records receives "cancelled" records for cancelled owned events
This contract makes removal behaviour easier to test, audit, and reproduce.
Collection removal
After removal, the agent is no longer in the model's agent collection.
agent.remove()
assert agent.unique_id not in model.agents
Looking up a removed agent by id should fail.
World removal
If the model has a spatial world attached, ABMForge attempts to remove the agent from the world as well.
Example:
model.world.place(agent, (2, 2))
agent.remove()
assert not hasattr(agent, "pos")
The agent's position is cleared by the space implementation.
Owned event cancellation
ABMForge's event queue supports event ownership.
When an agent is removed, pending events owned by that agent are cancelled.
Example:
model.events.schedule(
callback=lambda: None,
after=1.0,
owner=agent.unique_id,
)
agent.remove()
The pending event is cancelled and should not execute later.
This is important for event-driven ABM models where agents schedule future actions.
Lifecycle records
Agent removal writes a lifecycle record.
A typical lifecycle record contains:
run_id
step
time
event = "agent_removed"
agent_id
details
Lifecycle records make simulation history easier to inspect after a run.
Event records
If owned events are cancelled during agent removal, ABMForge records event transitions with status:
cancelled
This links agent lifecycle changes to the event queue audit trail.
Snapshot behaviour
lifecycle_status is framework-managed lifecycle metadata.
It is intentionally excluded from user-facing agent snapshot state.
For example, if an agent has user attributes:
agent.wealth = 10
agent.mood = "happy"
the snapshot user state should contain:
{
"wealth": 10,
"mood": "happy",
}
not framework internal lifecycle metadata.
Modelling recommendation
Use agent.remove() when the removal is initiated by the agent itself.
Use model.remove_agent(agent_id) when the removal is initiated by the model, scheduler, policy rule, or external event.
Research reproducibility recommendation
If agent removal is part of the model's scientific mechanism, document:
- why agents are removed,
- when removal happens,
- whether removed agents can re-enter,
- whether removal cancels future events,
- which lifecycle records are expected.
This makes model behaviour easier to audit and reproduce.