docs(05-employee-design): create phase plan — 3 plans in 3 waves
This commit is contained in:
257
.planning/phases/05-employee-design/05-01-PLAN.md
Normal file
257
.planning/phases/05-employee-design/05-01-PLAN.md
Normal file
@@ -0,0 +1,257 @@
|
||||
---
|
||||
phase: 05-employee-design
|
||||
plan: 01
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- packages/shared/shared/models/tenant.py
|
||||
- packages/shared/shared/api/templates.py
|
||||
- packages/shared/shared/prompts/system_prompt_builder.py
|
||||
- migrations/versions/007_agent_templates.py
|
||||
- packages/gateway/main.py
|
||||
- tests/unit/test_system_prompt_builder.py
|
||||
- tests/integration/test_templates.py
|
||||
autonomous: true
|
||||
requirements: [EMPL-02, EMPL-03, EMPL-04]
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "GET /api/portal/templates returns a list of 7+ pre-built agent templates"
|
||||
- "POST /api/portal/templates/{id}/deploy creates an independent agent snapshot with is_active=True"
|
||||
- "Template deploy is blocked for customer_operator (403)"
|
||||
- "System prompt builder produces a coherent prompt including AI transparency clause"
|
||||
artifacts:
|
||||
- path: "packages/shared/shared/models/tenant.py"
|
||||
provides: "AgentTemplate ORM model"
|
||||
contains: "class AgentTemplate"
|
||||
- path: "packages/shared/shared/api/templates.py"
|
||||
provides: "Template list + deploy endpoints"
|
||||
exports: ["templates_router"]
|
||||
- path: "packages/shared/shared/prompts/system_prompt_builder.py"
|
||||
provides: "System prompt auto-generation from wizard inputs"
|
||||
exports: ["build_system_prompt"]
|
||||
- path: "migrations/versions/007_agent_templates.py"
|
||||
provides: "agent_templates table with 7 seed templates"
|
||||
contains: "agent_templates"
|
||||
- path: "tests/unit/test_system_prompt_builder.py"
|
||||
provides: "Unit tests for prompt builder"
|
||||
- path: "tests/integration/test_templates.py"
|
||||
provides: "Integration tests for template API"
|
||||
key_links:
|
||||
- from: "packages/shared/shared/api/templates.py"
|
||||
to: "packages/shared/shared/models/tenant.py"
|
||||
via: "AgentTemplate ORM model import"
|
||||
pattern: "from shared\\.models\\.tenant import.*AgentTemplate"
|
||||
- from: "packages/shared/shared/api/templates.py"
|
||||
to: "packages/shared/shared/models/tenant.py"
|
||||
via: "Agent ORM model for deploy snapshot"
|
||||
pattern: "Agent\\("
|
||||
- from: "packages/gateway/main.py"
|
||||
to: "packages/shared/shared/api/templates.py"
|
||||
via: "Router mount"
|
||||
pattern: "templates_router"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Backend foundation for the Employee Design phase: AgentTemplate ORM model, database migration with 7 seed templates, template list + deploy API endpoints, system prompt builder function, and comprehensive tests.
|
||||
|
||||
Purpose: Provide the API layer that the frontend template gallery and wizard will consume. Templates are global (not tenant-scoped), readable by all authenticated users, deployable by tenant admins only.
|
||||
Output: Working API at /api/portal/templates (GET list, GET detail, POST deploy), system prompt builder module, migration 007, unit + integration tests.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@/home/adelorenzo/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@/home/adelorenzo/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.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
|
||||
|
||||
<interfaces>
|
||||
<!-- Key types and contracts the executor needs. Extracted from codebase. -->
|
||||
|
||||
From packages/shared/shared/models/tenant.py:
|
||||
```python
|
||||
class Base(DeclarativeBase):
|
||||
pass
|
||||
|
||||
class Agent(Base):
|
||||
__tablename__ = "agents"
|
||||
id: Mapped[uuid.UUID]
|
||||
tenant_id: Mapped[uuid.UUID] # FK to tenants.id
|
||||
name: Mapped[str]
|
||||
role: Mapped[str]
|
||||
persona: Mapped[str]
|
||||
system_prompt: Mapped[str]
|
||||
model_preference: Mapped[str] # quality | balanced | economy | local
|
||||
tool_assignments: Mapped[list[Any]] # JSON
|
||||
escalation_rules: Mapped[list[Any]] # JSON
|
||||
escalation_assignee: Mapped[str | None]
|
||||
natural_language_escalation: Mapped[bool]
|
||||
is_active: Mapped[bool] # default True
|
||||
budget_limit_usd: Mapped[float | None]
|
||||
created_at: Mapped[datetime]
|
||||
updated_at: Mapped[datetime]
|
||||
```
|
||||
|
||||
From packages/shared/shared/api/portal.py:
|
||||
```python
|
||||
portal_router = APIRouter(prefix="/api/portal", tags=["portal"])
|
||||
|
||||
class AgentCreate(BaseModel):
|
||||
name: str
|
||||
role: str
|
||||
persona: str = ""
|
||||
system_prompt: str = ""
|
||||
model_preference: str = "quality"
|
||||
tool_assignments: list[str] = []
|
||||
escalation_rules: list[dict] = []
|
||||
is_active: bool = True
|
||||
|
||||
class AgentResponse(BaseModel):
|
||||
id: str; tenant_id: str; name: str; role: str; persona: str
|
||||
system_prompt: str; model_preference: str; tool_assignments: list[str]
|
||||
escalation_rules: list[dict]; is_active: bool; budget_limit_usd: float | None
|
||||
created_at: datetime; updated_at: datetime
|
||||
```
|
||||
|
||||
From packages/shared/shared/api/rbac.py:
|
||||
```python
|
||||
async def require_platform_admin(caller: PortalCaller) -> PortalCaller
|
||||
async def require_tenant_admin(caller: PortalCaller) -> PortalCaller
|
||||
async def require_tenant_member(caller: PortalCaller) -> PortalCaller
|
||||
```
|
||||
|
||||
From packages/gateway/main.py (router mounting pattern):
|
||||
```python
|
||||
from shared.api.portal import portal_router
|
||||
app.include_router(portal_router)
|
||||
# All Phase 3 routers mounted similarly
|
||||
```
|
||||
|
||||
Latest migration: 006_rbac_roles.py (next is 007)
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto" tdd="true">
|
||||
<name>Task 1: AgentTemplate model, migration 007, system prompt builder, and tests</name>
|
||||
<files>
|
||||
packages/shared/shared/models/tenant.py,
|
||||
migrations/versions/007_agent_templates.py,
|
||||
packages/shared/shared/prompts/__init__.py,
|
||||
packages/shared/shared/prompts/system_prompt_builder.py,
|
||||
tests/unit/test_system_prompt_builder.py
|
||||
</files>
|
||||
<behavior>
|
||||
- build_system_prompt({name: "Mara", role: "Customer Support", persona: "Friendly and helpful", tool_assignments: ["knowledge_base_search"], escalation_rules: [{"condition": "billing_dispute AND attempts > 2", "action": "handoff_human"}]}) produces a string containing "You are Mara", "Customer Support", "Friendly and helpful", "knowledge_base_search", the escalation rule text, AND the AI transparency clause "When directly asked if you are an AI, always disclose that you are an AI assistant."
|
||||
- build_system_prompt with empty tools and empty escalation_rules omits those sections (no "tools:" or "Escalation" text)
|
||||
- build_system_prompt with only name and role still produces valid prompt with AI transparency clause
|
||||
</behavior>
|
||||
<action>
|
||||
1. Add `AgentTemplate` ORM model to `packages/shared/shared/models/tenant.py`:
|
||||
- NOT tenant-scoped (no tenant_id, no RLS)
|
||||
- Fields: id (UUID PK), name (String 255), role (String 255), description (Text, shown in card preview), category (String 100, default "general"), persona (Text), system_prompt (Text), model_preference (String 50, default "quality"), tool_assignments (JSON, default []), escalation_rules (JSON, default []), is_active (Boolean, default True), sort_order (Integer, default 0), created_at (DateTime tz, server_default now())
|
||||
- Add `__repr__` method
|
||||
|
||||
2. Create migration `007_agent_templates.py`:
|
||||
- down_revision = "006"
|
||||
- Create `agent_templates` table matching the ORM model
|
||||
- Seed 7 templates with INSERT. Each template needs: name, role, description (2-3 sentences for the card preview), category, persona (paragraph describing communication style), system_prompt (full system prompt with AI transparency clause), model_preference "quality", tool_assignments (JSON array of relevant tool names), escalation_rules (JSON array of {condition, action} objects)
|
||||
- Templates:
|
||||
a. Customer Support Rep — category "support", tools: knowledge_base_search, zendesk_ticket_lookup, zendesk_ticket_create. Escalation: billing_dispute AND attempts > 2 -> handoff_human, sentiment < -0.7 -> handoff_human
|
||||
b. Sales Assistant — category "sales", tools: knowledge_base_search, calendar_book. Escalation: pricing_negotiation AND attempts > 3 -> handoff_human
|
||||
c. Office Manager — category "operations", tools: knowledge_base_search, calendar_book. Escalation: hr_complaint -> handoff_human
|
||||
d. Project Coordinator — category "operations", tools: knowledge_base_search. Escalation: deadline_missed -> handoff_human
|
||||
e. Financial Manager — category "finance", tools: knowledge_base_search. Escalation: large_transaction AND amount > threshold -> handoff_human
|
||||
f. Controller — category "finance", tools: knowledge_base_search. Escalation: budget_exceeded -> handoff_human
|
||||
g. Accountant — category "finance", tools: knowledge_base_search. Escalation: invoice_discrepancy AND amount > threshold -> handoff_human
|
||||
|
||||
3. Create `packages/shared/shared/prompts/__init__.py` (empty) and `system_prompt_builder.py`:
|
||||
- Function `build_system_prompt(name: str, role: str, persona: str = "", tool_assignments: list[str] | None = None, escalation_rules: list[dict] | None = None) -> str`
|
||||
- Assembles: "You are {name}, {role}.\n\n{persona}" + optional tools section + optional escalation section + ALWAYS the AI transparency clause
|
||||
- AI transparency clause (non-negotiable, per Phase 1 decision): "\n\nWhen directly asked if you are an AI, always disclose that you are an AI assistant."
|
||||
|
||||
4. Write unit tests in `tests/unit/test_system_prompt_builder.py`:
|
||||
- Test full prompt with all fields populated (name, role, persona, tools, escalation)
|
||||
- Test minimal prompt (name + role only) still includes AI clause
|
||||
- Test empty tools/escalation omit those sections
|
||||
- Test AI transparency clause is always present
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/adelorenzo/repos/konstruct && python -m pytest tests/unit/test_system_prompt_builder.py -x -v</automated>
|
||||
</verify>
|
||||
<done>AgentTemplate ORM model exists in tenant.py, migration 007 creates table with 7 seed templates, build_system_prompt function passes all unit tests including AI transparency clause verification</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Template API endpoints (list, detail, deploy) with RBAC and integration tests</name>
|
||||
<files>
|
||||
packages/shared/shared/api/templates.py,
|
||||
packages/gateway/main.py,
|
||||
tests/integration/test_templates.py
|
||||
</files>
|
||||
<action>
|
||||
1. Create `packages/shared/shared/api/templates.py` with a new `templates_router = APIRouter(prefix="/api/portal", tags=["templates"])`:
|
||||
|
||||
Pydantic schemas:
|
||||
- `TemplateResponse(BaseModel)`: id (str), name, role, description, category, persona, system_prompt, model_preference, tool_assignments (list[str]), escalation_rules (list[dict]), is_active (bool), sort_order (int), created_at (datetime)
|
||||
- `TemplateDeployRequest(BaseModel)`: tenant_id (str, UUID format)
|
||||
- `TemplateDeployResponse(BaseModel)`: agent (AgentResponse from portal.py) — the newly created agent
|
||||
|
||||
Endpoints:
|
||||
a. `GET /api/portal/templates` — returns list[TemplateResponse]. Guard: `require_tenant_member` (any authenticated portal user can browse). Query: `SELECT * FROM agent_templates WHERE is_active = True ORDER BY sort_order, name`. No RLS needed (templates are global).
|
||||
b. `GET /api/portal/templates/{template_id}` — returns TemplateResponse. Guard: `require_tenant_member`. 404 if not found or inactive.
|
||||
c. `POST /api/portal/templates/{template_id}/deploy` — Guard: `require_tenant_admin` (per EMPL-04). Body: TemplateDeployRequest with tenant_id.
|
||||
- Fetch template by ID (404 if not found)
|
||||
- Set RLS context to body.tenant_id (same pattern as create_agent in portal.py)
|
||||
- Create Agent from template fields: name, role, persona, system_prompt, model_preference, tool_assignments, escalation_rules, is_active=True
|
||||
- Commit and return TemplateDeployResponse with the new agent
|
||||
|
||||
2. Mount `templates_router` in `packages/gateway/main.py` alongside existing routers:
|
||||
```python
|
||||
from shared.api.templates import templates_router
|
||||
app.include_router(templates_router)
|
||||
```
|
||||
|
||||
3. Write integration tests in `tests/integration/test_templates.py`:
|
||||
- `test_list_templates` — GET returns 200 with 7+ templates (seeded by migration)
|
||||
- `test_get_template_detail` — GET single template returns correct fields
|
||||
- `test_deploy_template` — POST deploy returns 201 with new agent, agent has is_active=True, agent fields match template (snapshot)
|
||||
- `test_deploy_template_rbac` — POST deploy as customer_operator returns 403
|
||||
- `test_deploy_template_not_found` — POST deploy with invalid UUID returns 404
|
||||
- Follow the existing test pattern from `tests/integration/test_portal_rbac.py` for RBAC header injection (X-Portal-User-Id, X-Portal-User-Role, X-Portal-Tenant-Id headers)
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/adelorenzo/repos/konstruct && python -m pytest tests/integration/test_templates.py -x -v</automated>
|
||||
</verify>
|
||||
<done>GET /api/portal/templates returns 7 seeded templates, POST deploy creates an independent agent snapshot with is_active=True, customer_operator gets 403 on deploy, all integration tests pass</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
1. `pytest tests/unit/test_system_prompt_builder.py -x` passes
|
||||
2. `pytest tests/integration/test_templates.py -x` passes
|
||||
3. `pytest tests/ -x` full suite still green (no regressions)
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- AgentTemplate table exists with 7 seed templates
|
||||
- GET /api/portal/templates returns all active templates
|
||||
- POST /api/portal/templates/{id}/deploy creates agent snapshot with is_active=True
|
||||
- Deploy blocked for customer_operator (403)
|
||||
- System prompt builder produces valid prompts with AI transparency clause
|
||||
- All unit and integration tests pass
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/05-employee-design/05-01-SUMMARY.md`
|
||||
</output>
|
||||
345
.planning/phases/05-employee-design/05-02-PLAN.md
Normal file
345
.planning/phases/05-employee-design/05-02-PLAN.md
Normal file
@@ -0,0 +1,345 @@
|
||||
---
|
||||
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"
|
||||
---
|
||||
|
||||
<objective>
|
||||
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.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@/home/adelorenzo/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@/home/adelorenzo/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.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
|
||||
|
||||
<interfaces>
|
||||
<!-- Key types and contracts from Plan 01 that this plan depends on -->
|
||||
|
||||
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<Agent, Error, { tenantId: string; data: AgentCreate }>
|
||||
export function useChannelConnections(tenantId: string): UseQueryResult<ChannelConnection[]>
|
||||
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<AgentDesignerValues>; tenants: Tenant[]; onSubmit: (data: AgentDesignerValues) => Promise<void>; 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 })
|
||||
```
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Three-option entry screen, Advanced page, TypeScript types, TanStack hooks, and system prompt builder</name>
|
||||
<files>
|
||||
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
|
||||
</files>
|
||||
<action>
|
||||
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<Template[]>` — GET /api/portal/templates
|
||||
- `useDeployTemplate(): UseMutationResult<TemplateDeployResponse, Error, { templateId: string; tenantId: string }>` — 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
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/adelorenzo/repos/konstruct/packages/portal && npx next build 2>&1 | tail -20</automated>
|
||||
</verify>
|
||||
<done>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.</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Template gallery page and wizard with all step components</name>
|
||||
<files>
|
||||
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
|
||||
</files>
|
||||
<action>
|
||||
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 `<TemplateGallery tenantId={tenantId} />`
|
||||
- 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<Partial<WizardData>>({})` 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<WizardData>) => { 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<WizardData>; onNext: (updates: Partial<WizardData>) => 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 `<EmployeeWizard tenantId={tenantId} initialStep={parseInt(step || "1")} />`
|
||||
- If no tenant selected, show tenant selector
|
||||
</action>
|
||||
<verify>
|
||||
<automated>cd /home/adelorenzo/repos/konstruct/packages/portal && npx next build 2>&1 | tail -20</automated>
|
||||
</verify>
|
||||
<done>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).</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
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)
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- 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
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/05-employee-design/05-02-SUMMARY.md`
|
||||
</output>
|
||||
97
.planning/phases/05-employee-design/05-03-PLAN.md
Normal file
97
.planning/phases/05-employee-design/05-03-PLAN.md
Normal file
@@ -0,0 +1,97 @@
|
||||
---
|
||||
phase: 05-employee-design
|
||||
plan: 03
|
||||
type: execute
|
||||
wave: 3
|
||||
depends_on: ["05-02"]
|
||||
files_modified: []
|
||||
autonomous: false
|
||||
requirements: [EMPL-01, EMPL-02, EMPL-03, EMPL-04, EMPL-05]
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "All three creation paths work end-to-end"
|
||||
- "Template-deployed agents respond in channels"
|
||||
- "Wizard-created agents are editable in Agent Designer"
|
||||
artifacts: []
|
||||
key_links: []
|
||||
---
|
||||
|
||||
<objective>
|
||||
Human verification of all three employee creation paths: template deployment, guided wizard, and Advanced Agent Designer.
|
||||
|
||||
Purpose: Confirm that the complete Employee Design feature works visually and functionally before marking Phase 5 complete.
|
||||
Output: Human approval or issue list for gap closure.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@/home/adelorenzo/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@/home/adelorenzo/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/phases/05-employee-design/05-CONTEXT.md
|
||||
@.planning/phases/05-employee-design/05-01-SUMMARY.md
|
||||
@.planning/phases/05-employee-design/05-02-SUMMARY.md
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="checkpoint:human-verify" gate="blocking">
|
||||
<name>Task 1: Verify all three employee creation paths</name>
|
||||
<files></files>
|
||||
<action>
|
||||
Human verifies the complete three-path AI employee creation system: template gallery with one-click deploy, 5-step guided wizard, and Advanced Agent Designer mode.
|
||||
|
||||
Prerequisites: Docker Compose stack running (docker compose up -d), portal at http://localhost:3000, logged in as platform_admin or customer_admin.
|
||||
|
||||
1. **Entry Screen**: Navigate to Employees list, click "New Employee" (or go to /agents/new)
|
||||
- Verify three cards appear: Templates (recommended), Guided Setup, Advanced
|
||||
- Verify Templates card has emphasis/recommended styling
|
||||
|
||||
2. **Template Path**: Click "Browse Templates"
|
||||
- Verify 7 template cards appear in a grid (Customer Support Rep, Sales Assistant, Office Manager, Project Coordinator, Financial Manager, Controller, Accountant)
|
||||
- Click "Preview" on Customer Support Rep — verify it shows persona, tools, escalation rules
|
||||
- Click "Deploy" on any template — verify agent is created and you are redirected to the agent edit page
|
||||
- Verify the deployed agent appears in the Employees list with is_active=true
|
||||
|
||||
3. **Wizard Path**: Go back to /agents/new, click "Start Setup"
|
||||
- Step 1 (Role): Enter name and role title, click Next
|
||||
- Step 2 (Persona): Enter a persona description, click Next
|
||||
- Step 3 (Tools): Select one or more tools, click Next
|
||||
- Step 4 (Channels): Verify connected channels are shown (or empty state message), click Next
|
||||
- Step 5 (Escalation): Add an escalation rule, click Next
|
||||
- Review: Verify all entered data is displayed in summary, system prompt is NOT shown
|
||||
- Click "Deploy Employee" — verify agent is created and redirected to edit page
|
||||
- Open the agent in Agent Designer — verify system_prompt was auto-generated (contains AI transparency clause)
|
||||
|
||||
4. **Advanced Path**: Go back to /agents/new, click "Open Designer"
|
||||
- Verify the full Agent Designer form appears (same as before Phase 5)
|
||||
- All fields editable including system_prompt
|
||||
|
||||
5. **RBAC**: Log in as customer_operator
|
||||
- Verify "New Employee" button is NOT visible or routes to 403
|
||||
- Verify /agents/new entry screen is not accessible to operators
|
||||
</action>
|
||||
<verify>Human approval</verify>
|
||||
<done>Human confirms all three creation paths work correctly, RBAC enforced, system prompt auto-generated properly</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
Human confirms all three creation paths work visually and functionally.
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- Human approves all three paths (template, wizard, advanced)
|
||||
- Template deploy creates working agent
|
||||
- Wizard generates correct system prompt
|
||||
- RBAC prevents operator access to creation paths
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/05-employee-design/05-03-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user