# Model Orchestrator Service — API Documentation **Version**: 1.0 **Base URL**: `http://localhost:8090` (local) — configured via `SERVICE_RUNTIME_HOST` **Content-Type**: `application/json` --- ## Authentication All endpoints under `/api/*` require a JWT Bearer token. ``` Authorization: Bearer ``` The token must contain the following claims: `TenantId`, `UserId`, `Email`, `UniqueName`, `FullName`. --- ## Response Format ### Success All successful responses are wrapped in a consistent envelope: ```json { "data": { ... } } ``` ### Error ```json { "error_message": "Human-readable description", "error_code": "machine.readable.code" } ``` ### HTTP Status Codes | Code | Meaning | |------|---------| | 200 | Success | | 400 | Bad request / validation error | | 401 | Unauthorized — missing or invalid token | | 500 | Internal server error | --- ## Endpoints Overview | Method | Path | Description | Auth | |--------|------|-------------|------| | GET | `/health/ready` | Readiness probe | No | | GET | `/health/live` | Liveness probe | No | | GET | `/api/room` | Get all rooms | Yes | | PUT | `/api/room/:room_id` | Update room name | Yes | | PATCH | `/api/room/:room_id` | Delete a room | Yes | | GET | `/api/room/:room_id/chat` | Get all chats in a room | Yes | | POST | `/api/chat` | Create a new chat | Yes | | POST | `/api/chat/:chat_id/retry` | Retry a failed chat | Yes | | GET | `/api/chat/:chat_id/status` | Get chat processing status | Yes | | POST | `/api/chat/:chat_id/feedback` | Submit feedback for a chat | Yes | | GET | `/api/chatbot/helper_prompt` | Get equipment helper prompts | Yes | --- ## Health ### GET `/health/ready` Returns `200 Ok` when the service is ready to receive traffic. No auth required. ### GET `/health/live` Returns `200 Ok` when the service process is alive. No auth required. --- ## Room Rooms are conversation containers. Each room holds a list of chat exchanges belonging to a user. --- ### GET `/api/room` Get all rooms belonging to the authenticated user. **Request**: No body, no query parameters. **Response `200`**: ```json { "data": [ { "id": "string", "name": "string" } ] } ``` | Field | Type | Description | |-------|------|-------------| | `id` | string | Unique room identifier | | `name` | string | Display name of the room | **Error responses**: | Code | `error_code` | Description | |------|-------------|-------------| | 500 | `modelorchestrator.room.get.error` | Failed to retrieve rooms | --- ### PUT `/api/room/:room_id` Rename an existing room. **Path parameter**: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `room_id` | string | Yes | ID of the room to update | **Request body**: ```json { "name": "string" } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `name` | string | Yes | New name for the room | **Response `200`**: ```json { "data": { "room_id": "string" } } ``` **Error responses**: | Code | `error_code` | Description | |------|-------------|-------------| | 400 | `modelorchestrator.room.update.errorvalidation` | Invalid or missing request body | | 500 | `modelorchestrator.room.update.error` | Failed to update room | --- ### PATCH `/api/room/:room_id` Soft-delete a room. **Path parameter**: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `room_id` | string | Yes | ID of the room to delete | **Request body**: None **Response `200`**: ```json { "data": { "room_id": "string" } } ``` **Error responses**: | Code | `error_code` | Description | |------|-------------|-------------| | 500 | `modelorchestrator.room.delete.error` | Failed to delete room | --- ### GET `/api/room/:room_id/chat` Get the full chat history for a specific room. **Path parameter**: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `room_id` | string | Yes | ID of the room | **Request body**: None **Response `200`**: ```json { "data": [ { "id": "string", "question": "any", "answer_text": "any | null", "status": "string", "feedback_status": "string | null", "feedback_reason": "string | null" } ] } ``` | Field | Type | Nullable | Description | |-------|------|----------|-------------| | `id` | string | No | Chat entry ID | | `question` | any | No | The question that was submitted (can be string or object) | | `answer_text` | any | Yes | The answer returned by the AI. `null` if still processing | | `status` | string | No | Processing status of the chat. See [Chat Status Values](#chat-status-values) | | `feedback_status` | string | Yes | Feedback given by user, if any | | `feedback_reason` | string | Yes | Reason for the feedback, if any | **Error responses**: | Code | `error_code` | Description | |------|-------------|-------------| | 500 | `modelorchestrator.room.chat.error` | Failed to retrieve room chats | --- ## Chat A chat represents a single question–answer exchange within a room. Creating a chat triggers the AI processing asynchronously — use the status endpoint to poll for completion. --- ### POST `/api/chat` Create a new chat (submit a question to the AI). If `room_id` is empty, a new room will be created automatically and its ID is returned in the response. **Request body**: ```json { "agent": "string", "req_plot_object": false, "room_id": "string", "question": "any" } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `agent` | string | Yes | Identifier of the AI agent to use | | `req_plot_object` | boolean | Yes | Set `true` if the response should include a plot/chart object | | `room_id` | string | Yes | ID of the room to post the chat in. Pass an empty string `""` to auto-create a room | | `question` | any | Yes | The question or prompt. Can be a plain string or a structured object depending on the agent | **Response `200`**: ```json { "data": { "room_id": "string", "room_name": "string", "chat_id": "string" } } ``` | Field | Type | Description | |-------|------|-------------| | `room_id` | string | The room this chat belongs to (auto-generated if not provided) | | `room_name` | string | Display name of the room | | `chat_id` | string | ID of the newly created chat. Use this to poll status and submit feedback | **Error responses**: | Code | `error_code` | Description | |------|-------------|-------------| | 400 | `modelorchestrator.chat.create.errorvalidation` | Invalid or missing request body | | 500 | `modelorchestrator.chat.create.error` | Failed to create chat | --- ### POST `/api/chat/:chat_id/retry` Retry a chat that failed or got stuck. Resubmits the original question. **Path parameter**: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `chat_id` | string | Yes | ID of the chat to retry | **Request body**: None **Response `200`**: ```json { "data": { "room_id": "string", "chat_id": "string" } } ``` **Error responses**: | Code | `error_code` | Description | |------|-------------|-------------| | 500 | `modelorchestrator.chat.retry.error` | Failed to retry chat | --- ### GET `/api/chat/:chat_id/status` Poll the processing status of a chat. Use this after creating a chat to determine when the answer is ready. **Path parameter**: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `chat_id` | string | Yes | ID of the chat | **Request body**: None **Response `200`**: ```json { "data": { "chat_id": "string", "status": "string" } } ``` **Error responses**: | Code | `error_code` | Description | |------|-------------|-------------| | 500 | `modelorchestrator.chat.getstatus.error` | Failed to retrieve chat status | #### Chat Status Values | Status | Description | |--------|-------------| | `pending` | Chat has been created, waiting to be processed | | `processing` | AI is currently generating a response | | `completed` | Response is ready — fetch via `GET /api/room/:room_id/chat` | | `failed` | Processing failed — use retry endpoint | > **Polling recommendation**: Poll every 2–3 seconds. Stop when status is `completed` or `failed`. --- ### POST `/api/chat/:chat_id/feedback` Submit user feedback (thumbs up/down and reason) for a completed chat. **Path parameter**: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `chat_id` | string | Yes | ID of the chat to give feedback on | **Request body**: ```json { "status": "string", "reason": "string" } ``` | Field | Type | Required | Description | |-------|------|----------|-------------| | `status` | string | Yes | Feedback rating (e.g. `"positive"`, `"negative"`) | | `reason` | string | Yes | Explanation for the feedback | **Response `200`**: ```json { "data": { "id": "string" } } ``` | Field | Type | Description | |-------|------|-------------| | `id` | string | ID of the created feedback record | **Error responses**: | Code | `error_code` | Description | |------|-------------|-------------| | 400 | `modelorchestrator.chat.createfeedback.errorvalidation` | Invalid or missing request body | | 500 | `modelorchestrator.chat.createfeedback.error` | Failed to submit feedback | --- ## Chatbot ### GET `/api/chatbot/helper_prompt` Get a structured list of equipment suggestions to help users construct prompts. The response is a 4-level nested map: `site_id → section → model → eqm_no → [equipment list]`. **Query parameters**: | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | `topic` | string | Yes | Topic category. Must be one of the allowed values below | | `year` | integer | Yes | The year to filter data by (e.g. `2024`) | **Allowed `topic` values**: | Value | Description | |-------|-------------| | `pa performance` | PA performance analysis | | `bad actor` | Bad actor identification | | `pareto` | Pareto analysis | | `inspection` | Inspection data | | `backlog` | Maintenance backlog | | `planning` | Planning analysis | | `execution` | Execution analysis | **Response `200`**: ```json { "data": { "": { "
": { "": { "": ["equipment_name_1", "equipment_name_2"] } } } } } ``` **Example**: ```json { "data": { "SITE_A": { "MECHANICAL": { "PUMP": { "P-001": ["P-001A", "P-001B"] } } } } } ``` **Error responses**: | Code | `error_code` | Description | |------|-------------|-------------| | 400 | `helper.prompt.validation.topic` | `topic` is missing or not one of the allowed values | | 400 | `helper.prompt.validation.year` | `year` query parameter is missing | | 400 | `helper.prompt.validation.year.format` | `year` is not a valid integer | | 500 | `helper.prompt.service.error` | Failed to retrieve helper prompt data | --- ## Typical Frontend Flow Below is the recommended sequence for a full chat interaction: ``` 1. GET /api/room → fetch existing rooms for sidebar 2. POST /api/chat → submit question (use room_id="" for new room) ← returns { room_id, room_name, chat_id } 3. GET /api/chat/:chat_id/status → poll every 2–3s until status = "completed" or "failed" 4. GET /api/room/:room_id/chat → fetch full chat history including the answer 5. POST /api/chat/:chat_id/feedback → (optional) submit user rating 6. POST /api/chat/:chat_id/retry → (if status = "failed") retry ``` --- ## Error Code Reference All error responses follow this format: ```json { "error_message": "Human-readable description", "error_code": "machine.readable.code" } ``` ### Authentication Errors These errors are returned before any endpoint logic runs, when the JWT token is missing, malformed, or invalid. | HTTP | `error_code` | `error_message` | Cause | |------|-------------|-----------------|-------| | 401 | `error.cred.missing` | Authorization creds missing | `Authorization` header not present in request | | 401 | `error.cred.incomplete` | Authorization cred incomplete | Header present but not in `Bearer ` format | | 401 | `error.cred.invalid` | Authorization cred invalid | JWT token cannot be parsed or is malformed | | 401 | `error.cred.missingAttribute` | Authorization cred attribute missing | Token is valid but missing required claims (`tenantId` or `userId`) | | 401 | `error.database.connectionfailure` | Unable to establish connection to tenant database | Service could not open a DB connection for the tenant derived from the token | ### Room Errors | HTTP | `error_code` | `error_message` | Endpoint | Cause | |------|-------------|-----------------|----------|-------| | 500 | `modelorchestrator.room.gettenant.error` | Unable to get tenant context | All room endpoints | Internal error reading tenant context from middleware | | 400 | `modelorchestrator.room.update.errorvalidation` | Unable to read input | `PUT /api/room/:room_id` | Request body is missing or not valid JSON | | 500 | `modelorchestrator.room.update.error` | Unable to update room | `PUT /api/room/:room_id` | Database error while updating the room | | 500 | `modelorchestrator.room.delete.error` | Unable to get room chats | `PATCH /api/room/:room_id` | Database error while deleting the room | | 500 | `modelorchestrator.room.get.error` | Unable to get rooms | `GET /api/room` | Database error while fetching room list | | 500 | `modelorchestrator.room.chat.error` | Unable to get room chats | `GET /api/room/:room_id/chat` | Database error while fetching chat history | ### Chat Errors | HTTP | `error_code` | `error_message` | Endpoint | Cause | |------|-------------|-----------------|----------|-------| | 500 | `modelorchestrator.chat.gettenant.error` | Unable to get tenant context | All chat endpoints | Internal error reading tenant context from middleware | | 400 | `modelorchestrator.chat.create.errorvalidation` | Unable to read input | `POST /api/chat` | Request body is missing or not valid JSON | | 500 | `modelorchestrator.chat.create.error` | Unable to create chat | `POST /api/chat` | Database error while creating the chat record | | 500 | `modelorchestrator.chat.retry.error` | Unable to retry chat | `POST /api/chat/:chat_id/retry` | Chat not found or database error during retry | | 500 | `modelorchestrator.chat.getstatus.error` | Unable to get chat status | `GET /api/chat/:chat_id/status` | Database error while fetching chat status | | 400 | `modelorchestrator.chat.createfeedback.errorvalidation` | Unable to read input | `POST /api/chat/:chat_id/feedback` | Request body is missing or not valid JSON | | 500 | `modelorchestrator.chat.createfeedback.error` | Unable to get chat status | `POST /api/chat/:chat_id/feedback` | Database error while saving feedback | ### Chatbot Errors | HTTP | `error_code` | `error_message` | Endpoint | Cause | |------|-------------|-----------------|----------|-------| | 500 | `modelorchestrator.prompt.gettenant.error` | Unable to get tenant context | `GET /api/chatbot/helper_prompt` | Internal error reading tenant context from middleware | | 400 | `helper.prompt.validation.topic` | Invalid topic provided | `GET /api/chatbot/helper_prompt` | `topic` query param is missing or not one of the 7 allowed values | | 400 | `helper.prompt.validation.year` | Year is required | `GET /api/chatbot/helper_prompt` | `year` query param is not provided | | 400 | `helper.prompt.validation.year.format` | Invalid year format | `GET /api/chatbot/helper_prompt` | `year` query param is not a valid integer | | 500 | `helper.prompt.service.error` | Failed to get helper prompt | `GET /api/chatbot/helper_prompt` | Database error while fetching helper prompt data | ### System Errors | HTTP | `error_code` | `error_message` | Cause | |------|-------------|-----------------|-------| | 500 | `error.internalservererror` | Internal Server Error | Unhandled panic in the service — logged server-side with full stack trace | --- ## CORS CORS is enabled globally. All origins are allowed and credentials are supported. ``` Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true Access-Control-Allow-Methods: POST, OPTIONS, GET, PUT, PATCH ```