{"openapi":"3.1.0","info":{"title":"World Models API","description":"WM-schema REST API in front of an external OpenAI Chat Completions deployment. POST /v1/predict with the WM Pydantic schema; the app composes the 5-section system prompt + State:/Action: user turn and dispatches to the upstream.","version":"0.1.0"},"paths":{"/health":{"get":{"summary":"Health","description":"Liveness probe — always 200 while the process is up (no upstream call).","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/ready":{"get":{"summary":"Ready","description":"Readiness probe — 200 once the adapter has been built in the lifespan.","operationId":"ready_ready_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/v1/predict":{"post":{"summary":"Predict","operationId":"predict_v1_predict_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorldModelRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/WorldModelResponse"},{"$ref":"#/components/schemas/WorldModelPrediction"}],"title":"Response Predict V1 Predict Post"}}}},"413":{"description":"Input exceeds the upstream model's context length.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Upstream rate-limited the request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream returned an unclassified non-2xx response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Upstream temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"504":{"description":"Upstream timed out.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/chat/completions":{"post":{"summary":"Chat Completions","description":"WM-aware OpenAI Chat Completions endpoint.\n\nTwo input modes, both returning the upstream's ``ChatCompletion`` verbatim:\n\n* **WM mode** — when ``context``/``interaction`` are supplied (e.g. via the\n  OpenAI client's ``extra_body``), the prompt is composed here, exactly like\n  `/v1/predict` (``build_system_prompt`` + ``build_user_message``); any\n  ``messages`` is ignored.\n* **Passthrough** — otherwise the caller's ``messages`` are forwarded as-is.\n\nSampling: the nested ``params`` object wins; otherwise the native top-level\nfields apply. Auth + rate limiting are shared with `/v1/predict`. Streaming\nis unsupported; ``stream=True`` is rejected.","operationId":"chat_completions_v1_chat_completions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatCompletionResponse"}}}},"400":{"description":"Unsupported request (e.g. streaming).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Input exceeds the upstream model's context length.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Upstream rate-limited the request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"502":{"description":"Upstream returned an unclassified non-2xx response.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Upstream temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"504":{"description":"Upstream timed out.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/me":{"get":{"tags":["dashboard"],"summary":"Me","operationId":"me_v1_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}}}}},"/v1/api-keys":{"get":{"tags":["dashboard"],"summary":"Get Api Keys","operationId":"get_api_keys_v1_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyListResponse"}}}}}},"post":{"tags":["dashboard"],"summary":"Post Api Key","operationId":"post_api_key_v1_api_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreateRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/api-keys/{key_id}":{"delete":{"tags":["dashboard"],"summary":"Delete Api Key","operationId":"delete_api_key_v1_api_keys__key_id__delete","parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Key Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"ApiKeyCreateRequest":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["name"],"title":"ApiKeyCreateRequest"},"ApiKeyCreateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"prefix":{"type":"string","title":"Prefix"},"last_four":{"type":"string","title":"Last Four"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"},"key":{"type":"string","title":"Key"}},"type":"object","required":["id","name","prefix","last_four","created_at","key"],"title":"ApiKeyCreateResponse"},"ApiKeyListResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/ApiKeyResponse"},"type":"array","title":"Data"}},"type":"object","required":["data"],"title":"ApiKeyListResponse"},"ApiKeyResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"prefix":{"type":"string","title":"Prefix"},"last_four":{"type":"string","title":"Last Four"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"}},"type":"object","required":["id","name","prefix","last_four","created_at"],"title":"ApiKeyResponse"},"AssistantMessage":{"properties":{"role":{"type":"string","const":"assistant","title":"Role","default":"assistant"},"content":{"type":"string","title":"Content"}},"type":"object","required":["content"],"title":"AssistantMessage"},"ChatCompletionRequest":{"properties":{"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"messages":{"items":{"$ref":"#/components/schemas/ChatMessage"},"type":"array","title":"Messages"},"context":{"anyOf":[{"$ref":"#/components/schemas/Context"},{"type":"null"}]},"interaction":{"anyOf":[{"$ref":"#/components/schemas/Interaction"},{"type":"null"}]},"params":{"anyOf":[{"$ref":"#/components/schemas/Params"},{"type":"null"}]},"max_tokens":{"type":"integer","exclusiveMinimum":0.0,"title":"Max Tokens","default":512},"temperature":{"type":"number","minimum":0.0,"title":"Temperature","default":0.2},"top_p":{"type":"number","maximum":1.0,"exclusiveMinimum":0.0,"title":"Top P","default":1.0},"top_k":{"type":"integer","minimum":0.0,"title":"Top K","default":0},"stream":{"type":"boolean","title":"Stream","default":false}},"additionalProperties":true,"type":"object","title":"ChatCompletionRequest","description":"A WM-aware superset of an OpenAI Chat Completions request. `extra=\"allow\"`\nlets callers pass any additional OpenAI / SGLang param straight through to the\nupstream (forwarded via the OpenAI SDK's `extra_body`).\n\nTwo input modes, resolved in the route:\n\n* **WM mode** — supply `context` and/or `interaction` (e.g. via the OpenAI\n  client's `extra_body`); the route composes the system/user prompt from them\n  and ignores `messages`. `interaction` is required in this mode.\n* **Passthrough** — supply `messages[]` directly; they are forwarded as-is.\n\nSampling: the nested `params` object wins when present; otherwise the native\n`max_tokens`/`temperature`/`top_p`/`top_k` below apply (defaults mirror\n`Params`). `model` is optional — the adapter falls back to the configured\n`served_model_name`. Streaming is unsupported (the route rejects `stream=True`\nwith 400)."},"ChatCompletionResponse":{"properties":{"id":{"type":"string","title":"Id"},"object":{"type":"string","title":"Object"},"created":{"type":"integer","title":"Created"},"model":{"type":"string","title":"Model"},"choices":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Choices"},"usage":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Usage"}},"additionalProperties":true,"type":"object","required":["id","object","created","model","choices"],"title":"ChatCompletionResponse","description":"The upstream's OpenAI `ChatCompletion` body, passed through verbatim.\n\nPermissive on purpose (`extra=\"allow\"`): unlike the WM response — which\ntrims `usage` and re-shapes into `WorldModelPrediction` — this endpoint is\nOpenAI-consistent, so it returns the full standard shape (`id` / `object` /\n`created` / `model` / `choices` / `usage` including `total_tokens`) plus any\nnon-standard SGLang extensions (e.g. `matched_stop`) untouched."},"ChatMessage":{"properties":{"role":{"type":"string","enum":["system","user","assistant"],"title":"Role"},"content":{"type":"string","title":"Content"}},"additionalProperties":true,"type":"object","required":["role","content"],"title":"ChatMessage","description":"One OpenAI chat message. The OpenAI-native analogue of `PromptMessage`,\nwidened to the three roles a caller may legitimately send."},"Context":{"properties":{"environment_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Environment State"},"task_context":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Context"},"tool_schemas":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tool Schemas"},"domain_knowledge":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain Knowledge"},"steering_directives":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Steering Directives"}},"additionalProperties":false,"type":"object","title":"Context","description":"Conditioning context the world model is grounded on — rendered into the\nsystem message by `build_system_prompt`. All sections optional; empty ones\nare skipped."},"ErrorResponse":{"properties":{"detail":{"type":"string","title":"Detail"},"upstream_status":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Upstream Status"},"upstream_body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Upstream Body"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"}},"type":"object","required":["detail"],"title":"ErrorResponse","description":"Body returned when the upstream deployment fails.\n\nDeclared on the ``/v1/predict`` route so the 4xx/5xx shapes show up in the\nOpenAPI schema rather than being undocumented surprises. ``category`` is a\nmachine-readable label for the failure mode — one of:\n\n- ``\"context_exceeded\"`` — input exceeded the model's context length (413).\n- ``\"rate_limit\"`` — upstream rate-limited us (429).\n- ``\"unavailable\"`` — upstream temporarily down (503).\n- ``\"timeout\"`` — upstream timed out (504).\n- ``\"upstream\"`` — anything else non-2xx from the upstream (502)."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthResponse":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"HealthResponse"},"Interaction":{"properties":{"state":{"type":"string","minLength":1,"title":"State"},"action":{"type":"string","minLength":1,"title":"Action"}},"additionalProperties":false,"type":"object","required":["state","action"],"title":"Interaction","description":"The state-action transition whose outcome the world model predicts —\nrendered into the user turn by `build_user_message`. Both fields are\n**required and non-empty**: a prediction needs both the conversation state\nand the action whose outcome it is predicting."},"MeResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"oidc_issuer":{"type":"string","title":"Oidc Issuer"},"oidc_subject":{"type":"string","title":"Oidc Subject"}},"type":"object","required":["id","oidc_issuer","oidc_subject"],"title":"MeResponse"},"Params":{"properties":{"max_tokens":{"type":"integer","exclusiveMinimum":0.0,"title":"Max Tokens","default":512},"temperature":{"type":"number","minimum":0.0,"title":"Temperature","default":0.2},"top_p":{"type":"number","maximum":1.0,"exclusiveMinimum":0.0,"title":"Top P","default":1.0},"top_k":{"type":"integer","minimum":0.0,"title":"Top K","default":0},"enable_thinking":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enable Thinking"},"reasoning_budget":{"anyOf":[{"type":"string","enum":["low","medium","high"]},{"type":"null"}],"title":"Reasoning Budget"}},"additionalProperties":true,"type":"object","title":"Params","description":"Sampling / decoding knobs. `extra=\"allow\"` lets callers pass any\ndeployment-specific param (e.g. `min_p`, `no_stop_trim`) straight through to\nthe upstream without a schema change; the adapter forwards every set field."},"PromptMessage":{"properties":{"role":{"type":"string","enum":["system","user"],"title":"Role"},"content":{"type":"string","title":"Content"}},"type":"object","required":["role","content"],"title":"PromptMessage"},"Usage":{"properties":{"prompt_tokens":{"type":"integer","title":"Prompt Tokens"},"completion_tokens":{"type":"integer","title":"Completion Tokens"}},"type":"object","required":["prompt_tokens","completion_tokens"],"title":"Usage"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WorldModelPrediction":{"properties":{"response":{"$ref":"#/components/schemas/AssistantMessage"},"reasoning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reasoning"},"finish_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Finish Reason"},"usage":{"$ref":"#/components/schemas/Usage"},"matched_stop":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Matched Stop"}},"type":"object","required":["response","usage"],"title":"WorldModelPrediction","description":"The **default** ``POST /v1/predict`` response (the standalone / EKS shape):\nthe generated turn, the stop reason, and token accounting.\n\n``usage`` and ``matched_stop`` are **always** returned; only the composed-\nprompt echo (``messages``) is gated behind ``include_debug_fields``, in which\ncase the route returns the full `WorldModelResponse` below. The two are\nindependent models (not a subclass relationship) — ``messages`` is the sole\ndiscriminator — so FastAPI's union ``response_model`` resolves each returned\ninstance unambiguously by type."},"WorldModelRequest":{"properties":{"context":{"anyOf":[{"$ref":"#/components/schemas/Context"},{"type":"null"}]},"interaction":{"$ref":"#/components/schemas/Interaction"},"params":{"$ref":"#/components/schemas/Params"}},"additionalProperties":false,"type":"object","required":["interaction"],"title":"WorldModelRequest"},"WorldModelResponse":{"properties":{"response":{"$ref":"#/components/schemas/AssistantMessage"},"messages":{"items":{"$ref":"#/components/schemas/PromptMessage"},"type":"array","title":"Messages"},"reasoning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reasoning"},"usage":{"$ref":"#/components/schemas/Usage"},"finish_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Finish Reason"},"matched_stop":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Matched Stop"}},"type":"object","required":["response","messages","usage"],"title":"WorldModelResponse","description":"The full ``POST /v1/predict`` response, returned when debug fields are\nenabled (the UI forces this on; a deployment opts in via config). Adds the\ncomposed-prompt echo (``messages``) on top of `WorldModelPrediction`."}}}}