--- phase: 05-employee-design plan: 02 type: execute wave: 2 depends_on: ["05-01"] files_modified: - packages/portal/app/(dashboard)/agents/new/page.tsx - packages/portal/app/(dashboard)/agents/new/advanced/page.tsx - packages/portal/app/(dashboard)/agents/new/templates/page.tsx - packages/portal/app/(dashboard)/agents/new/wizard/page.tsx - packages/portal/components/employee-wizard.tsx - packages/portal/components/wizard-steps/step-role.tsx - packages/portal/components/wizard-steps/step-persona.tsx - packages/portal/components/wizard-steps/step-tools.tsx - packages/portal/components/wizard-steps/step-channels.tsx - packages/portal/components/wizard-steps/step-escalation.tsx - packages/portal/components/wizard-steps/step-review.tsx - packages/portal/components/template-gallery.tsx - packages/portal/lib/queries.ts - packages/portal/lib/api.ts - packages/portal/lib/system-prompt-builder.ts autonomous: true requirements: [EMPL-01, EMPL-02, EMPL-03, EMPL-04, EMPL-05] must_haves: truths: - "New Employee button presents three options: Templates, Guided Setup, Advanced" - "Template gallery shows card grid with name, role, tools — one-click deploy creates agent" - "Wizard walks through 5 steps: Role, Persona, Tools, Channels, Escalation + Review" - "Wizard auto-generates system prompt (hidden from user) with AI transparency clause" - "Advanced option opens existing Agent Designer with full control" - "Wizard-created and template-deployed agents appear in Agent Designer for editing" - "Only platform_admin and customer_admin can access creation paths" artifacts: - path: "packages/portal/app/(dashboard)/agents/new/page.tsx" provides: "Three-option entry screen (Templates / Guided Setup / Advanced)" - path: "packages/portal/app/(dashboard)/agents/new/templates/page.tsx" provides: "Template gallery page" - path: "packages/portal/app/(dashboard)/agents/new/wizard/page.tsx" provides: "5-step wizard page" - path: "packages/portal/app/(dashboard)/agents/new/advanced/page.tsx" provides: "Advanced mode (AgentDesigner)" - path: "packages/portal/components/employee-wizard.tsx" provides: "Wizard client component with state management and stepper" - path: "packages/portal/components/template-gallery.tsx" provides: "Template card grid with preview and one-click deploy" - path: "packages/portal/lib/system-prompt-builder.ts" provides: "TypeScript system prompt builder (mirrors Python version)" - path: "packages/portal/lib/queries.ts" provides: "useTemplates and useDeployTemplate hooks" - path: "packages/portal/lib/api.ts" provides: "Template and TemplateDeployResponse types" key_links: - from: "packages/portal/app/(dashboard)/agents/new/page.tsx" to: "/agents/new/templates, /agents/new/wizard, /agents/new/advanced" via: "router.push on card click" pattern: "router\\.push.*agents/new/(templates|wizard|advanced)" - from: "packages/portal/components/template-gallery.tsx" to: "/api/portal/templates" via: "useTemplates TanStack Query hook" pattern: "useTemplates" - from: "packages/portal/components/template-gallery.tsx" to: "/api/portal/templates/{id}/deploy" via: "useDeployTemplate mutation" pattern: "useDeployTemplate" - from: "packages/portal/components/employee-wizard.tsx" to: "/api/portal/tenants/{tid}/agents" via: "useCreateAgent mutation with auto-generated system prompt" pattern: "useCreateAgent|buildSystemPrompt" - from: "packages/portal/lib/system-prompt-builder.ts" to: "packages/portal/components/employee-wizard.tsx" via: "import in review step" pattern: "buildSystemPrompt" --- Complete frontend for all three employee creation paths: three-option entry screen, template gallery with one-click deploy, 5-step guided wizard, and Advanced mode (existing Agent Designer relocated). Purpose: Give operators and customer admins three ways to create AI employees — from fastest (templates) to most control (Advanced) — all producing agents editable in Agent Designer. Output: New pages (entry, templates, wizard, advanced), wizard step components, template gallery component, system prompt builder, TanStack Query hooks for templates API. @/home/adelorenzo/.claude/get-shit-done/workflows/execute-plan.md @/home/adelorenzo/.claude/get-shit-done/templates/summary.md @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/05-employee-design/05-CONTEXT.md @.planning/phases/05-employee-design/05-RESEARCH.md @.planning/phases/05-employee-design/05-VALIDATION.md @.planning/phases/05-employee-design/05-01-SUMMARY.md From packages/shared/shared/api/templates.py (created in Plan 01): ```python # GET /api/portal/templates -> list[TemplateResponse] # GET /api/portal/templates/{id} -> TemplateResponse # POST /api/portal/templates/{id}/deploy -> TemplateDeployResponse class TemplateResponse(BaseModel): id: str name: str role: str description: str category: str persona: str system_prompt: str model_preference: str tool_assignments: list[str] escalation_rules: list[dict] is_active: bool sort_order: int created_at: datetime class TemplateDeployRequest(BaseModel): tenant_id: str class TemplateDeployResponse(BaseModel): agent: AgentResponse # the newly created agent ``` From packages/portal/lib/api.ts (existing): ```typescript export interface Agent { id: string; tenant_id: string; name: string; role: string; persona: string; system_prompt: string; model_preference: string; tool_assignments: string[]; escalation_rules: EscalationRule[]; is_active: boolean; ... } export interface AgentCreate { name: string; role: string; persona?: string; system_prompt?: string; model_preference?: string; tool_assignments?: string[]; escalation_rules?: EscalationRule[]; is_active?: boolean; } export interface EscalationRule { condition: string; action: string; } ``` From packages/portal/lib/queries.ts (existing): ```typescript export function useCreateAgent(): UseMutationResult export function useChannelConnections(tenantId: string): UseQueryResult export const queryKeys = { agents: (tenantId: string) => [...], ... } ``` From packages/portal/components/agent-designer.tsx (existing): ```typescript export interface AgentDesignerValues { tenant_id: string; name: string; role: string; persona: string; system_prompt: string; model_preference: string; tool_assignments: string[]; escalation_rules: EscalationRule[]; is_active: boolean; } export function AgentDesigner(props: { defaultValues?: Partial; tenants: Tenant[]; onSubmit: (data: AgentDesignerValues) => Promise; isLoading: boolean; submitLabel: string; }) ``` From packages/portal/components/onboarding-stepper.tsx (existing pattern to adapt): ```typescript export interface StepInfo { number: number; label: string; description: string; } export function OnboardingStepper({ currentStep }: { currentStep: number }) ``` Task 1: Three-option entry screen, Advanced page, TypeScript types, TanStack hooks, and system prompt builder packages/portal/app/(dashboard)/agents/new/page.tsx, packages/portal/app/(dashboard)/agents/new/advanced/page.tsx, packages/portal/lib/api.ts, packages/portal/lib/queries.ts, packages/portal/lib/system-prompt-builder.ts 1. Add TypeScript types to `packages/portal/lib/api.ts`: ```typescript export interface Template { id: string; name: string; role: string; description: string; category: string; persona: string; system_prompt: string; model_preference: string; tool_assignments: string[]; escalation_rules: EscalationRule[]; is_active: boolean; sort_order: number; created_at: string; } export interface TemplateDeployResponse { agent: Agent; } ``` 2. Add TanStack Query hooks to `packages/portal/lib/queries.ts`: - Add query key: `templates: () => ["templates"] as const` - `useTemplates(): UseQueryResult` — GET /api/portal/templates - `useDeployTemplate(): UseMutationResult` — POST /api/portal/templates/{templateId}/deploy with body { tenant_id }. On success, invalidate queryKeys.agents(tenantId) and queryKeys.allAgents. 3. Create `packages/portal/lib/system-prompt-builder.ts`: - `export function buildSystemPrompt(data: { name: string; role: string; persona?: string; tool_assignments?: string[]; escalation_rules?: { condition: string; action: string }[] }): string` - Assembles: "You are {name}, {role}.\n\n{persona}" (skip persona line if empty) - If tools not empty: "\n\nYou have access to the following tools: {tools.join(', ')}." - If escalation rules not empty: "\n\nEscalation rules:\n" + rules mapped to "- If {condition}: {action}" - ALWAYS append: "\n\nWhen directly asked if you are an AI, always disclose that you are an AI assistant." - This mirrors the Python build_system_prompt from Plan 01 4. Replace `packages/portal/app/(dashboard)/agents/new/page.tsx` with three-option entry screen: - "use client" component wrapped in Suspense (existing pattern) - Page title: "New AI Employee" with subtitle: "Choose how you want to get started" - Three Card components in a responsive grid (grid-cols-1 md:grid-cols-3 gap-6): a. **Templates** — Icon: LayoutTemplate (lucide-react). Headline: "Templates". Subtitle: "Deploy in 30 seconds". Description: "Choose from pre-built AI employees with sensible defaults. One click to deploy." Button: "Browse Templates" -> router.push(`/agents/new/templates?tenant=${tenantId}`) b. **Guided Setup** — Icon: Wand2 (lucide-react). Headline: "Guided Setup". Subtitle: "5-minute setup". Description: "Step-by-step wizard walks you through role, persona, tools, channels, and escalation." Button: "Start Setup" -> router.push(`/agents/new/wizard?tenant=${tenantId}&step=1`) c. **Advanced** — Icon: Settings (lucide-react). Headline: "Advanced". Subtitle: "Full control". Description: "Complete Agent Designer with manual system prompt editing and all configuration options." Button: "Open Designer" -> router.push(`/agents/new/advanced?tenant=${tenantId}`) - Include tenant selector dropdown at top if the user has multiple tenants (reuse useTenants pattern from current page) - Include "Back to Employees" button with ArrowLeft icon (existing pattern) - Template card should have a visual emphasis (e.g., "Recommended" badge or primary border) since it is the fastest path per user decision 5. Create `packages/portal/app/(dashboard)/agents/new/advanced/page.tsx`: - Move the existing NewAgentContent logic from the current page.tsx here - "use client", Suspense wrapper, useTenants, useCreateAgent, AgentDesigner component - Identical functionality to the old /agents/new page — this IS the existing Agent Designer in create mode - Page title: "Advanced Agent Designer" with "Back to New Employee" link to /agents/new cd /home/adelorenzo/repos/konstruct/packages/portal && npx next build 2>&1 | tail -20 Three-option entry screen at /agents/new shows Templates, Guided Setup, and Advanced cards. Advanced page at /agents/new/advanced renders existing AgentDesigner. Template types and hooks added to api.ts and queries.ts. System prompt builder function created. Portal builds without errors. Task 2: Template gallery page and wizard with all step components packages/portal/app/(dashboard)/agents/new/templates/page.tsx, packages/portal/app/(dashboard)/agents/new/wizard/page.tsx, packages/portal/components/template-gallery.tsx, packages/portal/components/employee-wizard.tsx, packages/portal/components/wizard-steps/step-role.tsx, packages/portal/components/wizard-steps/step-persona.tsx, packages/portal/components/wizard-steps/step-tools.tsx, packages/portal/components/wizard-steps/step-channels.tsx, packages/portal/components/wizard-steps/step-escalation.tsx, packages/portal/components/wizard-steps/step-review.tsx 1. Create `packages/portal/components/template-gallery.tsx` ("use client"): - Props: `{ tenantId: string; onDeployed?: (agent: Agent) => void }` - Uses `useTemplates()` hook to fetch templates - Uses `useDeployTemplate()` mutation for one-click deploy - Card grid layout: `grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4` - Each card shows: name (bold), role, description (text-muted-foreground), tool_assignments as Badge chips, category as small label - Each card has two actions: "Preview" button (expands to show full config: persona, escalation rules, system_prompt) and "Deploy" button (primary, calls deploy mutation) - Preview: use a collapsible section or Dialog. Show persona paragraph, escalation rules list, model preference. Per user decision: "Preview expands to show full configuration before deploying" - Deploy button: on click, call `deployTemplate.mutateAsync({ templateId: template.id, tenantId })`, on success redirect to `/agents/${newAgent.id}?tenant=${tenantId}` (satisfies EMPL-05: agent appears in Agent Designer for customization) - Loading state: skeleton cards while fetching - Deploy loading state: button shows spinner/disabled during mutation - Error state: toast or inline error on deploy failure - Empty state: "No templates available" (should not happen with seed data, but handle gracefully) 2. Create `packages/portal/app/(dashboard)/agents/new/templates/page.tsx`: - "use client" with Suspense wrapper - Reads `tenant` from `useSearchParams()` - Renders: Back button to /agents/new, page title "Template Library" with subtitle "Choose a pre-built AI employee to deploy instantly", then `` - If no tenant selected, show tenant selector (same pattern as entry screen) 3. Create `packages/portal/components/employee-wizard.tsx` ("use client"): - Props: `{ tenantId: string; initialStep?: number }` - State: `useState>({})` where WizardData = `{ name: string; roleTitle: string; persona: string; tool_assignments: string[]; channel_ids: string[]; escalation_rules: { condition: string; action: string }[] }` - State: `currentStep` number (1-6, where 6 is the review step) - Renders a stepper component adapted from OnboardingStepper pattern with 5 numbered steps + review: Steps: Role (1), Persona (2), Tools (3), Channels (4), Escalation (5), Review (6) Stepper shows steps 1-5 as numbered circles with labels; step 6 (Review) is a distinct "Review & Deploy" section - Each step renders the corresponding step component, passing wizardData and onNext callback - onNext: `(updates: Partial) => { setWizardData(prev => ({...prev, ...updates})); setCurrentStep(prev => prev + 1); }` - onBack: `setCurrentStep(prev => prev - 1)` (show "Back" button on steps 2-6) - URL update on step change: `router.replace(`/agents/new/wizard?tenant=${tenantId}&step=${currentStep}`, { scroll: false })` - Note: wizard state is in React state, NOT URL params (per research: persona text would pollute URL). State loss on refresh is acceptable per research pitfall analysis. 4. Create step components in `packages/portal/components/wizard-steps/`: a. `step-role.tsx` — "What role will they fill?" - Props: `{ data: Partial; onNext: (updates: Partial) => void }` - Two inputs: Employee Name (text input, required, placeholder "e.g., Mara") and Job Title / Role (text input, required, placeholder "e.g., Customer Support Representative") - Use react-hook-form with zod schema: `z.object({ name: z.string().min(1, "Name is required").max(255), roleTitle: z.string().min(1, "Role is required").max(255) })` - Use standardSchemaResolver (NOT zodResolver — project decision) - "Next" button calls onNext with { name, roleTitle } - Pre-fill from data if user navigates back b. `step-persona.tsx` — "How should they behave?" - Textarea for persona description, placeholder: "Describe your employee's personality and communication style. For example: Professional, empathetic, solution-oriented. Fluent in English and Spanish. Prefers concise responses." - Optional field — can proceed with empty (will generate a default persona in system prompt) - "Next" button calls onNext with { persona } c. `step-tools.tsx` — "What tools can they use?" - Multi-select for tool_assignments using Badge chip pattern (same as Agent Designer) - Available tools: knowledge_base_search, zendesk_ticket_create, zendesk_ticket_lookup, calendar_book (hardcoded list — same as Agent Designer) - Click to toggle, selected tools shown as highlighted Badges - Optional — can proceed with no tools selected - "Next" button calls onNext with { tool_assignments } d. `step-channels.tsx` — "Where will they work?" - Uses `useChannelConnections(tenantId)` to fetch connected channels - If channels exist: show checkboxes for each channel (channel_type + workspace_id), pre-select all - If NO channels connected: show info message "No channels connected yet. Your employee will be deployed and can be assigned to channels later." (per research pitfall 4) — allow proceeding with empty selection - "Next" button calls onNext with { channel_ids: selectedChannelIds } - NOTE: In v1, agent routing is tenant-scoped not per-agent. The channel step is informational — selecting channels does NOT create a channel-agent join. The agent will respond in all tenant channels. Display this as "Your employee will be active in all connected channels" with the channel list shown for confirmation. e. `step-escalation.tsx` — "When should they hand off to a human?" - Dynamic list of escalation rules (add/remove) - Each rule: condition input (text, placeholder "e.g., billing_dispute AND attempts > 2") + action select (handoff_human, notify_admin) - "Add Rule" button to add another row - Optional — can proceed with no rules - "Next" button calls onNext with { escalation_rules } f. `step-review.tsx` — "Review & Deploy" - Props: `{ data: WizardData; tenantId: string; onBack: () => void }` - Summary card showing all configured values: Name, Role, Persona (or "Default"), Tools (or "None"), Channels ("All connected" or specific list), Escalation Rules (or "None") - Does NOT show the system prompt (per locked decision: system prompt hidden from wizard user) - "Deploy Employee" primary button — calls useCreateAgent mutation with: ``` { tenantId, data: { name: data.name, role: data.roleTitle, persona: data.persona || "", system_prompt: buildSystemPrompt({ name: data.name, role: data.roleTitle, persona: data.persona, tool_assignments: data.tool_assignments, escalation_rules: data.escalation_rules }), model_preference: "quality", tool_assignments: data.tool_assignments || [], escalation_rules: data.escalation_rules || [], is_active: true } } ``` - On success: redirect to `/agents/${newAgent.id}?tenant=${tenantId}` (agent edit page — satisfies EMPL-05) - Error handling: show inline error message on failure 5. Create `packages/portal/app/(dashboard)/agents/new/wizard/page.tsx`: - "use client" with Suspense wrapper - Reads `tenant` and `step` from `useSearchParams()` - Renders: Back button to /agents/new, page title "Create AI Employee" with subtitle "Step-by-step guided setup", then `` - If no tenant selected, show tenant selector cd /home/adelorenzo/repos/konstruct/packages/portal && npx next build 2>&1 | tail -20 Template gallery at /agents/new/templates shows card grid of templates with preview and one-click deploy. Wizard at /agents/new/wizard walks through 5 steps (Role, Persona, Tools, Channels, Escalation) plus Review with Deploy button. Both paths create agents via existing API. All pages build without TypeScript errors. Agents created via either path redirect to edit page (EMPL-05). 1. `cd packages/portal && npx next build` succeeds without errors 2. All three paths from /agents/new route correctly: Templates, Guided Setup, Advanced 3. Template gallery loads templates from API and deploys with one click 4. Wizard collects data across 5 steps and creates agent with auto-generated system prompt 5. `pytest tests/ -x` still passes (no backend regressions) - Three-option entry screen at /agents/new with Templates (recommended), Guided Setup, and Advanced cards - Template gallery shows 7 templates as cards with preview and one-click deploy - Template deploy creates agent and redirects to edit page - 5-step wizard collects Role, Persona, Tools, Channels, Escalation then shows Review summary - Wizard Deploy creates agent with auto-generated system prompt (including AI transparency clause) and redirects to edit page - Advanced mode renders existing AgentDesigner unchanged - Portal builds without TypeScript errors After completion, create `.planning/phases/05-employee-design/05-02-SUMMARY.md`