CODEX // oaoisme wiki

§ unswayed-backend · API contract & docs

Lexi AI — interview coaching (Phase 14, UN-112)

updated 2026-06-17

What it is

A mock-interview loop (src/lexi-ai/interview-coaching/): the applicant starts a session for a job, answers AI-generated questions one at a time, gets per-answer feedback, and finishes with an overall score. Per-user Lexi /api/v1/*, behind the interviewCoaching feature flag.

The loop

  • POST /api/v1/users/{userId}/interview-coaching/sessions — 10/hour. Body {jobPostingId | jobDescriptionText, focusAreas?} (focus ⊆ technical/behavioral/situational/ culture_fit). The LLM generates the first question grounded in the JD + focus areas; the session is created in_progress (default maxQuestions=5) with the first InterviewCoachingResponse (ordinal 1, unanswered). Returns {sessionId, status, currentQuestion:{questionId, category, questionText}}.
  • POST .../sessions/{id}/responses — 60/hour. Body {questionId, responseText} (≥20 chars, else 422). Validates the session is owned + in_progress (completed → 422 read-only) and that questionId is the current unanswered question. The LLM evaluates the answer → feedback:{score, strengths[], improvementAreas[]} + responseScore. If more questions remain it generates the next one and returns {feedback, nextQuestion}; on the last answer it completes the session (overallScore = average of response scores, status:completed, nextQuestion:null).
  • GET .../sessions/{id} — summary with each response's score + improvementAreas (404 if not owned).
  • GET .../sessions — paginated history, newest first.

How it works

Questions and answers are rows in InterviewCoachingResponse (the row id is the questionId handed to the client); the session tracks status + the running overallScore. The slice reuses the shared AI seam (gpt-4o-mini, JSON + retry-once, LexiUnavailableError → 503) and the per-user ownership/feature primitives. It deliberately does not read the employer-side Lenux interview_questions table — only shared prompt patterns, never shared data — keeping the applicant and recruiter sides isolated.