World Spec API
The world-runner exposes a small set of admin-only HTTP endpoints for uploading and activating world and region specs at runtime — no restart required.
All endpoints require an authenticated session with the Admin role. Unauthenticated requests receive 401 Unauthorized; non-admin sessions receive 403 Forbidden.
Region Specs
A region spec is a YAML document that describes a single region (geometry, tile materials, tags, etc.). Regions must be uploaded before a world spec that references them.
Upload a region spec
POST /spec/region
Content-Type: application/x-yaml
Body: Raw YAML of the region spec. The spec must contain a meta.genome field — this is the canonical identifier used for all subsequent lookups.
Success — 200 OK
{
"name": "amboseli",
"title": "Amboseli Basin",
"genome": "01a2fc988f4dee38"
}
Errors
| Status | error field |
Meaning |
|---|---|---|
400 |
invalid_utf8 |
Body is not valid UTF-8 |
422 |
invalid_region_spec |
YAML is malformed or missing required fields |
Retrieve a region spec
GET /spec/region/{genome}
Returns the raw YAML that was uploaded for the given genome, or 404 if not found.
Success — 200 OK
Content-Type: application/x-yaml; charset=utf-8
meta:
genome: "01a2fc988f4dee38"
name: amboseli
...
Errors
| Status | error field |
Meaning |
|---|---|---|
404 |
not_found |
No region spec stored for this genome |
World Specs
A world spec declares which regions compose the active world, using short alias names that reference uploaded region specs.
Provision a world
POST /world/spec
Content-Type: application/x-yaml
Body: Raw YAML of the world spec. The spec must declare world_id and a refs.regions map whose keys are the alias names used inside regions.
What this endpoint does:
- Parses and validates the world spec YAML.
- Resolves each region alias against the in-memory spec store (by ref alias → name → genome). Returns
422immediately if any alias cannot be resolved. - Pauses a running continuous clock (resumed unconditionally when the operation finishes).
- Atomically replaces the live region registry with the newly built one.
- Stores the world YAML as the active world; subsequent
GET /world/specreturns it.
Success — 200 OK
{
"world_id": "starter_world",
"region_count": 2,
"regions": ["amboseli", "pictou"]
}
Errors
| Status | error field |
Meaning |
|---|---|---|
400 |
invalid_utf8 |
Body is not valid UTF-8 |
422 |
invalid_world_spec |
YAML is malformed or missing required fields |
422 |
missing_region_refs |
One or more region aliases have not been uploaded yet. The response includes a missing_refs array. |
409 |
clock_pause_failed |
The running clock could not be paused before the swap |
422 |
world_provision_failed |
The registry replacement step itself failed |
500 |
world_replace_task_failed |
An internal async task panic occurred |
Missing refs example:
{
"error": "missing_region_refs",
"missing_refs": ["pictou"]
}
Upload the missing region specs and retry.
Retrieve the active world spec
GET /world/spec
Returns the raw YAML of the most recently provisioned world spec.
Success — 200 OK
Content-Type: application/x-yaml; charset=utf-8
world_id: starter_world
refs:
regions:
amboseli: ...
pictou: ...
Errors
| Status | error field |
Meaning |
|---|---|---|
404 |
not_found |
No world has been provisioned yet |
Typical provisioning flow
# 1. Authenticate and obtain a session token
TOKEN=$(curl -sX POST http://localhost:8080/token -d '{"admin_secret":"..."}' | jq -r .token)
# 2. Upload each region spec
curl -X POST http://localhost:8080/spec/region \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/x-yaml" \
--data-binary @regions/amboseli.yaml
curl -X POST http://localhost:8080/spec/region \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/x-yaml" \
--data-binary @regions/pictou.yaml
# 3. Retrieve a region spec to verify
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8080/spec/region/01a2fc988f4dee38
# 4. Provision the world
curl -X POST http://localhost:8080/world/spec \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/x-yaml" \
--data-binary @worlds/starter_world.yaml
# 5. Verify the active world
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:8080/world/spec
Genome — the canonical identity
meta.genome in a region spec is the single source of truth for that region's identity. It is a stable, opaque hex string generated once and embedded in the spec file itself.
- Upload uses
meta.genomefrom the body — there is no genome in the POST path. - Retrieval addresses by genome:
GET /spec/region/{genome}. - World specs reference regions by short alias names (e.g.
amboseli). The provisioning step resolves aliases to genomes automatically.
This means renaming an alias in a world spec without changing the underlying spec file is safe — the genome is unaffected.
Generic Spec Endpoints
Alongside dedicated world and region APIs, the runner exposes generalized spec storage and instantiation endpoints.
Upload any registered kind
POST /spec/{kind}
Content-Type: application/x-yaml
Returns:
{
"kind": "simulation.vehicle",
"id": "beatle_test_001"
}
Retrieve by kind and id
GET /spec/{kind}/{id}
Returns raw YAML.
List ids for a kind
GET /spec/{kind}
Returns:
{
"kind": "simulation.vehicle",
"ids": ["beatle_test_001"]
}
Instantiate a stored spec
POST /spec/{kind}/{id}/instantiate
Whitelisted instantiable kinds:
- simulation.vehicle
- earth.animal
- simulation.region
- social.fate
Storage-only kinds return 422 with error not_instantiable.
Example vehicle response:
{
"kind": "simulation.vehicle",
"id": "beatle_test_001",
"instance": {
"vehicle_id": "beatle_test_001-...",
"genome": "...",
"architecture": "...",
"region_id": "coreland"
}
}
Notes
- The spec store is in-memory only. Uploaded specs do not persist across world-runner restarts. Re-upload region specs and re-provision the world after a restart (or pass
--world-specat startup to seed from disk). - Provisioning is atomic: either the full registry is replaced or the existing registry is left intact and an error is returned.
- Clock management is transparent: if the simulation clock is running in continuous mode it is paused during the swap and resumed (or left paused on error) — callers do not need to pause manually.
- Schema fixture and document resolution conventions are described in runtime/schema-discovery.