Summary
Extend FormContent to support wizard-style inputs (text, single_choice, multiple_choice), then migrate the Deep Research architecture generation feature to use ChatMessage + FORM artifacts instead of StakworkRun.result/feedback.
This unifies the pattern: when AI wants user input, it creates a FORM artifact - same rendering in task chat and architecture generation.
Key Decisions
- Storage: Add
ChatMessage relation directly to Feature (new schema relation)
- Migration: No data migration - new system only for new generations
- Rollout: Feature flag
NEXT_PUBLIC_FEATURE_CHAT_ARCHITECTURE
Implementation Plan
Phase 1: Extend FormContent Types
File: src/lib/chat.ts
// New input types
type FormInputType = "text" | "single_choice" | "multiple_choice";
interface FormInput {
id: string;
question: string;
type: FormInputType;
options?: string[];
required?: boolean;
placeholder?: string;
}
// Extend FormContent (backwards compatible)
interface FormContent {
actionText: string; // Existing - intro/title
webhook: string; // Existing - callback URL
options: Option[]; // Existing - button options
// New wizard fields (optional for backwards compat)
inputs?: FormInput[];
submitLabel?: string;
showReview?: boolean;
allowCustomText?: boolean;
}
// Response structure for wizard submissions
interface FormResponse {
answers: Record<string, { selections?: string[]; text?: string }>;
formatted: string; // "Q: ... A: ..." format
}
Phase 2: Create Shared WizardForm Component
New file: src/components/ui/wizard-form/index.tsx
Extract wizard logic from ClarifyingQuestionsPreview into a reusable component:
- Props:
inputs: FormInput[], onSubmit: (response: FormResponse) => void, isLoading?: boolean
- Features: step navigation, progress bar, review step, text/choice inputs
- Reuse existing styling and UX patterns from
ClarifyingQuestionsPreview
Phase 3: Extend FormArtifact Component
File: src/app/w/[slug]/task/[...taskParams]/artifacts/form.tsx
Detect wizard-style forms and render appropriately:
export function FormArtifact({ messageId, artifact, onAction, ... }) {
const content = artifact.content as FormContent;
const hasWizardInputs = content.inputs && content.inputs.length > 0;
if (hasWizardInputs) {
return (
<WizardForm
inputs={content.inputs}
introText={content.actionText}
onSubmit={(response) => onAction(messageId, response, content.webhook)}
isLoading={isDisabled}
/>
);
}
// Existing button-style form rendering
return <ButtonForm ... />;
}
Phase 4: Database Schema Changes
File: prisma/schema.prisma
Add ChatMessage relation to Feature:
model Feature {
// ... existing fields
// Architecture generation conversation
architectureMessages ChatMessage[] @relation("FeatureArchitectureMessages")
}
model ChatMessage {
// ... existing fields
// Optional: link to feature for architecture conversations
featureId String? @map("feature_id")
feature Feature? @relation("FeatureArchitectureMessages", fields: [featureId], references: [id])
}
Run: npx prisma migrate dev --name add-feature-architecture-messages
Phase 5: Create Architecture Conversation API
New file: src/app/api/features/[featureId]/architecture/messages/route.ts
- GET - fetch architecture conversation messages
- POST - create new message (user response to wizard)
New file: src/services/architecture-conversation.ts
getArchitectureMessages(featureId)
createArchitectureMessage(featureId, params)
submitWizardResponse(messageId, response)
Phase 6: Update Stakwork Webhook Handler
File: src/app/api/webhook/stakwork/response/route.ts
When Stakwork returns clarifying questions:
- Detect
tool_use: "ask_clarifying_questions" response
- Transform to
FormContent with inputs array
- Create
ChatMessage with role: ASSISTANT and FORM artifact
- Link to Feature via
featureId
- Broadcast via Pusher
Phase 7: Update AITextareaSection
File: src/components/features/AITextareaSection.tsx
const useChatBasedArchitecture = useFeatureFlag('CHAT_ARCHITECTURE');
if (useChatBasedArchitecture) {
// Use new ChatMessage-based flow
// Fetch messages via useArchitectureMessages(featureId)
} else {
// Existing StakworkRun-based flow
}
New hook: src/hooks/useArchitectureMessages.ts
Phase 8: Add Feature Flag
File: src/lib/feature-flags.ts
case 'CHAT_ARCHITECTURE':
return process.env.NEXT_PUBLIC_FEATURE_CHAT_ARCHITECTURE === 'true';
Files Summary
Files to Modify
| File |
Change |
src/lib/chat.ts |
Add FormInput, FormInputType, FormResponse, extend FormContent |
prisma/schema.prisma |
Add Feature ↔ ChatMessage relation |
src/app/w/[slug]/task/[...taskParams]/artifacts/form.tsx |
Detect wizard forms, render WizardForm |
src/components/features/AITextareaSection.tsx |
Feature flag, switch to chat-based flow |
src/lib/feature-flags.ts |
Add CHAT_ARCHITECTURE flag |
src/app/api/webhook/stakwork/response/route.ts |
Transform questions to FORM artifacts |
New Files to Create
| File |
Purpose |
src/components/ui/wizard-form/index.tsx |
Shared wizard form component |
src/app/api/features/[featureId]/architecture/messages/route.ts |
API for architecture messages |
src/services/architecture-conversation.ts |
Business logic for architecture conversations |
src/hooks/useArchitectureMessages.ts |
Hook for fetching/subscribing to messages |
Implementation Order
- Types - Extend FormContent in
src/lib/chat.ts
- Component - Create WizardForm in
src/components/ui/wizard-form/
- FormArtifact - Extend to detect and render wizard forms
- Schema - Add Feature ↔ ChatMessage relation, run migration
- Feature Flag - Add CHAT_ARCHITECTURE flag
- API/Service - Create architecture conversation endpoints
- Webhook - Update Stakwork handler to create FORM artifacts
- Integration - Update AITextareaSection with feature flag
- Testing - Verify both flows work correctly
Summary
Extend
FormContentto support wizard-style inputs (text, single_choice, multiple_choice), then migrate the Deep Research architecture generation feature to useChatMessage+FORMartifacts instead ofStakworkRun.result/feedback.This unifies the pattern: when AI wants user input, it creates a FORM artifact - same rendering in task chat and architecture generation.
Key Decisions
ChatMessagerelation directly toFeature(new schema relation)NEXT_PUBLIC_FEATURE_CHAT_ARCHITECTUREImplementation Plan
Phase 1: Extend FormContent Types
File:
src/lib/chat.tsPhase 2: Create Shared WizardForm Component
New file:
src/components/ui/wizard-form/index.tsxExtract wizard logic from
ClarifyingQuestionsPreviewinto a reusable component:inputs: FormInput[],onSubmit: (response: FormResponse) => void,isLoading?: booleanClarifyingQuestionsPreviewPhase 3: Extend FormArtifact Component
File:
src/app/w/[slug]/task/[...taskParams]/artifacts/form.tsxDetect wizard-style forms and render appropriately:
Phase 4: Database Schema Changes
File:
prisma/schema.prismaAdd ChatMessage relation to Feature:
Run:
npx prisma migrate dev --name add-feature-architecture-messagesPhase 5: Create Architecture Conversation API
New file:
src/app/api/features/[featureId]/architecture/messages/route.tsNew file:
src/services/architecture-conversation.tsgetArchitectureMessages(featureId)createArchitectureMessage(featureId, params)submitWizardResponse(messageId, response)Phase 6: Update Stakwork Webhook Handler
File:
src/app/api/webhook/stakwork/response/route.tsWhen Stakwork returns clarifying questions:
tool_use: "ask_clarifying_questions"responseFormContentwithinputsarrayChatMessagewithrole: ASSISTANTandFORMartifactfeatureIdPhase 7: Update AITextareaSection
File:
src/components/features/AITextareaSection.tsxNew hook:
src/hooks/useArchitectureMessages.tsPhase 8: Add Feature Flag
File:
src/lib/feature-flags.tsFiles Summary
Files to Modify
src/lib/chat.tsprisma/schema.prismasrc/app/w/[slug]/task/[...taskParams]/artifacts/form.tsxsrc/components/features/AITextareaSection.tsxsrc/lib/feature-flags.tssrc/app/api/webhook/stakwork/response/route.tsNew Files to Create
src/components/ui/wizard-form/index.tsxsrc/app/api/features/[featureId]/architecture/messages/route.tssrc/services/architecture-conversation.tssrc/hooks/useArchitectureMessages.tsImplementation Order
src/lib/chat.tssrc/components/ui/wizard-form/