{"openapi":"3.1.0","info":{"title":"Singing Bird","description":"Control plane for the Singing Bird embodied simulation kernel","version":"0.3.0"},"paths":{"/v1/sessions":{"get":{"summary":"List active simulation sessions","description":"List all active simulation sessions.\n\nReturns session_id, scenario_path, created_at, and paused state for each.\nUse before create_session to see what is already running, or to pick a\nsession_id for other tools.","operationId":"list_sessions_v1_sessions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"post":{"summary":"Start a new simulation","description":"Start a new simulation from a scenario pack.\n\nIdentify the scenario via `scenario_ref` (preferred) or `scenario_path`\n(legacy alias). Both accept id, filename stem, or a path — all normalize.\nCall list_scenarios to discover available ids. Sessions start paused;\nadvance via step_session, or resume_session for auto-advance.","operationId":"create_session_v1_sessions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}":{"get":{"summary":"Inspect one session","description":"Get a single session's current state — same shape as get_overview.\n\nExists for REST-idiomatic lookup-by-id; prefer get_overview when you\nare calling by session_id anyway, or list_sessions for discovery.","operationId":"get_session_v1_sessions__session_id__get","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"summary":"Close and destroy a session","description":"Close a session and release its resources.\n\nDestroys the session's in-memory state. If you may want to go back,\ntake or reference a snapshot first (list_snapshots + restore_snapshot).","operationId":"close_session_v1_sessions__session_id__delete","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/scenarios/{scenario_id}":{"get":{"summary":"Inspect a scenario pack in detail","description":"Inspect a scenario pack in detail.\n\nscenario_id accepts id, filename stem, or a scenario_path — all\nnormalize to the same scenario.\n\nview modes (use view='authoring' when you plan to edit and write back):\n  - full (default): headline metadata + section summary + parsed YAML + raw text\n  - summary:   headline metadata + section summary only (compact)\n  - authoring: {scenario_id, path, content} where `content` is the exact\n               shape update_scenario accepts as its body\n  - raw:       {scenario_id, path, raw} — raw YAML text\n\nformat=raw returns the YAML as text/yaml (overrides view).","operationId":"get_scenario","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":false,"schema":{"type":"string","title":"View","default":"full"},"name":"view","in":"query"},{"required":false,"schema":{"type":"string","title":"Format","default":"json"},"name":"format","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"put":{"summary":"Replace a scenario's full contents","description":"Full replace. The body `content` must match the authoring shape from\nget_scenario(view='authoring') — i.e. the raw YAML dict with\nworld.topology.locations, world.entities, synths, profiles, etc. (NOT\nthe flat content-summary view from get_scenario(view='summary')).\n\nIf the target is a shipped baseline, the write lands in data/scenarios/\nand shadows the original (fork-on-write). Pass dry_run=true to preview.","operationId":"update_scenario","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateScenarioRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"summary":"Delete a user-authored scenario","description":"Removes a user-authored scenario. Shipped scenarios cannot be deleted —\nfork them first if you want a deletable copy. Accepts scenario_id (id,\nfilename stem, or scenario_path — all normalize to the same scenario).","operationId":"delete_scenario","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/scenarios":{"get":{"summary":"List available scenario packs","description":"List scenario packs available on disk.\n\nMetadata-only — no world is loaded. Use before create_session to\ndiscover what simulations can be started; pass a returned path\nas the scenario_path argument to create_session.","operationId":"list_scenarios_v1_scenarios_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"post":{"summary":"Create a new scenario pack","description":"Author a new scenario. If content is omitted a minimal valid scaffold\n(one location, no entities, no synths) is written so you can fill it in\npiece by piece with the component-level add_* tools.\n\nPass dry_run=true to preview the effect without writing the file.","operationId":"create_scenario","parameters":[{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateScenarioRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/scenarios/{scenario_id}/fork":{"post":{"summary":"Duplicate a scenario under a new id","description":"Duplicate the source scenario under new_scenario_id. Optional overrides\nare merged at the top level (e.g. {\"random_seed\": 123}). scenario_id\naccepts id, filename stem, or a scenario_path — all normalize to the\nsame scenario. Pass dry_run=true to preview the fork without writing.","operationId":"fork_scenario","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForkScenarioRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/scenarios/{scenario_id}/locations":{"post":{"summary":"Add a location to a scenario","operationId":"add_location","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationModel"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/scenarios/{scenario_id}/locations/{loc_id}":{"put":{"summary":"Replace a location (destructive; drops unsent fields)","description":"Full replace. Every unsent field on the prior location is dropped.\nIf you only want to change a few fields, use patch_location.","operationId":"replace_location","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Loc Id"},"name":"loc_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationModel"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"summary":"Remove a location (and its adjacency edges)","operationId":"remove_location","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Loc Id"},"name":"loc_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"summary":"Patch a location (merge; unsent fields are preserved)","description":"Deep-merge partial update. Fields you don't send are preserved.\nSend `{\"key\": null}` to delete a key. Returns the full location after\nthe merge, so you can see both the changed and unchanged fields.\n\nBody must be `{\"patch\": {...}}` — the patch dict is the value of the\nrequired `patch` field. Example: `{\"patch\": {\"description\": \"updated\"}}`.","operationId":"patch_location","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Loc Id"},"name":"loc_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/scenarios/{scenario_id}/entities":{"post":{"summary":"Add an entity to a scenario (ruleset-validated)","operationId":"add_entity","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityModel"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/scenarios/{scenario_id}/entities/{entity_id}":{"put":{"summary":"Replace an entity (destructive; drops unsent fields)","description":"Full replace. Every unsent field on the prior entity is dropped.\nComponents are revalidated against the ruleset. Use patch_entity for\npartial updates.","operationId":"replace_entity","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Entity Id"},"name":"entity_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityModel"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"summary":"Remove an entity from a scenario","operationId":"remove_entity","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Entity Id"},"name":"entity_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"summary":"Patch an entity (merge; unsent fields are preserved)","description":"Deep-merge partial update. Fields you don't send are preserved.\nIf you include 'components', the whole list is replaced (list merging is\nambiguous). Returns the full entity after the merge.\n\nBody must be `{\"patch\": {...}}`. Example: `{\"patch\": {\"name\": \"Stone Bench\"}}`.","operationId":"patch_entity","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Entity Id"},"name":"entity_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/scenarios/{scenario_id}/synths":{"post":{"summary":"Add a synth to a scenario","description":"Add a synth. Required fields (id, entity, identity) are validated at\nthe edge; the full synth shape — identity, cognition, initial_state\n(affect, beliefs, projects, memories, mental_models) — is published in\nthe OpenAPI schema so clients know what to send.","operationId":"add_synth","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SynthModel"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/scenarios/{scenario_id}/synths/{synth_id}":{"put":{"summary":"Replace a synth (destructive; drops unsent fields)","description":"Full replace. Every unsent field on the prior synth is dropped. This is\nintentionally risky — use patch_synth when you only want to change a few\nfields (e.g. initial_state.beliefs).","operationId":"replace_synth","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Synth Id"},"name":"synth_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SynthModel"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"summary":"Remove a synth from a scenario","operationId":"remove_synth","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Synth Id"},"name":"synth_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"summary":"Patch a synth (merge; unsent fields are preserved)","description":"Deep-merge partial update of one synth.\n\nBody must be `{\"patch\": {...}}` — wrap your merge under the `patch` key.\nExample to clear James's prior knowledge of the shore without losing\nhis identity, embodiment, or mood:\n\n  PATCH /v1/scenarios/lighthouse/synths/james\n  {\"patch\": {\"initial_state\": {\"beliefs\": []}}}\n\nReturns the full synth after the merge so you can see both the fields\nyou changed and the ones you didn't touch.\n\nPass dry_run=true to preview the merged synth without writing.","operationId":"patch_synth","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Synth Id"},"name":"synth_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchBody"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/scenarios/{scenario_id}/adjacency":{"post":{"summary":"Add an adjacency edge between two locations","operationId":"add_adjacency","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdjacencyModel"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"summary":"Remove an adjacency edge (by from+to)","operationId":"remove_adjacency","parameters":[{"required":true,"schema":{"type":"string","title":"Scenario Id"},"name":"scenario_id","in":"path"},{"required":true,"schema":{"type":"string","title":"From Location"},"name":"from_location","in":"query"},{"required":true,"schema":{"type":"string","title":"To Location"},"name":"to_location","in":"query"},{"required":false,"schema":{"type":"boolean","title":"Dry Run","default":false},"name":"dry_run","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/snapshots":{"get":{"summary":"List a session's snapshots","description":"List snapshots taken for a session.\n\nSnapshots are automatic checkpoints taken at cycle boundaries. Pair\nwith restore_snapshot to undo recent changes or roll back after a bad\npatch or an unintended step.","operationId":"list_snapshots_v1_sessions__session_id__snapshots_get","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/snapshots/diff":{"get":{"summary":"Diff two arbitrary snapshots","description":"Event-level diff between two persisted snapshots (RFC-0001).\n\nGeneralizes get_changes to arbitrary snapshot pairs: returns changed_refs,\nevent counts by type, event details, and compact summaries for everything\nthat happened from from_snapshot (exclusive) to to_snapshot (inclusive).\nRead-only; the live session is untouched.","operationId":"diff_snapshots","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"},{"required":true,"schema":{"type":"string","title":"From Snapshot"},"name":"from_snapshot","in":"query"},{"required":true,"schema":{"type":"string","title":"To Snapshot"},"name":"to_snapshot","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/snapshots/{snapshot_ref}/overview":{"get":{"summary":"Historical session overview at a snapshot","description":"RFC-0001 tool #1: full world overview materialized from a past snapshot.\n\nSame shape as get_overview, but read from a persisted snapshot. The live\nsession is not modified — this is how you scrub through cycles without\nthe destructive side effect of restore_snapshot.","operationId":"get_snapshot_overview","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Snapshot Ref"},"name":"snapshot_ref","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/snapshots/{snapshot_ref}/objects/{kind}/{ref}":{"get":{"summary":"Historical object detail at a snapshot","description":"RFC-0001 tool #2: object detail as of a persisted snapshot.\n\nSame shape as get_object. Returns 404 if the object did not exist yet at\nthat snapshot (e.g. an entity created at a later cycle). Read-only.","operationId":"get_snapshot_object","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Snapshot Ref"},"name":"snapshot_ref","in":"path"},{"required":true,"schema":{"type":"string","title":"Kind"},"name":"kind","in":"path"},{"required":true,"schema":{"type":"string","title":"Ref"},"name":"ref","in":"path"},{"required":false,"schema":{"type":"string","title":"View","default":"both"},"name":"view","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/restore":{"post":{"summary":"Roll back to a snapshot","description":"Rewind a session to a previous snapshot — the undo button.\n\nReplaces the current session state with the snapshot; anything after\nthat point is discarded unless it was itself snapshotted. Get\nsnapshot_ref from list_snapshots. Safe to retry with idempotency_key.","operationId":"restore_snapshot_v1_sessions__session_id__restore_post","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RestoreRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/step":{"post":{"summary":"Advance N cognitive cycles","description":"Advance the simulation by n cycles (default 1).\n\nEach cycle runs perception → cognition → intent resolution → commit:\nsynths observe their surroundings, decide, and act. Any stimuli queued\nvia queue_stimulus are drained into this step. After stepping, call\nget_last_cycle_report for a narrative of what happened, or get_changes\nfor a structured diff.","operationId":"step_session_v1_sessions__session_id__step_post","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/StepRequest"}],"title":"Req","default":{"n":1}}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/pause":{"post":{"summary":"Pause auto-advance","description":"Pause a session's auto-advance.\n\nStops any timed cycle loop; manual step_session calls still work.\nPair with resume_session to restart the loop.","operationId":"pause_session_v1_sessions__session_id__pause_post","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/resume":{"post":{"summary":"Resume auto-advance","description":"Resume a session's auto-advance after pause_session.\n\nCycles run on the configured cadence. No-op if the session is already\nrunning.","operationId":"resume_session_v1_sessions__session_id__resume_post","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/turns":{"post":{"summary":"Inject an external turn","description":"Inject an external event through the director and run a cycle.\n\nUse for in-world events: a spoken announcement, a narrated action, a\nscripted intervention from the operator. The event flows through the\ndirector and triggers a full cycle. Compare queue_stimulus, which\nenqueues a sensory stimulus without triggering a cycle. origin_type\nis usually 'human'; payload is free-form but typically includes a\n'message' field.","operationId":"submit_turn_v1_sessions__session_id__turns_post","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TurnRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/overview":{"get":{"summary":"Full session overview","description":"Compact snapshot of the current session state.\n\nReturns synths (with brief status), environment, time, and locations —\nthe go-to call for a status update. Cheaper than inspecting individual\nobjects; use get_object for deep detail on a specific synth/entity/location.","operationId":"get_overview_v1_sessions__session_id__overview_get","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/resolve":{"get":{"summary":"Resolve a name to a ref","description":"Resolve a human-readable name to its stable UUID ref.\n\nPass q (the name) and optionally kind (synth, entity, or location) to\nnarrow the search. Use before any tool that takes a ref argument —\nnotably get_object and the ref-bearing ops in apply_patch. Returns a\nmatches array; ambiguous names return multiple hits.","operationId":"resolve_ref_v1_sessions__session_id__resolve_get","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Q"},"name":"q","in":"query"},{"required":false,"schema":{"type":"string","title":"Kind"},"name":"kind","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/objects/{kind}/{ref}":{"get":{"summary":"Fetch a typed object by ref","description":"Detailed view of a specific synth, entity, or location by ref.\n\nkind must be one of: synth, entity, location.\n- synth: beliefs, mood, memories, available actions.\n- entity: components, location, mobility.\n- location: contents, exits.\nUse resolve_ref first if you only know the name. view defaults to 'both'\n(internal + external) — the other options are 'internal' or 'external'.","operationId":"get_object_v1_sessions__session_id__objects__kind___ref__get","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"},{"required":true,"schema":{"type":"string","title":"Kind"},"name":"kind","in":"path"},{"required":true,"schema":{"type":"string","title":"Ref"},"name":"ref","in":"path"},{"required":false,"schema":{"type":"string","title":"View","default":"both"},"name":"view","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/events":{"get":{"summary":"Paginate raw audit events","description":"Raw audit events from the session since a sequence number.\n\nFull fidelity — every perception, thought, action, and world change.\nBest for detailed history or debugging. For a narrative summary, use\nget_last_cycle_report (single cycle) or get_report_since (multi-cycle).\nPagination: pass since=<last seq seen>, limit=N.","operationId":"get_events_v1_sessions__session_id__events_get","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"},{"required":false,"schema":{"type":"integer","title":"Since","default":0},"name":"since","in":"query"},{"required":false,"schema":{"type":"integer","title":"Limit","default":50},"name":"limit","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/changes":{"get":{"summary":"Structured change set since a cursor","description":"Structured diff of world state: what refs changed and by how much.\n\nAggregated event counts, short summaries, and the set of changed refs —\nsince a given sequence cursor or against a snapshot (snapshot_ref).\nNarrower than get_events (no per-event detail), broader than\nget_overview (historical, not just current).","operationId":"get_changes_v1_sessions__session_id__changes_get","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"},{"required":false,"schema":{"type":"integer","title":"Since","default":0},"name":"since","in":"query"},{"required":false,"schema":{"type":"string","title":"Snapshot Ref"},"name":"snapshot_ref","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/reports/last-cycle":{"get":{"summary":"Narrative report of the last cycle","description":"Narrative report of the most recent cycle.\n\nWorld events, synth speech and actions, belief changes, mood shifts —\nhuman-readable. Call after step_session to see what just happened.\nFor multiple cycles at once, use get_report_since.","operationId":"get_last_cycle_report_v1_sessions__session_id__reports_last_cycle_get","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/reports/since":{"get":{"summary":"Narrative report since a cursor","description":"Narrative report spanning every cycle since a sequence cursor.\n\nLike get_last_cycle_report but multi-cycle — use to catch up after\nseveral steps without walking raw events. Returns summaries, event\ncounts, and changed refs since the cursor.","operationId":"get_report_since_v1_sessions__session_id__reports_since_get","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"},{"required":false,"schema":{"type":"integer","title":"Since","default":0},"name":"since","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/stream":{"get":{"summary":"Live SSE event stream","description":"SSE event stream. Connect and receive events as they happen.","operationId":"stream_events_v1_sessions__session_id__stream_get","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"},{"required":false,"schema":{"type":"integer","title":"Since","default":0},"name":"since","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/patches":{"post":{"summary":"Apply world mutations","description":"Apply typed operations to mutate world state directly.\n\nBypasses the perception path — synths do NOT necessarily perceive\nthese changes. For things synths should sense (sounds, sights, smells),\nprefer queue_stimulus instead.\n\noperations is an array of op objects. Supported ops:\n  - move_entity: {op, entity_ref, destination_ref}\n  - create_entity: {op, name, description, location_ref, components}\n  - remove_entity: {op, entity_ref}\n  - set_component_property: {op, entity_ref, component_type, property, value}\n  - set_environment_field: {op, field_path, value}\n  - add_belief: {op, synth_ref, subject, predicate, content, confidence, ...}\n  - add_memory: {op, synth_ref, content, memory_type, salience, ...}\n  - set_mood: {op, synth_ref, mood, valence, arousal, stress}\n\nmode: 'dry_run' (validate only, no change), 'commit' (apply), or\n'commit_and_step' (apply then run one cycle). Safe to retry with\nidempotency_key.","operationId":"apply_patch_v1_sessions__session_id__patches_post","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PatchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/sessions/{session_id}/stimuli":{"post":{"summary":"Queue an external sensory stimulus","description":"Queue an external stimulus for delivery through the perception path.\n\nStimuli are mediated: they enter through compose_sensory_bundle on the\nnext step or turn, so synths perceive them naturally — a sound heard,\na smell noticed, a visual cue. Contrast apply_patch (mutates state\ndirectly, bypasses perception) and submit_turn (routes through the\ndirector and triggers a cycle).\n\nchannel: auditory, visual, olfactory, tactile, proprioceptive.\ntarget_synth_refs: empty list means broadcast to all synths in scope.\ndelivery: 'next_cycle' (default — queues, fires on next step) or\n'immediate_with_step' (queues + runs one step right now).","operationId":"queue_stimulus_v1_sessions__session_id__stimuli_post","parameters":[{"required":true,"schema":{"type":"string","title":"Session Id"},"name":"session_id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StimulusRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/health/llm":{"get":{"summary":"LLM backend health check","description":"Probe the LLM backend the synths would actually call.\n\nPer ADR-0001, silent cognition failure is an operational hazard. This\nendpoint surfaces reachability + TLS + auth state before anyone tries\nto step a session. Never raises; failures are reported in the payload.","operationId":"check_llm_health","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/tooling/manifest":{"get":{"summary":"API tool manifest","description":"Tool manifest generated from the OpenAPI schema (the source of truth).\n\nLists every tool with name, method, path, scope, and description. The\nsame tool set is available over MCP at POST /mcp — MCP clients should\nprefer tools/list there instead of calling this endpoint.","operationId":"get_tool_manifest_v1_tooling_manifest_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/v1/admin/logs":{"get":{"summary":"API request/response audit log","description":"Search the API request/response audit log.\n\nEvery HTTP request (REST, MCP, dashboard) produces one JSONL record at\ndata/audit/api_calls.jsonl. MCP JSON-RPC messages produce a second record\nwith type=\"mcp_call\". Each record carries a request_id that is also\nreturned in the X-Request-Id response header for correlation.\n\nFilters are AND-combined. For pagination, use limit+offset with order=desc\nto walk from newest to oldest; total_matched lets you know when to stop.\nDefault order is newest-first (desc) which is what you usually want when\ndebugging.\n\nCommon recipes:\n  - Find a specific request:            ?request_id=df143dc0...\n  - Find failures on a path:            ?path=/v1/sessions&min_status=400\n  - Find slow requests:                 ?min_duration_ms=500\n  - Find all MCP tool calls:            ?type=mcp_call\n  - Find a specific MCP tool's calls:   ?type=mcp_call&tool_name=list_scenarios\n  - Errors of any kind:                 ?has_error=true","operationId":"get_api_call_log","parameters":[{"required":false,"schema":{"type":"integer","title":"Limit","default":100},"name":"limit","in":"query"},{"required":false,"schema":{"type":"integer","title":"Offset","default":0},"name":"offset","in":"query"},{"required":false,"schema":{"type":"string","title":"Since Ts"},"name":"since_ts","in":"query"},{"required":false,"schema":{"type":"string","title":"Before Ts"},"name":"before_ts","in":"query"},{"required":false,"schema":{"type":"string","title":"Request Id"},"name":"request_id","in":"query"},{"required":false,"schema":{"type":"string","title":"Path"},"name":"path","in":"query"},{"required":false,"schema":{"type":"string","title":"Method"},"name":"method","in":"query"},{"required":false,"schema":{"type":"integer","title":"Status"},"name":"status","in":"query"},{"required":false,"schema":{"type":"integer","title":"Min Status"},"name":"min_status","in":"query"},{"required":false,"schema":{"type":"integer","title":"Max Status"},"name":"max_status","in":"query"},{"required":false,"schema":{"type":"string","title":"Operation Id"},"name":"operation_id","in":"query"},{"required":false,"schema":{"type":"string","title":"Tool Name"},"name":"tool_name","in":"query"},{"required":false,"schema":{"type":"string","title":"Type"},"name":"type","in":"query"},{"required":false,"schema":{"type":"number","title":"Min Duration Ms"},"name":"min_duration_ms","in":"query"},{"required":false,"schema":{"type":"boolean","title":"Has Error"},"name":"has_error","in":"query"},{"required":false,"schema":{"type":"string","title":"Order","default":"desc"},"name":"order","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/dashboard":{"get":{"summary":"Dashboard Html","description":"Operator dashboard: one tile per tool, showing available options.","operationId":"dashboard_html_dashboard_get","responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}}}}},"/dashboard/data":{"get":{"summary":"Dashboard Data","description":"JSON form of the dashboard — same tiles, machine-readable.","operationId":"dashboard_data_dashboard_data_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/dashboard/execute":{"get":{"summary":"Dashboard Execute","description":"Render a page that fires the given API request from the browser and displays the response.","operationId":"dashboard_execute_dashboard_execute_get","parameters":[{"required":false,"schema":{"type":"string","title":"Method","default":"GET"},"name":"method","in":"query"},{"required":false,"schema":{"type":"string","title":"Path","default":"/"},"name":"path","in":"query"},{"required":false,"schema":{"type":"string","title":"Body","default":""},"name":"body","in":"query"},{"required":false,"schema":{"type":"string","title":"Label","default":""},"name":"label","in":"query"}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AdjacencyModel":{"properties":{"from":{"type":"string","title":"From"},"to":{"type":"string","title":"To"},"kind":{"type":"string","title":"Kind","default":"path"},"bidirectional":{"type":"boolean","title":"Bidirectional","default":true},"constraints":{"type":"object","title":"Constraints"}},"type":"object","required":["from","to"],"title":"AdjacencyModel"},"AffectModel":{"properties":{"mood":{"type":"string","title":"Mood","default":"neutral"},"valence":{"type":"number","title":"Valence","default":0.0},"arousal":{"type":"number","title":"Arousal","default":0.3},"stress":{"type":"number","title":"Stress","default":0.2},"drives":{"items":{"type":"string"},"type":"array","title":"Drives"}},"type":"object","title":"AffectModel","description":"Leaf model — accepts extra keys so forward-compatible fields survive."},"BeliefModel":{"properties":{"subject":{"type":"string","title":"Subject"},"predicate":{"type":"string","title":"Predicate"},"value":{"type":"string","title":"Value"},"confidence":{"type":"number","title":"Confidence","default":0.8},"source_modality":{"type":"string","title":"Source Modality","default":"prior"}},"type":"object","required":["subject","predicate","value"],"title":"BeliefModel","description":"Leaf model — accepts extra keys so forward-compatible fields survive."},"CognitionModel":{"properties":{"model":{"type":"string","title":"Model","description":"Model alias or concrete model id.","default":"@chat"},"temperature":{"type":"number","title":"Temperature","default":0.7},"max_intents":{"type":"integer","title":"Max Intents","default":3}},"type":"object","title":"CognitionModel","description":"Leaf model — accepts extra keys so forward-compatible fields survive."},"ComponentModel":{"properties":{"type":{"type":"string","title":"Type","description":"Component type. Must be valid in the ruleset."}},"type":"object","required":["type"],"title":"ComponentModel","description":"Leaf model — accepts extra keys so forward-compatible fields survive."},"CreateScenarioRequest":{"properties":{"scenario_id":{"type":"string","title":"Scenario Id"},"content":{"type":"object","title":"Content"}},"type":"object","required":["scenario_id"],"title":"CreateScenarioRequest"},"CreateSessionRequest":{"properties":{"scenario_path":{"type":"string","title":"Scenario Path"},"scenario_ref":{"type":"string","title":"Scenario Ref"}},"type":"object","title":"CreateSessionRequest","description":"Pass either `scenario_ref` (preferred) or `scenario_path` (historical alias). Accepts id, filename stem, or a path — all normalize to the same scenario."},"EntityModel":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"location":{"type":"string","title":"Location","description":"Location id where the entity starts."},"mobility":{"type":"string","title":"Mobility","description":"movable | fixed | carried","default":"movable"},"description":{"type":"string","title":"Description","default":""},"visible":{"type":"boolean","title":"Visible","default":true},"components":{"items":{"$ref":"#/components/schemas/ComponentModel"},"type":"array","title":"Components"}},"type":"object","required":["id","name","location"],"title":"EntityModel"},"ForkScenarioRequest":{"properties":{"new_scenario_id":{"type":"string","title":"New Scenario Id"},"overrides":{"type":"object","title":"Overrides"}},"type":"object","required":["new_scenario_id"],"title":"ForkScenarioRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"IdentityModel":{"properties":{"name":{"type":"string","title":"Name"},"kind":{"type":"string","title":"Kind","default":"human"},"biography":{"type":"string","title":"Biography"},"traits":{"items":{"type":"string"},"type":"array","title":"Traits"},"values":{"items":{"type":"string"},"type":"array","title":"Values"}},"type":"object","required":["name"],"title":"IdentityModel","description":"Leaf model — accepts extra keys so forward-compatible fields survive."},"InitialStateModel":{"properties":{"believed_location":{"type":"string","title":"Believed Location"},"believed_condition":{"type":"object","title":"Believed Condition"},"affect":{"$ref":"#/components/schemas/AffectModel"},"beliefs":{"items":{"$ref":"#/components/schemas/BeliefModel"},"type":"array","title":"Beliefs"},"mental_models":{"items":{"$ref":"#/components/schemas/MentalModelModel"},"type":"array","title":"Mental Models"},"projects":{"items":{"$ref":"#/components/schemas/ProjectModel"},"type":"array","title":"Projects"},"memories":{"items":{"$ref":"#/components/schemas/MemoryModel"},"type":"array","title":"Memories"}},"type":"object","title":"InitialStateModel","description":"Leaf model — accepts extra keys so forward-compatible fields survive."},"LocationModel":{"properties":{"id":{"type":"string","title":"Id","description":"Stable ref, referenced by entities and adjacency edges."},"name":{"type":"string","title":"Name","description":"Human-readable label."},"kind":{"type":"string","title":"Kind","description":"LocationKind: room, exterior, vehicle, container, ...","default":"room"},"description":{"type":"string","title":"Description","description":"Short narrative description.","default":""},"parent":{"type":"string","title":"Parent","description":"Parent location id, for nested spaces."}},"type":"object","required":["id","name"],"title":"LocationModel"},"MemoryModel":{"properties":{"type":{"type":"string","title":"Type","description":"working | episodic | semantic | procedural","default":"semantic"},"content":{"type":"string","title":"Content"},"salience":{"type":"number","title":"Salience","default":0.5},"source_modality":{"type":"string","title":"Source Modality","default":"prior"},"emotional_tone":{"type":"string","title":"Emotional Tone"}},"type":"object","required":["content"],"title":"MemoryModel","description":"Leaf model — accepts extra keys so forward-compatible fields survive."},"MentalModelModel":{"properties":{"name":{"type":"string","title":"Name"},"believed_location":{"type":"string","title":"Believed Location"},"believed_mood":{"type":"string","title":"Believed Mood"},"believed_goals":{"items":{"type":"string"},"type":"array","title":"Believed Goals"},"believed_knowledge":{"items":{"type":"string"},"type":"array","title":"Believed Knowledge"},"believed_beliefs_about_me":{"type":"string","title":"Believed Beliefs About Me"},"confidence":{"type":"number","title":"Confidence","default":0.5}},"type":"object","required":["name"],"title":"MentalModelModel","description":"Leaf model — accepts extra keys so forward-compatible fields survive."},"PatchBody":{"properties":{"patch":{"type":"object","title":"Patch","description":"RFC 7396 JSON Merge Patch. Keys present in the patch overlay the existing object; null deletes a key; lists replace. Unsent fields are preserved."}},"type":"object","required":["patch"],"title":"PatchBody","description":"Wrapper so OpenAPI / MCP schemas publish a named 'patch' field.\n\nWithout this, `patch: Dict[str, Any]` emits an anonymous body and MCP\nclients can't see that `patch` is required — they send just scope\narguments and get a cryptic 422."},"PatchOperation":{"properties":{"op":{"type":"string","title":"Op"},"entity_ref":{"type":"string","title":"Entity Ref"},"destination_ref":{"type":"string","title":"Destination Ref"},"location_ref":{"type":"string","title":"Location Ref"},"synth_ref":{"type":"string","title":"Synth Ref"},"name":{"type":"string","title":"Name"},"description":{"type":"string","title":"Description"},"mobility":{"type":"string","title":"Mobility"},"components":{"items":{"type":"object"},"type":"array","title":"Components"},"component_type":{"type":"string","title":"Component Type"},"property":{"type":"string","title":"Property"},"value":{"title":"Value"},"field_path":{"type":"string","title":"Field Path"},"subject":{"type":"string","title":"Subject"},"predicate":{"type":"string","title":"Predicate"},"content":{"type":"string","title":"Content"},"confidence":{"type":"number","title":"Confidence"},"source_modality":{"type":"string","title":"Source Modality"},"source_agent":{"type":"string","title":"Source Agent"},"memory_type":{"type":"string","title":"Memory Type"},"salience":{"type":"number","title":"Salience"},"mood":{"type":"string","title":"Mood"},"valence":{"type":"number","title":"Valence"},"arousal":{"type":"number","title":"Arousal"},"stress":{"type":"number","title":"Stress"}},"type":"object","required":["op"],"title":"PatchOperation"},"PatchRequest":{"properties":{"operations":{"items":{"$ref":"#/components/schemas/PatchOperation"},"type":"array","title":"Operations"},"mode":{"type":"string","title":"Mode","default":"commit"},"idempotency_key":{"type":"string","title":"Idempotency Key"}},"type":"object","required":["operations"],"title":"PatchRequest"},"ProjectModel":{"properties":{"title":{"type":"string","title":"Title"},"goal":{"type":"string","title":"Goal"},"motivation":{"type":"string","title":"Motivation"},"status":{"type":"string","title":"Status","default":"active"},"priority":{"type":"integer","title":"Priority","default":0},"next_step":{"type":"string","title":"Next Step"}},"type":"object","required":["title","goal"],"title":"ProjectModel","description":"Leaf model — accepts extra keys so forward-compatible fields survive."},"RestoreRequest":{"properties":{"snapshot_ref":{"type":"string","title":"Snapshot Ref"},"idempotency_key":{"type":"string","title":"Idempotency Key"}},"type":"object","required":["snapshot_ref"],"title":"RestoreRequest"},"StepRequest":{"properties":{"n":{"type":"integer","title":"N","default":1},"idempotency_key":{"type":"string","title":"Idempotency Key"}},"type":"object","title":"StepRequest"},"StimulusRequest":{"properties":{"target_synth_refs":{"items":{"type":"string"},"type":"array","title":"Target Synth Refs","default":[]},"channel":{"type":"string","title":"Channel","default":"auditory"},"content":{"type":"string","title":"Content"},"source":{"type":"string","title":"Source","default":"external"},"source_agent":{"type":"string","title":"Source Agent","default":"director"},"salience":{"type":"number","title":"Salience","default":0.8},"delivery":{"type":"string","title":"Delivery","default":"next_cycle"},"idempotency_key":{"type":"string","title":"Idempotency Key"}},"type":"object","required":["content"],"title":"StimulusRequest"},"SynthModel":{"properties":{"id":{"type":"string","title":"Id"},"entity":{"type":"string","title":"Entity","description":"Entity id this synth is embodied in."},"embodiment_profile":{"type":"string","title":"Embodiment Profile","description":"Key into profiles.embodiment_profiles. Required unless 'embodiment' is provided inline."},"embodiment":{"type":"object","title":"Embodiment","description":"Inline embodiment override. Merged with profile if both given."},"identity":{"$ref":"#/components/schemas/IdentityModel"},"cognition":{"$ref":"#/components/schemas/CognitionModel"},"initial_state":{"$ref":"#/components/schemas/InitialStateModel"}},"type":"object","required":["id","entity","identity"],"title":"SynthModel"},"TurnRequest":{"properties":{"origin_type":{"type":"string","title":"Origin Type","default":"human"},"origin_ref":{"type":"string","title":"Origin Ref"},"payload":{"type":"object","title":"Payload","default":{}},"idempotency_key":{"type":"string","title":"Idempotency Key"}},"type":"object","title":"TurnRequest"},"UpdateScenarioRequest":{"properties":{"content":{"type":"object","title":"Content"}},"type":"object","required":["content"],"title":"UpdateScenarioRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}}}