Onboarding Voice Call

The Onboarding Voice Call feature gives every new user a one-on-one voice call with an AI character when they first join the simulation. It reuses the existing Quick Help voice infrastructure and is fully configurable by org admins.

How It Works

  1. On first login, the backend sets the user’s onboarding state to offered.
  2. The root layout runs a client OnboardingWorkspaceGate so deep links into /chat, /dashboard, /guide, etc. redirect to /onboarding-call when org policy requires it or when first_login trigger applies (same rules as workspace loading).
  3. The dashboard can still show an OnboardingCallCard when the user is already in the workspace.
  4. The user clicks Start Call; the frontend mints a LiveKit token via /api/v1/onboarding-call/start.
  5. An AI agent (configured by the org admin) greets the user with a dynamic, personalised system prompt.
  6. When the call ends the frontend calls /api/v1/onboarding-call/complete.

Onboarding State Machine

StatusMeaning
not_startedDefault; user has never been offered the call
offeredCall has been surfaced to the user (set on first login)
in_progressA LiveKit session is active
completedUser finished the call
skippedUser dismissed it (only possible when allow_skip = true)
failedSession errored before completion
State transitions are one-way and stored in the user_onboarding_states MongoDB collection.

API Endpoints

All endpoints are under the /api/v1/onboarding-call prefix and require a valid JWT.

GET /api/v1/onboarding-call/status

Returns the current user’s onboarding state. Response
{
  "enabled": true,
  "quick_help_call_enabled": true,
  "trigger": "first_login",
  "required": false,
  "allow_skip": true,
  "character_id": null,
  "character_display_name": "Patty Williams",
  "character_display_role": "HR Specialist",
  "status": "offered",
  "first_offered_at": "2026-05-01T10:00:00Z",
  "started_at": null,
  "completed_at": null,
  "skipped_at": null,
  "last_call_session_id": null
}
character_display_name / character_display_role are resolved using the same auto-detect rules as the voice worker (configured character_id when set, otherwise onboarding → HR → manager fallback).

POST /api/v1/onboarding-call/start

Starts the onboarding call. Returns a LiveKit connection token and room name. Response
{
  "token": "<livekit-jwt>",
  "room_name": "onboarding-<user_id>",
  "character_id": "patty",
  "character_name": "Patty",
  "status": "in_progress"
}
The returned token grants the user access to a LiveKit room where the AI agent is already listening.

POST /api/v1/onboarding-call/skip

Marks the call as skipped. Only permitted when the org setting onboarding_call_allow_skip is true and onboarding_call_required is false. Response204 No Content on success; 400 Bad Request if skipping is not allowed.

POST /api/v1/onboarding-call/complete

Called by the frontend when the LiveKit call ends. Transitions state to completed. Response204 No Content.

POST /api/v1/onboarding-call/admin/reset

Roles required: admin, super_admin Resets a user’s onboarding state to not_started so the call will be offered again on their next login. Request body
{
  "user_id": "<target-user-id>"
}
Response204 No Content.

Data Model

UserOnboardingState (MongoDB: user_onboarding_states)

FieldTypeDescription
org_idstringOrganization the user belongs to
user_idstringTarget user
statusstringSee state machine above
character_idstring?Character assigned for this call
first_offered_atdatetime?When the call was first surfaced
started_atdatetime?When the user began the call
completed_atdatetime?When the call ended normally
skipped_atdatetime?When the user skipped the call
last_call_session_idstring?LiveKit room name / session identifier
A unique compound index on (user_id, org_id) ensures one record per user per org.

System Prompt Generation

OnboardingContextBuilder.build() assembles a rich system prompt for the AI agent by combining:
  • Org context — company name, industry, mission.
  • User profile — name, role, department, start date.
  • Active tasks — the first 3 tasks assigned to the user (titles only).
  • Character persona — the AI character’s name, role, and background.
  • Custom instructions — free-text additions from the org admin (onboarding_call_custom_instructions).
The builder resolves the character through a fallback chain:
  1. settings.onboarding_call_character_id → look up in SimulationCharacter repo.
  2. First character whose role contains “onboarding” or “hr”.
  3. Any first character in the org.

Org Admin Configuration

Settings are stored in SimulationSettings and editable via the Onboarding Call tab in the simulation admin panel.
SettingTypeDefaultDescription
onboarding_call_enabledbooltrueMaster switch
onboarding_call_character_idstring?nullCharacter to use (falls back to onboarding/HR role)
onboarding_call_triggerenum"first_login"When to offer: first_login or manual_only
onboarding_call_requiredboolfalseIf true, skip is blocked
onboarding_call_allow_skipbooltrueShow skip button to user
onboarding_call_custom_instructionsstring?nullFree-text appended to the AI system prompt
onboarding_call_reset_policyenum"manual"When states reset: never, on_role_change, manual

Frontend Components

OnboardingCallCard

Path: frontend/src/components/onboarding/OnboardingCallCard.tsx A self-contained React card shown on the dashboard and guide pages. It:
  • Fetches onboarding status on mount.
  • Shows a “Start Call” button (and optional “Skip” button).
  • Connects to LiveKit using the token from /start.
  • Calls /complete when the LiveKit session ends.
Props: none — reads org/user context from the auth store.

OnboardingCallSettingsPanel

Path: frontend/src/components/admin/simulation/OnboardingCallSettingsPanel.tsx Admin UI rendered inside the Simulation → Onboarding Call subtab. Exposes all SimulationSettings onboarding fields:
  • Enable/disable toggle.
  • Character selector dropdown (populated from org characters).
  • Trigger mode, required/skip toggles.
  • Custom instructions textarea.
  • Reset policy dropdown.
  • Per-user manual reset input.

Integration Points

LayerWhere
Auth flowsrc/apis/auth.pyoffer_onboarding() called on first login
Servicesrc/core/voice_assistance/onboarding_service.py
Prompt buildersrc/core/voice_assistance/onboarding_context_builder.py
API routersrc/apis/onboarding_call.py
DB indexsrc/memory/mongo_client.pyonboarding_states_user_org_unique
Repositorysrc/memory/repositories.pyUserOnboardingStateRepository
Data modelsrc/common/models.pyUserOnboardingState, SimulationSettings
Dashboardfrontend/src/app/dashboard/page.tsx
Guide pagefrontend/src/app/guide/page.tsx
Admin navfrontend/src/components/admin/simulation/SimulationDashboardConfig.ts
Admin renderfrontend/src/components/admin/simulation/SimulationDashboardContent.tsx