# Step-by-Step Setup & Operator Routing Readiness Wizard Design **Date:** 2026-10-16 **Topic:** Step-by-Step Onboarding Setup, Readiness Diagnostics, Route Simulator, and One-Click Quick Fixes (`en-US`, `ru-RU`, `zh-CN`) --- ## 1. Problem Statement & User Intent When deploying or configuring `agent-desk-ng`, administrators and operators must configure six interdependent entities for customer requests to reach a human operator: 1. **Operator Teams (`AgentTeam`)**: At least one active team (`Status == StatusOk`). 2. **Working Schedules (`AgentTeamSchedule`)**: At least one active schedule (`Status == StatusOk`) covering the current timestamp (`start_at <= now < end_at`) for the target team. Without an active shift, conversations stay in `Pending` and return an off-hours message. 3. **Operator Profiles (`AgentProfile` & `User`)**: An active user (`User.Status == StatusOk`) with an active `AgentProfile` (`Status == StatusOk`), assigned to the active team, with `AutoAssignEnabled == true`, `ServiceStatus == ServiceStatusIdle (0)`, `MaxConcurrentCount > 0`, and available capacity (`activeCount < MaxConcurrentCount`). 4. **AI Agent & Handoff Mode (`AIAgent`)**: An active `AIAgent` (`Status == StatusOk`) whose `ServiceMode` allows reaching a human (`HumanOnly` or `AIFirst`), and whose `TeamIDs` field references at least one valid, active `AgentTeam`. 5. **Inbound Channels (`Channel`)**: At least one active `Channel` (`Status == StatusOk`) linked to a valid `AIAgentID` with `AIAgentRolloutPercent > 0`. 6. **End-to-End Routing Path**: A complete, unbroken path from an active `Channel` -> active `AIAgent` (with handoff enabled) -> active `AgentTeam` -> currently active `AgentTeamSchedule` -> at least one eligible, idle `AgentProfile` with free capacity. Currently, if any single link in this chain is missing or misconfigured (e.g., missing shift schedule for the current time, empty `TeamIDs` on the AI agent, operator `AutoAssignEnabled == false` or status `Busy`, or `AIOnly` service mode), requests silently fail to reach the operator without explaining why. ### Goals 1. **Step-by-Step Readiness Check**: Inspect all 6 steps of the operator routing chain and report exact status (`ok`, `warning`, `error`), specific blocking reasons, and actionable fixes. 2. **Current Operator Diagnostic**: Tell the currently logged-in operator whether they personally can receive customer conversations right now, and if not, why (missing profile, no team, team off-hours, busy status, auto-assign disabled, at capacity). 3. **Interactive Route Simulator ("Why isn't my request reaching an operator?")**: Dry-run the actual dispatch evaluation for a selected channel (or all channels) and visualize every hop from Channel -> AI Agent -> Team -> Shift Schedule -> Candidate Operators -> Winning Operator (or exact failure point). 4. **One-Click Quick Fixes**: Provide safe, atomic backend actions to fix common blockers in one click (create/enable default team & 24/7 shift schedule, activate current user's operator profile and set idle, bind teams & handoff mode on AI agents, create/link default web channel, or run a complete "Quick Setup All" action). 5. **Multi-Surface UI**: - Dedicated `/dashboard/setup` page with Step-by-Step Wizard and Route Simulator. - Setup Readiness Banner on `/dashboard` Overview page whenever any step is incomplete or degraded. - Sidebar navigation item under Dashboard. - Operator Readiness status indicator & popover with 1-click fix inside the `/support` operator workbench header. 6. **Full Localization**: Complete support across all three repository locales: `en-US`, `ru-RU`, and `zh-CN` (both backend and frontend). --- ## 2. Backend Architecture Following `AGENTS.md` layer ownership (`models -> repositories -> services -> handlers -> builders/response DTOs`): ### 2.1 Endpoints (`internal/bootstrap/routes.go`) Mounted under `/api/dashboard/setup`: - `GET /api/dashboard/setup/readiness` -> `SetupReadinessHandler.GetReadiness` - `POST /api/dashboard/setup/simulate_route` -> `SetupReadinessHandler.PostSimulateRoute` - `POST /api/dashboard/setup/quick_fix` -> `SetupReadinessHandler.PostQuickFix` Permissions: - `GET /api/dashboard/setup/readiness` and `POST /api/dashboard/setup/simulate_route` and `POST /api/dashboard/setup/quick_fix` are available to authenticated dashboard/support users so both administrators on `/dashboard` and operators on `/support` can diagnose and fix their readiness. Write actions that modify global resources check appropriate permissions or allow self-profile/bootstrap setup safely. ### 2.2 Request & Response DTOs (`internal/pkg/dto/request/setup_readiness_req.go`, `internal/pkg/dto/response/setup_readiness_resp.go`) #### `SetupReadinessResponse` - `overall_status`: `"ok" | "warning" | "error"` - `ready_steps`: `int` - `total_steps`: `int` (6) - `can_receive_requests_now`: `bool` - `steps`: `[]SetupStepItem` - `key`: `"teams" | "schedules" | "operators" | "ai_agents" | "channels" | "end_to_end"` - `step_number`: `1..6` - `status`: `"ok" | "warning" | "error"` - `summary_code`: machine-readable reason code (e.g. `"ok"`, `"no_active_team"`, `"no_schedule_now"`, `"no_idle_operator"`, `"agent_ai_only"`, `"agent_missing_teams"`, `"no_active_channel"`, `"no_end_to_end_path"`) - `total_count`: `int` - `ready_count`: `int` - `issues`: `[]SetupIssueItem` - `code`: string (e.g. `"team_no_active_schedule"`, `"agent_ai_only_mode"`, `"agent_no_teams"`, `"operator_busy"`, `"operator_auto_assign_off"`, `"operator_no_team"`, `"operator_at_capacity"`, `"channel_no_agent"`, `"channel_zero_rollout"`) - `severity`: `"warning" | "error"` - `entity_type`: `"team" | "schedule" | "operator" | "ai_agent" | "channel" | "system"` - `entity_id`: `int64` - `entity_name`: `string` - `quick_fix_action`: `string` (optional action key) - `quick_fix_actions`: `[] string` (e.g. `["ensure_team_and_schedule"]`) - `manage_path`: `string` (e.g. `"/dashboard/agent-team"`) - `current_operator`: `CurrentOperatorDiagnostic` - `user_id`: `int64` - `username`: `string` - `nickname`: `string` - `has_profile`: `bool` - `profile_status_ok`: `bool` - `team_id`: `int64` - `team_name`: `string` - `team_active`: `bool` - `team_has_schedule_now`: `bool` - `service_status`: `int` (`0` = Idle, `1` = Busy) - `auto_assign_enabled`: `bool` - `active_conversation_count`: `int64` - `max_concurrent_count`: `int` - `can_receive_now`: `bool` - `blocker_codes`: `[]string` (e.g. `["missing_profile", "no_team", "team_off_hours", "status_busy", "auto_assign_disabled", "at_capacity"]`) #### `SetupSimulateRouteRequest` & `SetupSimulateRouteResponse` - Request: - `channel_id`: `int64` (optional; if `0`, picks the first active channel or simulates all active channels) - `bypass_ai`: `bool` (optional; simulates what happens when customer requests a human / handoff triggers) - Response: - `channel_id`: `int64` - `channel_name`: `string` - `channel_type`: `string` - `will_reach_operator`: `bool` - `final_outcome_code`: `"assigned_to_operator" | "blocked_no_channel" | "blocked_channel_disabled" | "blocked_zero_rollout" | "blocked_missing_ai_agent" | "blocked_ai_only_mode" | "queued_ai_first_requires_handoff" | "blocked_agent_no_teams" | "queued_off_hours_no_schedule" | "queued_no_eligible_operator"` - `matched_operator`: `*SimulatedOperatorCandidate` - `hops`: `[]SimulatedRouteHop` - `hop_key`: `"channel" | "ai_agent" | "teams" | "schedules" | "operators"` - `status`: `"ok" | "warning" | "error"` - `reason_code`: string - `entity_name`: string - `quick_fix_action`: string - `candidate_operators`: `[]SimulatedOperatorCandidate` - `user_id`: `int64` - `display_name`: `string` - `team_id`: `int64` - `team_name`: `string` - `eligible`: `bool` - `skip_reason_code`: `"" | "profile_disabled" | "user_disabled" | "team_not_in_agent" | "team_off_hours" | "auto_assign_off" | "status_busy" | "at_capacity"` - `active_count`: `int64` - `max_concurrent_count`: `int` - `service_status`: `int` - `auto_assign_enabled`: `bool` #### `SetupQuickFixRequest` & `SetupQuickFixResponse` - Request: - `action`: - `"quick_setup_all"` — ensures an active team exists, ensures a 24/7 active shift schedule exists for all active teams without a current schedule, ensures the current user has an active idle `AgentProfile` in an active team with `AutoAssignEnabled = true`, ensures at least one active `AIAgent` is linked to the active teams and allows human handoff (`AIFirst` with `AutoHandoffOnFailure = true` or `HumanOnly`), and ensures at least one active Web `Channel` is linked to that `AIAgent` with `RolloutPercent = 100`. - `"ensure_team_and_schedule"` — creates a default team if none exists, and creates an active shift schedule (`now - 1h` to `now + 365d`) for any active team lacking a currently active schedule. - `"enable_my_operator_profile"` — creates or updates the current user's `AgentProfile`: assigns to first active team (creating one + schedule if needed), sets `Status = StatusOk`, `AutoAssignEnabled = true`, `ServiceStatus = ServiceStatusIdle`, `MaxConcurrentCount = max(existing, 10)`. Also triggers pending conversation dispatch. - `"fix_ai_agent_handoff"` — for `entity_id` (or all active AI agents): binds all active `TeamIDs` if empty, switches `AIOnly` to `AIFirst` (or `HumanOnly` if no model is configured), sets `AutoHandoffOnFailure = true`, and ensures `Status = StatusOk`. If no `AIAgent` exists at all, creates a default `HumanOnly` reception agent bound to the active team. - `"ensure_default_channel"` — if no active channel exists, creates a default Web channel linked to an active `AIAgent` with `AIAgentRolloutPercent = 100`; if channels exist with missing `AIAgentID` or `0%` rollout, fixes them. - `entity_id`: `int64` (optional target ID) - Response: - `applied_actions`: `[]string` - `readiness`: `SetupReadinessResponse` (fresh snapshot after fix) --- ## 3. Frontend Architecture ### 3.1 API Module (`web/lib/api/setup-readiness.ts`) - Typed client functions calling `/api/dashboard/setup/readiness`, `/api/dashboard/setup/simulate_route`, and `/api/dashboard/setup/quick_fix` via `web/lib/api/client.ts`. ### 3.2 Dedicated Setup & Diagnostics Page (`web/app/(dashboard)/dashboard/setup/page.tsx`) - Uses `DashboardPage` layout and standard `rounded-md` border styling without shadows (`AGENTS.md` 5.4). - **Top Readiness Header Card**: - Shows overall status badge (`Ready` / `Needs Attention`), progress bar (`X / 6 steps ready`), current operator status summary, and primary CTA **"Quick Setup All in 1 Click"** (`quick_setup_all`) + **"Refresh Check"**. - **Two Main Sections**: 1. **Step-by-Step Setup Checklist (Steps 1 to 6)**: - Renders each of the 6 steps in logical order: 1. Operator Teams 2. Working Hours & Active Shift Schedules 3. Operator Profiles & Online Availability 4. AI Agent & Handoff Configuration 5. Inbound Channels 6. End-to-End Dispatch Verification - Each step displays its status badge, counts (`ready / total`), specific detected issues (with entity names and localized explanations), a **1-Click Quick Fix** button when applicable, and a secondary **"Open Settings"** link to the corresponding management CRUD page. 2. **Interactive Route Simulator ("Why isn't a request reaching an operator?")**: - Allows selecting any channel via `OptionCombobox` (or auto-selects the first channel) and running the live route trace. - Displays the 5-hop visual pipeline (`Channel` -> `AI Agent` -> `Target Teams` -> `Active Schedule` -> `Operator Selection`) with status indicators and inline 1-click fix buttons on any failing hop. - Displays the **Candidate Operators Table** showing every operator profile, their team, load (`active / max`), status (`Idle` / `Busy`), auto-assign state, and exact reason why they were selected or skipped. ### 3.3 Dashboard Home Readiness Banner (`web/app/(dashboard)/dashboard/_components/setup-readiness-banner.tsx`) - Rendered at the top of `DashboardHome` (`web/app/(dashboard)/dashboard/_components/dashboard-home.tsx`). - When `can_receive_requests_now == false` or `overall_status != "ok"` (or when the current operator cannot receive requests), shows a clear alert banner listing the broken steps with: - **"Fix Automatically in 1 Click"** button - **"Open Step-by-Step Setup"** button linking to `/dashboard/setup` ### 3.4 Operator Workbench Readiness Indicator (`web/app/(support)/support/_components/operator-readiness-Button.tsx` / Header integration) - Integrated into the `/support` top bar (`web/app/(support)/support/page.tsx` or header component). - Shows a compact badge indicating whether the operator is currently able to receive incoming customer chats: - Green (`Ready to Receive Chats`) when `current_operator.can_receive_now && readiness.can_receive_requests_now`. - Amber/Red (`Routing Blocked: N issues`) when blocked. - Clicking opens a popover showing: - Why requests are not reaching this operator right now (e.g., *"Your team has no active shift schedule right now (Off-Hours)"*, *"Your operator profile is Busy"*, *"Auto-assign is disabled"*, *"AI Agent has no team assigned"*). - **"Enable Chat Reception in 1 Click"** button (`enable_my_operator_profile` / `quick_setup_all`). - Link to `/dashboard/setup` for full diagnostics. ### 3.5 Navigation (`web/components/app-sidebar.tsx`) - Adds a navigation item for `/dashboard/setup` under the Overview section so users can always find the step-by-step setup wizard. --- ## 4. Localization (`en-US`, `ru-RU`, `zh-CN`) - All backend error messages in `internal/pkg/i18nx/locales/{en-US,ru-RU,zh-CN}.yml`. - All frontend UI copy, step titles, issue descriptions, simulator hop reasons, candidate skip reasons, and action labels in `web/messages/{en-US,ru-RU,zh-CN}.json`. - Subagents running **Gemini Flash** (`model: "flash"`) will be used to prepare and verify translations and assist with parallel inspections. --- ## 5. Testing & Verification 1. **Backend Unit Tests (`internal/services/setup_readiness_service_test.go`)**: - Empty database -> `readiness` reports missing steps (`teams`, `schedules`, `operators`, `ai_agents`, `channels`, `end_to_end`). - Running `quick_Fix("quick_setup_all")` -> creates/fixes the chain atomically so `can_receive_requests_now` becomes `true` and all 6 steps become `ok`. - Route simulator (`SimulateRoute`) accurately identifies off-hours schedule blocks, `AIOnly` blocks, `Busy` operator blocks, and selects the winning operator when ready. 2. **Code Formatting & Static Checks**: - `gofmt` and `go test ./internal/services/...` - `cd web && pnpm typecheck` and `cd web && pnpm lint` - Locale parity check across `en-US.json`, `ru-RU.json`, and `zh-CN.json`. - Security scan via Snyk MCP (`snyk_code_scan`) per global rules.