Archetype is a data-centric Entity-Component-System (ECS) simulation engine. World state is stored as columnar DataFrames. Every tick appends new rows to storage without overwriting previous state, which enables time-travel queries, world forking, and replay.

Layers¶
archetype.api / cli External interface (REST + HTTP client)
|
archetype.sugar ArchetypeRuntime, RuntimeWorld (recommended scripts)
|
archetype.app Services, RBAC, CommandBroker, WorldRegistry
|
archetype.core AsyncWorld, AsyncProcessor, Resources, Storage
The system runs as a single archetype serve process. The CLI is a thin HTTP client.
Runtime Layer¶
ArchetypeRuntime is the recommended script entry point. It owns the shared
service container, gives you lazy world handles, keeps process lifetime
separate from world lifetime, and exposes the brokered mutation surface on
RuntimeWorld:
from uuid_utils import uuid7
from archetype import ArchetypeRuntime, Component
from archetype.app.auth.models import ActorCtx
class Position(Component):
x: float = 0.0
y: float = 0.0
async with ArchetypeRuntime() as runtime:
world = runtime.world("demo")
entity_id = await world.spawn(Position(x=0, y=0))
admin = world.as_actor(ActorCtx(id=uuid7(), roles={"admin"}))
await admin.update(entity_id, Position(x=1, y=0))
await world.run(steps=10)
Drop to the service layer only when you need custom command routing, non-script hosting, or lower-level read-path / lifecycle control.
Service Layer¶
The service layer mediates all access to worlds.
ServiceContainer¶
Lower-level composition root that instantiates and exposes all service-layer subsystems:
from archetype.app.container import ServiceContainer
container = ServiceContainer()
# container.world_service -- world lifecycle
# container.command_service -- command submission
# container.simulation_service -- tick stepping
# container.query_service -- read path
# container.broker -- command queue
# container.storage_service -- storage backends
Command Flow¶
All mutations from external actors flow through the command pipeline:
- CommandService.submit() -- accepts a
Commandwith type, payload, tick, priority - CommandBroker.enqueue() -- validates RBAC via
ActorCtx, enforces quotas, queues by priority - SimulationService.step() -- drains due commands, applies them to the world, steps processors
- QueryService -- reads world state (current or historical)
RBAC¶
Every command submission requires an ActorCtx specifying the actor's roles:
| Role | Permissions |
|---|---|
viewer |
Read-only (query, get state, get world) |
player |
spawn, despawn, update, message, custom |
coder |
add/remove components, update |
operator |
trajectory ingestion and labeling |
maintainer |
spawn, despawn, components, processors, update |
admin |
All commands (wildcard) |
Quotas: 500 commands per tick, 200k token budget per day. See Token Costs and Quotas for details.
Tick Lifecycle¶
Each step() call follows this sequence:
SimulationService.step(world_id, run_config)
|
1. drain_and_apply(world_id, tick)
| CommandBroker.dequeue_due(world_id, tick)
| CommandService.apply(world, cmd) for each command
| → spawn/despawn/update mutations queue in world caches
|
2. reset_tick_counters()
| Clear per-actor command counts for next tick
|
3. world.step(run_config)
|
a. For each archetype (concurrently via asyncio.gather):
| i. Query previous state from store (or _live cache)
| ii. Materialize spawn/despawn caches into the DataFrame
| iii. Execute matching processors in priority order
| iv. Persist result via updater → store
| v. Update _live cache
|
b. Increment tick counter
c. Fire `PostTick` hooks
Commands applied in step 1 produce deferred mutations (spawn/despawn caches). Those mutations materialize in step 3a-ii of the same tick. Cross-archetype communication (messages, spawns targeting different archetypes) takes effect on the next tick.
For full details: Worlds covers the internal tick cycle, Lifecycle Hooks covers typed observability events, Data Flow covers the command pipeline, System Execution covers processor dispatch.
Deep Dives¶
Core¶
The simulation engine. No auth awareness, no multi-world management.
- Archetype -- signatures, naming, schemas, entity-to-table mapping
- Components -- Pydantic models with Arrow serialization, column prefixing, field types
- Processors -- DataFrame transforms, resource injection, LLM integration
- Systems -- subset rule, priority ordering, per-archetype parallelism
- Worlds -- tick lifecycle, deferred mutations,
_livecache, forking - Lifecycle Hooks -- typed world events, async/sync handlers, hook failure policy
- Resources -- type-keyed dependency injection for world-level shared state
- Stores -- storage backends, append-only model, write-behind cache
- Querier -- filtered reads by tick, entity, and component projection
- Updater -- metadata stamping before append
- Configuration -- RunConfig, WorldConfig, StorageConfig, CacheConfig
App¶
The service layer. RBAC, command pipeline, multi-world orchestration.
- Overview -- how core connects through services to the API
- Services -- ServiceContainer, dependency graph, each service's role
- Command Broker -- priority queue, RBAC guardrails, audit trail
- API Layer -- FastAPI routes, dependency injection, CLI
- Data Flow -- read/write split, command pipeline, RBAC boundary, drain cycle