29 KiB
Phase 5: Employee Design - Research
Researched: 2026-03-24 Domain: Multi-path AI employee creation — wizard, templates, and Advanced mode refactor in Next.js 16 / React 19 Confidence: HIGH
<user_constraints>
User Constraints (from CONTEXT.md)
Locked Decisions
- "New Employee" button presents three options: Templates / Guided Setup / Advanced
- Templates: Card grid gallery of pre-built agents — one-click deploy
- Guided Setup: 5-step wizard (Role → Persona → Tools → Channels → Escalation)
- Advanced: Existing Agent Designer form — full manual control over all fields including system prompt
- Labels: "Templates", "Guided Setup", "Advanced" — clear hierarchy from easiest to most control
- 5 wizard steps: Role definition → Persona setup → Tool selection → Channel assignment → Escalation rules
- System prompt auto-generated from wizard inputs — hidden from user (never shown during wizard)
- Final step: Review summary card showing everything configured, user clicks "Deploy Employee"
- After deploy: agent goes live on selected channels immediately
- Wizard-created agents appear in Agent Designer for later customization
- Templates stored as database seed data — platform admin can add/edit templates via portal
- Card grid gallery with preview — each card shows: name, role description, included tools
- "Preview" expands to show full configuration before deploying
- V1 Templates (7+): Customer Support Rep, Sales Assistant, Office Manager, Project Coordinator, Financial Manager, Controller, Accountant
- One-click deploy — no customization step before deployment
- Auto-assigns to all connected channels for the tenant
- User can find the deployed agent in the employee list and edit via Agent Designer later
- Template is a snapshot — deploying creates an independent agent that doesn't track template changes
- Agent Designer becomes the "Advanced" option for new employee creation
- Also serves as the edit mode for all existing agents (regardless of how they were created)
- Wizard-created and template-deployed agents are fully editable in Agent Designer
- No functionality removed from Agent Designer — it remains the power-user tool
Claude's Discretion
- Wizard step UI design (stepper, cards, progress indicator)
- Template card visual design
- Review summary card layout
- How wizard inputs map to system prompt construction
- Template seed data format and migration approach
- Whether templates get a dedicated DB table or reuse the agents table with a
is_templateflag
Deferred Ideas (OUT OF SCOPE)
None — discussion stayed within phase scope </user_constraints>
<phase_requirements>
Phase Requirements
| ID | Description | Research Support |
|---|---|---|
| EMPL-01 | Multi-step wizard guides user through AI employee creation (role definition, persona, tools, channels, escalation rules) without requiring knowledge of system prompt format | Wizard component pattern using URL searchParams for step state; react-hook-form + zod for per-step validation; system prompt builder function maps wizard inputs to system_prompt field |
| EMPL-02 | Pre-built agent templates (e.g., Customer Support Rep, Sales Assistant, Office Manager) available for one-click deployment with sensible defaults | Templates DB table with seed migration 007; new GET /templates and POST /templates/{id}/deploy API endpoints; TanStack Query hooks useTemplates and useDeployTemplate |
| EMPL-03 | Template-deployed agents are immediately functional — respond in connected channels with the template's persona, tools, and escalation rules | Deploy endpoint calls existing POST /tenants/{tid}/agents + assigns all connected channels; channel_connections query provides auto-assignment targets |
| EMPL-04 | Wizard and templates accessible to platform admins and customer admins (RBAC-enforced, not operators) | require_tenant_admin guard on all new creation endpoints — same guard already used on POST /tenants/{tid}/agents; EMPL-01/02 are creation paths, so existing guard applies |
| EMPL-05 | Agents created via wizard or template appear in Agent Designer for further customization | All creation paths produce agents through the same POST /agents endpoint and ORM model; edit page at /agents/[id] already works for all agents |
| </phase_requirements> |
Summary
Phase 5 adds three employee creation paths on top of the existing Agent CRUD infrastructure. The backend (FastAPI, SQLAlchemy, PostgreSQL) is largely complete — the Agent ORM model, create/update/delete endpoints, and RBAC guards all exist and need only minor additions. The primary new backend work is a templates table with seed data and a deploy endpoint that wraps the existing agent creation path.
The frontend work is larger. The current /agents/new page routes directly to AgentDesigner. It must become a three-option entry screen. The 5-step wizard is a new client component using the same URL-searchParams step tracking pattern established by the onboarding wizard. The template gallery is a new card grid that reads from a new /api/portal/templates endpoint.
The system prompt auto-generation for the wizard is a pure TypeScript function that assembles the stored fields (role, persona, tool list, escalation rules) into a coherent system prompt string — no AI call needed.
Primary recommendation: Reuse the existing OnboardingStepper component pattern for the wizard stepper; store templates in a dedicated agent_templates table (cleaner than is_template flag, avoids polluting the agents list); use URL searchParams for wizard step state (established project pattern).
Standard Stack
Core (all already in use — no new installs needed)
| Library | Version | Purpose | Why Standard |
|---|---|---|---|
| Next.js | 16.2.1 | App Router, pages, routing | Project standard |
| React | 19.2.4 | UI | Project standard |
| react-hook-form | existing | Per-step form validation | Project standard (agentDesignerSchema pattern) |
| zod | existing | Schema validation | Project standard (standardSchemaResolver) |
| @hookform/resolvers | existing | standardSchemaResolver | Project standard — zodResolver dropped in v5 |
| TanStack Query | existing | Server state, mutations | Project standard (useCreateAgent pattern) |
| shadcn/ui | existing | Card, Button, Badge, Dialog, Select | Project standard |
| Tailwind CSS | existing | Styling | Project standard |
| FastAPI | existing | API endpoints | Project standard |
| SQLAlchemy 2.0 | existing | ORM, templates table | Project standard |
| Alembic | existing | Migration 007 for templates | Project standard |
| pytest + pytest-asyncio + httpx | existing | Integration tests | Project standard |
No new packages required
All needed libraries are already installed. The wizard, template gallery, and system prompt builder are implemented using existing tools.
Architecture Patterns
Recommended File Structure (new files only)
packages/portal/
├── app/(dashboard)/agents/
│ └── new/
│ ├── page.tsx # REPLACE: three-option entry screen
│ ├── wizard/
│ │ └── page.tsx # NEW: 5-step wizard page
│ └── templates/
│ └── page.tsx # NEW: template gallery page
├── components/
│ ├── employee-wizard.tsx # NEW: 5-step wizard component
│ ├── employee-wizard-stepper.tsx # NEW: wizard progress indicator
│ └── template-gallery.tsx # NEW: template card grid
packages/shared/shared/
├── api/
│ └── templates.py # NEW: GET /templates, POST /templates/{id}/deploy
├── models/
│ └── tenant.py # ADD: AgentTemplate ORM model
└── prompts/
└── system_prompt_builder.py # NEW: wizard → system prompt construction
migrations/versions/
└── 007_agent_templates.py # NEW: agent_templates table + seed data
Pattern 1: Three-Option Entry Screen
The current /agents/new/page.tsx becomes a three-panel selection screen. Each option is a Card with a headline, description, and "Start" button. This is a client component.
// packages/portal/app/(dashboard)/agents/new/page.tsx
"use client";
// Router push to three distinct destinations:
// Templates → /agents/new/templates?tenant={id}
// Guided Setup → /agents/new/wizard?tenant={id}&step=1
// Advanced → /agents/new/advanced?tenant={id} (or reuse existing AgentDesigner inline)
The "Advanced" path can either:
- Route to a sub-path
/agents/new/advancedthat renders<AgentDesigner>directly, OR - Replace
page.tsxwith a mode switch that renders the three-option screen when nomodeparam is set, and renders AgentDesigner when?mode=advanced
Recommendation: Sub-pages (/agents/new/wizard, /agents/new/templates) are cleaner — each is an independent route with its own URL. The existing /agents/new page becomes the selector. Advanced mode moves to /agents/new/advanced.
Pattern 2: 5-Step Wizard with URL State
The onboarding wizard at /onboarding uses ?step=1|2|3 in URL searchParams. The employee wizard follows the same pattern — established, browser-refresh safe, shareable.
The wizard page is an async server component that reads searchParams (Promise in Next.js 15+). The step content components are client components.
// packages/portal/app/(dashboard)/agents/new/wizard/page.tsx
// Server component (no "use client")
interface WizardPageProps {
searchParams: Promise<{ step?: string; tenant?: string }>;
}
export default async function WizardPage({ searchParams }: WizardPageProps) {
const params = await searchParams;
const step = parseInt(params.step ?? "1", 10);
const tenantId = params.tenant_id ?? "";
// ...render EmployeeWizardStepper + step content
}
Step navigation uses router.push with updated searchParams:
router.push(`/agents/new/wizard?tenant=${tenantId}&step=${nextStep}`);
Pattern 3: Wizard State — React useState (not URL)
The wizard accumulates data across 5 steps. The step page contains the stepper and renders one step component at a time. Step data is held in a client-component parent via useState — NOT in URL params (persona text, tool lists would pollute the URL).
// employee-wizard.tsx — client component
"use client";
interface WizardData {
role: string;
roleTitle: string;
persona: string;
tool_assignments: string[];
channel_ids: string[]; // IDs of selected channels to assign
escalation_rules: { condition: string; action: string }[];
}
// Parent holds state, passes down to each step component
const [wizardData, setWizardData] = useState<Partial<WizardData>>({});
The wizard page itself is a server component that renders <EmployeeWizard tenantId={tenantId} initialStep={step} /> which is a client component managing all state.
Pattern 4: System Prompt Builder
A pure TypeScript/Python function assembles wizard inputs into a system prompt. No LLM call — just string templating.
// 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 {
const toolsSection = data.tool_assignments.length > 0
? `\n\nYou have access to the following tools: ${data.tool_assignments.join(", ")}.`
: "";
const escalationSection = data.escalation_rules.length > 0
? `\n\nEscalation rules:\n${data.escalation_rules.map(r => `- If ${r.condition}: ${r.action}`).join("\n")}`
: "";
const aiClause = "\n\nWhen directly asked if you are an AI, always disclose that you are an AI assistant.";
return `You are ${data.name}, ${data.role}.\n\n${data.persona}${toolsSection}${escalationSection}${aiClause}`;
}
The AI transparency clause (unconditional AI disclosure) is a locked project decision from Phase 1. It must be included in all auto-generated system prompts.
Pattern 5: Template DB Table (Dedicated Table)
The CONTEXT.md leaves the template storage approach to Claude's discretion. A dedicated agent_templates table is cleaner than an is_template flag on the agents table:
- Templates are never tenant-scoped (global, created by platform admin)
- They should not appear in tenant agent lists
- They have additional metadata fields (description, category, preview)
- No RLS needed — templates are read-only for all users, write for platform admin
-- agent_templates table (migration 007)
CREATE TABLE agent_templates (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name TEXT NOT NULL,
role TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '', -- shown in card preview
category TEXT NOT NULL DEFAULT 'general',
persona TEXT NOT NULL DEFAULT '',
system_prompt TEXT NOT NULL DEFAULT '',
model_preference TEXT NOT NULL DEFAULT 'quality',
tool_assignments JSONB NOT NULL DEFAULT '[]',
escalation_rules JSONB NOT NULL DEFAULT '[]',
is_active BOOLEAN NOT NULL DEFAULT TRUE,
sort_order INTEGER NOT NULL DEFAULT 0,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
Platform admin CRUD uses require_platform_admin guard. All users can GET templates (no auth required beyond being a portal member).
Pattern 6: Template Deploy Endpoint
Deploy calls existing agent creation logic + auto-assigns all connected channels.
# POST /api/portal/templates/{template_id}/deploy
# Body: { tenant_id: UUID }
# Guard: require_tenant_admin
# Logic:
# 1. Fetch template by ID
# 2. Create Agent from template fields (snapshot — independent copy)
# 3. Return AgentResponse
Auto-assignment to connected channels: the deploy endpoint queries channel_connections for the tenant and stores the channel IDs. For v1, the agent is created and marked active — the channel assignment means the agent responds to all messages in those channels (the existing routing already assigns by tenant, not per-agent channel list). No additional channel-agent join table is needed for v1.
Pattern 7: Wizard Step Components
Each step is a separate component file under components/wizard-steps/:
components/wizard-steps/
├── step-role.tsx # Name + Job Title inputs
├── step-persona.tsx # Persona textarea (plain language)
├── step-tools.tsx # Tool multi-select (badge chips, same as AgentDesigner)
├── step-channels.tsx # Channel multi-select from connected channels
├── step-escalation.tsx # Escalation rules (simplified compared to AgentDesigner)
└── step-review.tsx # Summary card + "Deploy Employee" button
Each step receives wizardData and onNext: (updates: Partial<WizardData>) => void. The review step receives the complete wizardData and calls the createAgent mutation.
Anti-Patterns to Avoid
- Storing wizard state in URL params: Role name is fine, but persona text and tool lists would make URLs unreadable and hit browser URL length limits. Keep multi-field state in React state.
- Creating a new agent creation endpoint for wizard: The wizard uses the existing
POST /tenants/{tid}/agentsendpoint — it just pre-fillssystem_promptfrom the builder function. is_templateflag on the agents table: Templates are global platform data, not tenant agents. A separate table avoids polluting agent lists and avoids RLS complications.- Template tracking changes after deploy: The CONTEXT.md explicitly states deployed agents are independent snapshots. Do not add foreign key from agents back to templates.
- Showing the system_prompt field in the wizard UI: Locked decision — system prompt is hidden during wizard. Only visible in Agent Designer (Advanced mode).
Don't Hand-Roll
| Problem | Don't Build | Use Instead | Why |
|---|---|---|---|
| Step progress indicator | Custom stepper from scratch | Adapt existing OnboardingStepper component |
Already built, same visual style, just update step count and labels |
| Form validation | Custom validation logic | react-hook-form + zod (per-step schemas) | Established project pattern, handles error display |
| Server state | Custom fetch/cache | TanStack Query useTemplates, useDeployTemplate hooks |
Established pattern, handles loading/error states |
| Tool chip UI | Custom chip component | Badge + X button (same as AgentDesigner tool_assignments section) | Already implemented, copy the pattern |
| Channel selection | Custom channel list | useChannelConnections hook + checkboxes | Hook already exists in queries.ts |
Common Pitfalls
Pitfall 1: searchParams is a Promise in Next.js 15+ (project uses Next.js 16)
What goes wrong: Accessing searchParams.step directly causes a build error or runtime warning.
Why it happens: Next.js 15 made searchParams a Promise in page components. Confirmed in the project's STATE.md and existing onboarding page.
How to avoid: In server components, await searchParams. In client components, use useSearchParams() from next/navigation.
Warning signs: TypeScript errors on .step access without await.
Pitfall 2: Wizard state lost on browser refresh
What goes wrong: User refreshes midway through wizard, loses all entered data. Why it happens: React useState is ephemeral. How to avoid: For the current project's needs (5-step wizard completing in < 5 minutes), this is acceptable UX. Add a warning comment in the component. Do NOT try to serialize wizard state into URL params (too complex). If the user refreshes, they restart — this is fine. Warning signs: Temptation to serialize complex state to sessionStorage or URL.
Pitfall 3: Template deploy creates inactive agent
What goes wrong: Deployed agent is inactive by default, not responding in channels.
Why it happens: is_active defaults to True in the ORM, but code might explicitly set False.
How to avoid: Template deploy always creates agents with is_active=True. The phase 3 decision ("agent goes live automatically, is_active true by default") applies here.
Pitfall 4: Wizard channel step — no connected channels
What goes wrong: User reaches the Channels step but the tenant has no connected channels yet. Why it happens: Channel connection (Slack/WhatsApp) is a separate onboarding step. How to avoid: The Channels step should handle the empty state gracefully — show a message "No channels connected yet. Your employee will be deployed and can be assigned to channels later." Allow the step to be skipped with no channels selected.
Pitfall 5: Template gallery visible to customer_operator
What goes wrong: Operators can browse templates but cannot deploy (403 on the deploy endpoint). Confusing UX. Why it happens: EMPL-04 restricts wizard and template deployment to platform_admin and customer_admin. How to avoid: Check caller role before rendering the "New Employee" button (same RBAC check already used for nav items). The three-option screen should only be reachable by admins. If an operator somehow reaches it, the deploy API will return 403 and the UI should handle that error.
Pitfall 6: System prompt builder missing AI transparency clause
What goes wrong: Wizard-generated system prompts omit the mandatory AI disclosure clause. Why it happens: The disclosure is hardcoded into the default system prompt template but easy to forget when building the auto-generator. How to avoid: The system prompt builder function always appends: "When directly asked if you are an AI, always disclose that you are an AI assistant." This is a non-negotiable per Phase 1 design decision.
Code Examples
Existing stepper pattern (adapt for 5-step wizard)
The OnboardingStepper component at packages/portal/components/onboarding-stepper.tsx accepts currentStep: number and a StepInfo[] array. For the employee wizard, create EmployeeWizardStepper with the same structure but 5 steps:
// Source: packages/portal/components/onboarding-stepper.tsx (existing)
export const WIZARD_STEPS: StepInfo[] = [
{ number: 1, label: "Role", description: "What will they do?" },
{ number: 2, label: "Persona", description: "How will they behave?" },
{ number: 3, label: "Tools", description: "What can they use?" },
{ number: 4, label: "Channels", description: "Where will they work?" },
{ number: 5, label: "Escalation", description: "When to hand off?" },
];
// + step 6 (Review) is not a numbered wizard step — it's the final deploy screen
Existing createAgent mutation (wizard and template deploy both use this)
// Source: packages/portal/lib/queries.ts (existing)
const createAgent = useCreateAgent();
await createAgent.mutateAsync({
tenantId: tenantId,
data: {
name: wizardData.name,
role: wizardData.roleTitle,
persona: wizardData.persona,
system_prompt: buildSystemPrompt(wizardData), // auto-generated
model_preference: "quality",
tool_assignments: wizardData.tool_assignments,
escalation_rules: wizardData.escalation_rules,
is_active: true,
},
});
Alembic migration pattern for seed data (migration 007)
# Source: migrations/versions/006_rbac_roles.py pattern
revision: str = "007"
down_revision: Union[str, None] = "006"
def upgrade() -> None:
op.create_table(
"agent_templates",
sa.Column("id", postgresql.UUID(as_uuid=True), primary_key=True, ...),
sa.Column("name", sa.String(255), nullable=False),
...
)
# Seed data INSERT
op.execute("""
INSERT INTO agent_templates (id, name, role, description, ...) VALUES
(gen_random_uuid(), 'Customer Support Rep', 'Customer Support Representative', ...),
...
""")
Channel auto-assignment on template deploy
# POST /api/portal/templates/{template_id}/deploy
async def deploy_template(template_id, body, caller, session):
template = await get_template_or_404(template_id, session)
# Create agent (snapshot of template)
agent = Agent(
tenant_id=body.tenant_id,
name=template.name,
role=template.role,
persona=template.persona,
system_prompt=template.system_prompt,
model_preference=template.model_preference,
tool_assignments=template.tool_assignments,
escalation_rules=template.escalation_rules,
is_active=True,
)
session.add(agent)
await session.commit()
# Note: channel routing is tenant-scoped, not per-agent in v1.
# Agent responds to all channels connected to the tenant automatically.
return AgentResponse.from_orm(agent)
State of the Art
| Old Approach | Current Approach | When Changed | Impact |
|---|---|---|---|
| zodResolver from @hookform/resolvers | standardSchemaResolver | hookform/resolvers v5 (project already uses this) | Must use standardSchemaResolver, not zodResolver |
searchParams as sync object |
searchParams as Promise |
Next.js 15+ (project on 16.2.1) | Must await searchParams in server components, use useSearchParams() in client components |
params as sync object |
params as Promise |
Next.js 15+ (project on 16.2.1) | Must use(params) in client components (see existing /agents/[id]/page.tsx) |
| middleware.ts | proxy.ts | Next.js 16 (renamed) | Project already uses proxy.ts |
Open Questions
-
Wizard Channels Step — what exactly gets "assigned"?
- What we know: The deploy decision says "auto-assigns to all connected channels." The existing agent routing is tenant-scoped — all tenant agents share the channel and respond by agent selection logic.
- What's unclear: Is there a per-agent channel assignment in the ORM/routing layer, or is it purely tenant-level?
- Recommendation: Audit the orchestrator routing logic before planning. If per-agent channel assignment doesn't exist in the DB schema, the Channels step in the wizard becomes an informational step ("Your employee will be active in these channels") rather than a configuration step. Do not add a channel-agent join table in this phase.
-
Template CRUD for platform admin — new portal page or inline?
- What we know: Templates are stored as DB seed data. Platform admin should be able to add/edit.
- What's unclear: Context says "platform admin can add/edit templates via portal" but gives no UI spec.
- Recommendation: For Phase 5, templates are read-only via seed data. Full template CRUD UI can be a v2 feature. The seed migration covers the 7 V1 templates.
-
Wizard "Deploy Employee" step — return URL after success?
- What we know: Current createAgent mutations redirect to
/agentson success. - Recommendation: Redirect to
/agents/{newAgent.id}?tenant={tenantId}(the edit page) to confirm deployment and offer immediate customization. This satisfies EMPL-05 (agent appears in Agent Designer).
- What we know: Current createAgent mutations redirect to
Validation Architecture
Test Framework
| Property | Value |
|---|---|
| Framework | pytest 8.x + pytest-asyncio + httpx |
| Config file | pyproject.toml (root) |
| Quick run command | pytest tests/unit -x |
| Full suite command | pytest tests/ -x |
Phase Requirements → Test Map
| Req ID | Behavior | Test Type | Automated Command | File Exists? |
|---|---|---|---|---|
| EMPL-01 | Wizard creates agent with auto-generated system_prompt | unit | pytest tests/unit/test_system_prompt_builder.py -x |
❌ Wave 0 |
| EMPL-01 | Wizard agent creation hits POST /tenants/{tid}/agents (existing endpoint) | integration | pytest tests/integration/test_portal_agents.py -x |
✅ existing |
| EMPL-02 | GET /api/portal/templates returns template list | integration | pytest tests/integration/test_templates.py -x |
❌ Wave 0 |
| EMPL-02 | Template deploy creates independent agent snapshot | integration | pytest tests/integration/test_templates.py::test_deploy_template -x |
❌ Wave 0 |
| EMPL-03 | Deployed agent is_active=True and correct fields from template | integration | pytest tests/integration/test_templates.py::test_deployed_agent_is_active -x |
❌ Wave 0 |
| EMPL-04 | Template deploy blocked for customer_operator (403) | integration | pytest tests/integration/test_templates.py::test_deploy_template_rbac -x |
❌ Wave 0 |
| EMPL-04 | Wizard agent creation blocked for customer_operator (403) | integration | pytest tests/integration/test_portal_rbac.py -x |
✅ existing |
| EMPL-05 | Wizard-created agent has correct fields (accessible via GET /agents/{id}) | integration | pytest tests/integration/test_portal_agents.py -x |
✅ existing |
Sampling Rate
- Per task commit:
pytest tests/unit -x - Per wave merge:
pytest tests/ -x - Phase gate: Full suite green before
/gsd:verify-work
Wave 0 Gaps
tests/unit/test_system_prompt_builder.py— covers EMPL-01 (system prompt construction)tests/integration/test_templates.py— covers EMPL-02, EMPL-03, EMPL-04
(Frontend wizard UX is manual-only: no automated test framework for Next.js components is configured in this project)
Sources
Primary (HIGH confidence)
/home/adelorenzo/repos/konstruct/packages/portal/AGENTS.md— Next.js version caveat; confirmed Next.js 16.2.1, React 19.2.4/home/adelorenzo/repos/konstruct/packages/portal/node_modules/next/dist/docs/01-app/03-api-reference/04-functions/use-search-params.md— searchParams is read-only URLSearchParams in client components/home/adelorenzo/repos/konstruct/packages/portal/node_modules/next/dist/docs/01-app/03-api-reference/04-functions/use-router.md— router.push/replace API confirmed/home/adelorenzo/repos/konstruct/packages/portal/node_modules/next/dist/docs/01-app/02-guides/forms.md— Server Actions form patterns (not used for this phase — TanStack Query pattern preferred per project conventions)/home/adelorenzo/repos/konstruct/packages/portal/components/onboarding-stepper.tsx— OnboardingStepper pattern to reuse/home/adelorenzo/repos/konstruct/packages/portal/app/(dashboard)/onboarding/page.tsx—searchParams: Promise<{...}>server component pattern confirmed/home/adelorenzo/repos/konstruct/packages/shared/shared/models/tenant.py— Agent ORM model fields confirmed/home/adelorenzo/repos/konstruct/packages/shared/shared/api/portal.py—require_tenant_adminguard on POST /agents confirmed/home/adelorenzo/repos/konstruct/.planning/STATE.md— Project-wide architectural decisions
Secondary (MEDIUM confidence)
/home/adelorenzo/repos/konstruct/.planning/phases/05-employee-design/05-CONTEXT.md— User decisions (authoritative for this phase)
Metadata
Confidence breakdown:
- Standard stack: HIGH — all libraries verified from existing source files
- Architecture: HIGH — patterns derived from existing onboarding wizard and agent designer code in the project
- Pitfalls: HIGH — searchParams/params as Promise pitfalls confirmed from Next.js 16 docs; other pitfalls from existing STATE.md decisions
- System prompt builder: HIGH — pure function, no external dependencies
- Template DB design: MEDIUM — dedicated table recommendation is reasoned but not verified against a specific external source
Research date: 2026-03-24 Valid until: 2026-04-24 (stable stack — Next.js 16, no breaking changes expected)