Sessions
Session lifecycle — create, inspect, close, snapshot, restore.Available scenario packs
List scenario packs discoverable on disk. Dynamic: drop a new *.yaml into the scenarios directory and it appears.
Pass a scenario path as the body of POST /v1/sessions to create a session.
| scenario_id | path | ruleset | chronon | locations | entities | synths |
|---|
| dockside_outpost | scenarios/dockside_outpost.yaml | physical_social_v1 | 240s | 3 | 8 | 3 |
| lighthouse | scenarios/lighthouse.yaml | physical_social_v1 | 300s | 4 | 12 | 3 |
| lighthouse_fork | data/scenarios/lighthouse_fork.yaml | physical_social_v1 | 300s | 4 | 12 | 3 |
| lighthouse_test_base | data/scenarios/lighthouse_test_base.yaml | physical_social_v1 | 300s | 4 | 12 | 3 |
| night_clinic | scenarios/night_clinic.yaml | physical_social_v1 | 180s | 3 | 7 | 3 |
| park_bench | scenarios/park_bench.yaml | physical_social_v1 | 180s | 3 | 5 | 2 |
| storm_cellar | scenarios/storm_cellar.yaml | physical_social_v1 | 240s | 3 | 8 | 3 |
| workshop_blackout | scenarios/workshop_blackout.yaml | physical_social_v1 | 240s | 3 | 8 | 3 |
Create a new scenario
POSThttps://singing-bird.benac.dev/v1/scenariosscope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Sample request body (Run sends this):
{
"scenario_id": "my_draft"
}Replace scenario contents
PUThttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}scope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Sample request body (Run sends this):
{
"content": {
"scenario_id": "my_draft",
"schema_version": 1,
"world": {}
}
}Delete a user scenario
DELETEhttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}scope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Fork a scenario under a new id
POSThttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/forkscope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Sample request body (Run sends this):
{
"new_scenario_id": "lighthouse_v2"
}Add a location
POSThttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/locationsscope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Sample request body (Run sends this):
{
"id": "garden",
"name": "Walled Garden",
"kind": "exterior",
"description": "A quiet garden."
}Replace a location (destructive)
PUThttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/locations/{loc_id}scope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Sample request body (Run sends this):
{
"id": "garden",
"name": "Overgrown Garden",
"kind": "exterior"
}Patch a location (merge)
PATCHhttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/locations/{loc_id}scope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Sample request body (Run sends this):
{
"description": "Now with a fountain."
}Remove a location
DELETEhttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/locations/{loc_id}scope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Add a ruleset-validated entity
POSThttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/entitiesscope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Sample request body (Run sends this):
{
"id": "bench",
"name": "Bench",
"location": "garden",
"components": [
{
"type": "seating",
"capacity": 2
}
]
}Replace an entity (destructive)
PUThttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/entities/{entity_id}scope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Sample request body (Run sends this):
{
"id": "bench",
"name": "Stone Bench",
"location": "garden",
"components": [
{
"type": "seating",
"capacity": 4
}
]
}Patch an entity (merge)
PATCHhttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/entities/{entity_id}scope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Sample request body (Run sends this):
{
"name": "Stone Bench"
}Remove an entity
DELETEhttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/entities/{entity_id}scope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Add a synth
POSThttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/synthsscope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Sample request body (Run sends this):
{
"id": "alice",
"entity": "alice_body",
"identity": {
"name": "Alice",
"kind": "human"
},
"embodiment_profile": "standard_human",
"cognition": {
"model": "@chat",
"temperature": 0.7
}
}Replace a synth (destructive; drops unsent fields)
PUThttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/synths/{synth_id}scope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Sample request body (Run sends this):
{
"id": "alice",
"entity": "alice_body",
"identity": {
"name": "Alice",
"kind": "human"
},
"embodiment_profile": "standard_human",
"cognition": {
"model": "@chat"
}
}Patch a synth (merge; safest way to tweak)
PATCHhttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/synths/{synth_id}scope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Sample request body (Run sends this):
{
"initial_state": {
"beliefs": []
}
}Remove a synth
DELETEhttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/synths/{synth_id}scope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Connect two locations
POSThttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/adjacencyscope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Sample request body (Run sends this):
{
"from": "start",
"to": "garden",
"kind": "path",
"bidirectional": true
}Disconnect two locations
DELETEhttps://singing-bird.benac.dev/v1/scenarios/{scenario_id}/adjacency?from_location={from}&to_location={to}scope: operate
Scenario authoring — writes to data/scenarios/. Shipped baselines stay read-only; writes to a shipped id shadow the original.
Requires:
Inspect a scenario pack
Full pre-hydration view of a scenario — locations, entities, synths, processes, latent facts, embodiment profiles, environment. Pass ?format=raw for the unparsed YAML text.
dockside_outpost · scenarios/dockside_outpost.yaml · ruleset physical_social_v1 · chronon 240s · seed 777
Synths (3)
| id | name | kind | model | embodiment | mood | traits | beliefs | projects | memories |
|---|
| inez | Inez | human | @chat | standard_human | focused | steady, brisk, unsentimental | 2 | 1 | 1 |
| pavel | Pavel | human | @chat | standard_human | uncertain | patient, skeptical, cold, polite | 1 | 1 | 1 |
| sora | Sora | human | @chat | standard_human | watchful | capable, laconic, watchful | 2 | 1 | 1 |
Locations (3)
| id | name | kind | parent | description |
|---|
| dock_shed | Dock Shed | room | — | A salt-stiff wooden shed holding ropes, spare lantern parts, a bench, and a thermos that has gone lukewarm.
|
| pier | Pier | exterior | — | Wet planks stretching out into gray water. The railings sweat with fog and the morning is not yet fully awake.
|
| road_turnout | Road Turnout | exterior | — | A gravel turnout above the dock where travelers wait for the first boat or decide not to trust the weather.
|
Entities (8)
| id | name | location | mobility | components |
|---|
| signal_lantern | Signal Lantern | pier | fixed | light_source, repairable, switchable, fixed |
| fog_bell | Fog Bell | pier | fixed | fixed, sound_source |
| supply_crate | Supply Crate | dock_shed | movable | container |
| thermos | Thermos | dock_shed | movable | portable, consumable |
| mooring_rope | Mooring Rope | pier | fixed | fixed, sound_source |
| inez_body | Inez | dock_shed | movable | — |
| pavel_body | Pavel | road_turnout | movable | — |
| sora_body | Sora | pier | movable | — |
Adjacency (2)
| from | to | kind | bidirectional |
|---|
| dock_shed | pier | door | yes |
| pier | road_turnout | path | yes |
Processes (2)
| id | name | kind | initial_state | transitions |
|---|
| fog_thickens | Fog Thickens | weather | harbor_fog | 1 |
| morning_lifts | Morning Slow Lift | celestial | predawn | 1 |
Latent facts (1)
| id | scope | description |
|---|
| mantle_truth | signal_lantern | What is actually wrong with the signal lantern |
Environment (initial)
{
"celestial": {
"sun_altitude": -4.0,
"phase": "predawn",
"description": "Predawn gray presses down on the harbor and blurs the horizon."
},
"weather": {
"condition": "foggy",
"wind_speed": 8.0,
"wind_direction": "east",
"description": "Fog banks drift through the pilings and leave everything beaded with water."
},
"ambient": {
"light_level": 0.18,
"temperature": 11.0
}
}Embodiment profiles: standard_human
Raw YAML (9973 bytes)
scenario_id: dockside_outpost
schema_version: 1
ruleset_ref: physical_social_v1
random_seed: 777
runtime_defaults:
chronon_interval_seconds: 240
max_recursion_depth: 6
max_events_per_cycle: 60
profiles:
embodiment_profiles:
standard_human:
sensory:
- channel: visual
range: 70.0
acuity: 1.0
- channel: auditory
range: 45.0
acuity: 1.0
- channel: tactile
range: 1.0
acuity: 1.0
- channel: proprioceptive
range: 0.0
acuity: 1.0
actuators:
- name: hands
description: can carry, inspect, and manipulate objects
range: 1.5
- name: locomotion
description: can move between shed and pier
range: 1.0
communication:
- speech
world:
simulation_time: "2026-08-29T05:40:00"
chronon_interval_seconds: 240
topology:
locations:
- id: dock_shed
name: Dock Shed
kind: room
description: >
A salt-stiff wooden shed holding ropes, spare lantern parts,
a bench, and a thermos that has gone lukewarm.
- id: pier
name: Pier
kind: exterior
description: >
Wet planks stretching out into gray water. The railings sweat with
fog and the morning is not yet fully awake.
- id: road_turnout
name: Road Turnout
kind: exterior
description: >
A gravel turnout above the dock where travelers wait for the first
boat or decide not to trust the weather.
adjacency:
- from: dock_shed
to: pier
kind: door
bidirectional: true
- from: pier
to: road_turnout
kind: path
bidirectional: true
entities:
- id: signal_lantern
name: Signal Lantern
location: pier
mobility: fixed
description: A harbor lantern mounted chest-high near the end of the pier.
components:
- type: light_source
functional: false
intensity: 3.5
range: 60.0
description: "The lantern is dark and glass-fogged."
- type: repairable
condition: dirty_mantle
difficulty: 0.45
description: "The mantle assembly is dirty and the latch sticks."
- type: switchable
state: "off"
- type: fixed
- id: fog_bell
name: Fog Bell
location: pier
mobility: fixed
description: A hand bell mounted on a post by the rail.
components:
- type: fixed
- type: sound_source
description: "Metal rings out dull and heavy through the fog."
volume: 0.4
- id: supply_crate
name: Supply Crate
location: dock_shed
mobility: movable
description: A dock crate with simple emergency supplies.
components:
- type: container
contents: [rag, matches, spare_mantle]
- id: thermos
name: Thermos
location: dock_shed
mobility: movable
description: A metal thermos with a little coffee left in it.
components:
- type: portable
- type: consumable
uses_remaining: 1
effect_description: "The coffee is lukewarm and bitter, but it wakes you up."
- id: mooring_rope
name: Mooring Rope
location: pier
mobility: fixed
description: Rope knocking softly against a wet cleat.
components:
- type: fixed
- type: sound_source
description: "Wet rope taps and scrapes against the cleat."
volume: 0.2
- id: inez_body
name: Inez
location: dock_shed
mobility: movable
components: []
- id: pavel_body
name: Pavel
location: road_turnout
mobility: movable
components: []
- id: sora_body
name: Sora
location: pier
mobility: movable
components: []
environment:
celestial:
sun_altitude: -4.0
phase: predawn
description: "Predawn gray presses down on the harbor and blurs the horizon."
weather:
condition: foggy
wind_speed: 8.0
wind_direction: east
description: "Fog banks drift through the pilings and leave everything beaded with water."
ambient:
light_level: 0.18
temperature: 11.0
processes:
- id: fog_thickens
name: Fog Thickens
kind: weather
initial_state: harbor_fog
transitions:
- from: harbor_fog
to: heavy_fog
trigger_time: "2026-08-29T05:48:00"
effects:
"environment.weather.condition": "heavy_fog"
"environment.ambient.light_level": 0.12
visual_description: "The fog thickens until shapes feel cut from paper."
auditory_description: "Every sound seems closer and farther at once in the fog."
description: "Fog closes in"
- id: morning_lifts
name: Morning Slow Lift
kind: celestial
initial_state: predawn
transitions:
- from: predawn
to: first_light
trigger_time: "2026-08-29T05:56:00"
effects:
"environment.celestial.phase": "first_light"
"environment.celestial.sun_altitude": 1.0
"environment.ambient.light_level": 0.28
visual_description: "A pale line of morning appears behind the fog."
description: "First light shows through"
latent_facts:
- id: mantle_truth
scope: signal_lantern
description: "What is actually wrong with the signal lantern"
allowed_values: [dirty_mantle, loose_latch, damp_fuel_line]
default_prior: dirty_mantle
synths:
- id: inez
entity: inez_body
embodiment_profile: standard_human
identity:
name: Inez
kind: human
biography: >
Inez opens the outpost before dawn and thinks in checklists when the
weather turns doubtful.
traits: [steady, brisk, unsentimental]
values: [reliability, safety, competence]
initial_state:
believed_location: Dock Shed
affect:
mood: focused
valence: 0.0
arousal: 0.4
stress: 0.3
drives: [get the signal lantern working, read the weather, decide whether service is wise]
beliefs:
- subject: signal lantern
predicate: is
value: out and needs attention
confidence: 0.9
source_modality: prior
- subject: the fog
predicate: is
value: thick enough that people will start asking questions
confidence: 0.8
source_modality: visual
projects:
- title: Restore the dock signal
goal: Get the lantern working before the first real movement on the pier
motivation: Bad weather is survivable; bad weather and confusion are worse
status: active
priority: 1
memories:
- type: semantic
content: "In fog, people trust a lit signal more than any spoken reassurance."
salience: 0.6
source_modality: prior
cognition:
model: "@chat"
temperature: 0.9
- id: pavel
entity: pavel_body
embodiment_profile: standard_human
identity:
name: Pavel
kind: human
biography: >
Pavel arrived early for the crossing and now suspects he may be early
for bad news instead.
traits: [patient, skeptical, cold, polite]
values: [clarity, caution, getting where I said I would go]
initial_state:
believed_location: Road Turnout
affect:
mood: uncertain
valence: -0.1
arousal: 0.4
stress: 0.2
drives: [learn whether the crossing is happening, stay warm, not waste the morning]
beliefs:
- subject: the harbor
predicate: is
value: too fogged in to trust casually
confidence: 0.8
source_modality: visual
projects:
- title: Decide whether to wait or leave
goal: Get a reliable sense of whether the dock is operating this morning
motivation: I would rather lose time than gamble stupidly in bad conditions
status: active
priority: 0
memories:
- type: episodic
content: "I once sat six hours at a different dock because nobody would give a straight answer about the weather."
salience: 0.5
source_modality: prior
cognition:
model: "@chat"
temperature: 0.9
- id: sora
entity: sora_body
embodiment_profile: standard_human
identity:
name: Sora
kind: human
biography: >
Sora works the small harbor boats and trusts sound on the water almost
as much as sight.
traits: [capable, laconic, watchful]
values: [good judgment, calm, not boasting]
initial_state:
believed_location: Pier
affect:
mood: watchful
valence: 0.0
arousal: 0.5
stress: 0.3
drives: [read the harbor honestly, help without making promises I cannot keep]
beliefs:
- subject: the pier
predicate: is
value: safer when the signal lantern is working
confidence: 0.9
source_modality: prior
- subject: pavel
predicate: is
value: likely to ask whether the crossing is happening
confidence: 0.6
source_modality: prior
projects:
- title: Judge the morning crossing
goal: Decide whether conditions are safe enough for movement at first light
motivation: Better a disappointed traveler than an avoidable rescue
status: active
priority: 1
memories:
- type: procedural
content: "In fog, bells and lamps matter more than confident voices."
salience: 0.6
source_modality: prior
cognition:
model: "@chat"
temperature: 0.9
Active simulation sessions
List active simulation sessions with live cycle and sim-time state.
Pass a session_id to any /v1/sessions/{id}/... endpoint. 1 active.
| session_id | scenario | state | cycle | synths | sim time | created |
|---|
| 479d31dd | data/scenarios/lighthouse_test_base.yaml | paused | 2 | 3 | 1847-10-14T19:40:00 | 2026-04-18T14:21:26.550267 |
Start a new simulation
POSThttps://singing-bird.benac.dev/v1/sessionsscope: operate
Start a new simulation from a scenario pack. State-changing: Run will prompt for confirmation before firing.
Requires:
- scenario_path from list_scenarios
Sample request body (Run sends this):
{
"scenario_path": "scenarios/park_bench.yaml"
}Inspect one session
Fetch a single session's current state (same shape as get_overview).
Requires:
- live session_id (from list_sessions)
Close and destroy a session
DELETEhttps://singing-bird.benac.dev/v1/sessions/{session_id}scope: operate
Destroy a session. State-changing; snapshot first if you may want it back.
Requires:
Snapshots for a session
List automatic cycle-boundary snapshots for a session. Pair with restore_snapshot to roll back.
Requires:
Roll back to a snapshot
POSThttps://singing-bird.benac.dev/v1/sessions/{session_id}/restorescope: operate
Roll back a session to a prior snapshot. State-changing.
Requires:
- live session_id
- snapshot_ref from list_snapshots
Sample request body (Run sends this):
{
"snapshot_ref": "{snapshot_ref}"
}