Get a simulation running in under 5 minutes.
Install¶
git clone https://github.com/vangelis-tech/archetype.git
cd archetype
uv sync
Python 3.12+ required.
Option A: Python API¶
Define components, write a processor, spawn entities, run:
import asyncio
from daft import DataFrame, col
from archetype import ArchetypeRuntime, AsyncProcessor, Component
# 1. Define components — typed data models that become table columns
class Position(Component):
x: float = 0.0
y: float = 0.0
class Velocity(Component):
dx: float = 0.0
dy: float = 0.0
# 2. Write a processor — a DataFrame transform that runs each tick
class MovementProcessor(AsyncProcessor):
components = (Position, Velocity) # Only runs on entities with BOTH
priority = 10
async def process(self, df: DataFrame, **kwargs) -> DataFrame:
return df.with_columns({
"position__x": col("position__x") + col("velocity__dx"),
"position__y": col("position__y") + col("velocity__dy"),
})
async def main():
async with ArchetypeRuntime() as runtime:
# 3. Create a lazy world handle and stage the processor
world = runtime.world("quickstart", processors=[MovementProcessor()])
# 4. Spawn entities
for dx, dy in [(1, 2), (-1, 0.5)]:
await world.spawn(Position(x=0, y=0), Velocity(dx=dx, dy=dy))
# 5. Run 5 ticks
result = await world.run(steps=5)
print(f"Done: {result.ticks_completed} ticks, {result.commands_applied} commands")
# 6. Query state
df = await world.query(Position)
for row in df.collect().to_pylist():
print(f" entity {row['entity_id']}: x={row['position__x']}, y={row['position__y']}")
asyncio.run(main())
Key patterns in this example:
- Components are
LanceModelsubclasses — their fields become prefixed columns (position__x) - Processors declare their component requirements via
components = (...)— the engine routes matching entities automatically ArchetypeRuntimeis the recommended script boundary; useworld.as_actor(...)for explicit roles andServiceContaineronly for custom routing or lower-level orchestration
Option B: HTTP API (curl)¶
# Start the API server
archetype serve &
# Create a world
curl -s -X POST localhost:8000/worlds \
-H 'Content-Type: application/json' \
-d '{"name": "quickstart"}' | python -m json.tool
# Use the returned world_id for subsequent commands
export WID=<world-id-from-above>
# Spawn an entity with components
curl -s -X POST localhost:8000/worlds/$WID/commands \
-H 'Content-Type: application/json' \
-d '{
"type": "spawn",
"payload": {
"components": [
{"type": "Position", "x": 0, "y": 0},
{"type": "Velocity", "dx": 1, "dy": 2}
]
}
}'
# Run 5 ticks
curl -s -X POST localhost:8000/worlds/$WID/run \
-H 'Content-Type: application/json' \
-d '{"num_steps": 5}' | python -m json.tool
# Query state
curl -s localhost:8000/worlds/$WID/state | python -m json.tool
Option C: CLI Commands¶
archetype world create quickstart
archetype run <world-id> --steps 5
archetype query <world-id>
archetype history <world-id>
Next Steps¶
- Architecture — how the layers and tick lifecycle fit together
- Components — field types, Arrow serialization, column prefixing
- Processors — LLM-powered processors, structured outputs, testing
- Building Simulations — the full workflow with forking and resources
- Examples — runnable examples for every pattern