AI Service Implementation Guide
Status: Complete
Purpose: Comprehensive guide for implementing AI-first services in autonomous builds
Critical: Prevents catastrophic AI architecture gaps like those in build-v1
Why This Guide Exists
Build-v1 Lesson: NudgeCampaign was specified as an AI-first conversational platform but was built as a traditional CRUD application with ZERO AI integration. This guide ensures AI-first platforms actually implement AI from day one.
The Failure: Built traditional forms when wireframes showed conversational AI interface with Maya assistant and voice interaction. This must never happen again.
AI-First Architecture Principles
1. AI-First vs AI-Enhanced
AI-First Platforms (Revolutionary):
- Core value proposition depends on AI
- Traditional interfaces replaced by conversation
- AI eliminates complexity rather than adding features
- Examples: ChatGPT, Claude, Maya AI assistant
AI-Enhanced Platforms (Incremental):
- Traditional functionality with AI features added
- Core workflows remain manual
- AI provides suggestions or automation
- Examples: Gmail Smart Compose, traditional CRM with AI insights
Validation: If removing AI breaks the core value proposition, it's AI-first. If core functionality remains, it's AI-enhanced.
2. Mandatory AI Components for AI-First Platforms
// Core AI Architecture Requirements
interface AIFirstPlatform {
// Primary interface is conversational
conversationalInterface: ConversationalUI
// Core AI character/assistant
aiCharacter: AIPersonality
// Intent analysis replaces traditional forms
intentAnalysis: IntentAnalysisEngine
// AI generates workflows/content dynamically
aiGeneration: GenerativeAI
// Business context understanding
contextEngine: BusinessContextEngine
}
LLM Integration Architecture
1. Provider Abstraction Layer
Always implement provider abstraction to avoid vendor lock-in and enable cost optimization:
// ai-service.ts - Core abstraction
interface AIProvider {
generateResponse(prompt: string, context: AIContext): Promise<AIResponse>
analyzeIntent(userInput: string): Promise<IntentAnalysis>
generateContent(template: ContentTemplate): Promise<GeneratedContent>
validateResponse(response: string): Promise<ValidationResult>
}
// Provider implementations
class OpenAIProvider implements AIProvider {
private openai: OpenAI
constructor(apiKey: string) {
this.openai = new OpenAI({ apiKey })
}
async generateResponse(prompt: string, context: AIContext): Promise<AIResponse> {
const completion = await this.openai.chat.completions.create({
model: context.model || 'gpt-4',
messages: [
{ role: 'system', content: context.systemPrompt },
{ role: 'user', content: prompt }
],
temperature: context.temperature || 0.7,
max_tokens: context.maxTokens || 1000
})
return {
content: completion.choices[0]?.message?.content || '',
usage: completion.usage,
model: completion.model,
finishReason: completion.choices[0]?.finish_reason
}
}
async analyzeIntent(userInput: string): Promise<IntentAnalysis> {
const prompt = `
Analyze the user's intent and extract structured data:
User Input: "${userInput}"
Respond with JSON:
{
"intent": "create_campaign" | "manage_contacts" | "view_analytics" | "ask_question",
"entities": { "campaignName": string, "targetAudience": string, ... },
"confidence": number,
"followUpQuestions": string[]
}
`
const response = await this.generateResponse(prompt, {
systemPrompt: 'You are an intent analysis expert for business automation.',
temperature: 0.3
})
return JSON.parse(response.content)
}
}
class AnthropicProvider implements AIProvider {
private anthropic: Anthropic
constructor(apiKey: string) {
this.anthropic = new Anthropic({ apiKey })
}
async generateResponse(prompt: string, context: AIContext): Promise<AIResponse> {
const message = await this.anthropic.messages.create({
model: context.model || 'claude-3-sonnet-20240229',
max_tokens: context.maxTokens || 1000,
system: context.systemPrompt,
messages: [
{ role: 'user', content: prompt }
]
})
return {
content: message.content[0]?.text || '',
usage: message.usage,
model: message.model,
finishReason: message.stop_reason
}
}
async analyzeIntent(userInput: string): Promise<IntentAnalysis> {
// Similar implementation to OpenAI
}
}
// AI Service Manager
class AIService {
private providers: Map<string, AIProvider> = new Map()
private fallbackOrder: string[] = ['anthropic', 'openai']
constructor() {
this.providers.set('openai', new OpenAIProvider(process.env.OPENAI_API_KEY!))
this.providers.set('anthropic', new AnthropicProvider(process.env.ANTHROPIC_API_KEY!))
}
async generateResponse(prompt: string, context: AIContext = {}): Promise<AIResponse> {
for (const providerName of this.fallbackOrder) {
try {
const provider = this.providers.get(providerName)
if (!provider) continue
const response = await provider.generateResponse(prompt, context)
// Track usage and costs
await this.trackUsage(providerName, response.usage)
return response
} catch (error) {
console.warn(`Provider ${providerName} failed:`, error)
continue
}
}
throw new Error('All AI providers failed')
}
private async trackUsage(provider: string, usage: any) {
// Implement usage tracking for cost management
await UsageTracker.track({
provider,
timestamp: new Date(),
tokens: usage?.total_tokens || 0,
cost: this.calculateCost(provider, usage)
})
}
}
2. Conversation Management
Implement persistent conversation state for context-aware interactions:
// conversation-manager.ts
interface ConversationContext {
conversationId: string
userId: string
messages: ConversationMessage[]
businessContext: BusinessContext
currentIntent?: IntentAnalysis
metadata: {
startedAt: Date
lastActiveAt: Date
totalMessages: number
aiCharacter: string
}
}
interface ConversationMessage {
id: string
role: 'user' | 'assistant' | 'system'
content: string
timestamp: Date
metadata?: {
intent?: IntentAnalysis
actions?: ActionsTaken[]
cost?: number
}
}
class ConversationManager {
private conversations: Map<string, ConversationContext> = new Map()
private aiService: AIService
constructor(aiService: AIService) {
this.aiService = aiService
}
async startConversation(userId: string, aiCharacter: string = 'maya'): Promise<string> {
const conversationId = generateId()
const context: ConversationContext = {
conversationId,
userId,
messages: [],
businessContext: await this.loadBusinessContext(userId),
metadata: {
startedAt: new Date(),
lastActiveAt: new Date(),
totalMessages: 0,
aiCharacter
}
}
// Add welcome message
const welcomeMessage = await this.generateWelcomeMessage(context)
context.messages.push({
id: generateId(),
role: 'assistant',
content: welcomeMessage,
timestamp: new Date()
})
this.conversations.set(conversationId, context)
await this.persistConversation(context)
return conversationId
}
async processMessage(
conversationId: string,
userMessage: string
): Promise<ConversationResponse> {
const context = await this.getConversation(conversationId)
// Add user message
const userMsg: ConversationMessage = {
id: generateId(),
role: 'user',
content: userMessage,
timestamp: new Date()
}
context.messages.push(userMsg)
// Analyze intent
const intent = await this.aiService.analyzeIntent(userMessage)
userMsg.metadata = { intent }
context.currentIntent = intent
// Generate AI response
const aiResponse = await this.generateContextualResponse(context, userMessage)
// Add AI message
const aiMsg: ConversationMessage = {
id: generateId(),
role: 'assistant',
content: aiResponse.content,
timestamp: new Date(),
metadata: {
actions: aiResponse.actions,
cost: aiResponse.cost
}
}
context.messages.push(aiMsg)
// Update metadata
context.metadata.lastActiveAt = new Date()
context.metadata.totalMessages += 2
await this.persistConversation(context)
return {
message: aiMsg,
actions: aiResponse.actions,
intent,
context: this.getSafeContext(context)
}
}
private async generateContextualResponse(
context: ConversationContext,
userMessage: string
): Promise<AIGeneratedResponse> {
const prompt = this.buildPrompt(context, userMessage)
const systemPrompt = this.buildSystemPrompt(context)
const response = await this.aiService.generateResponse(prompt, {
systemPrompt,
temperature: 0.7,
maxTokens: 1000
})
// Extract actions from response
const actions = await this.extractActions(response.content, context)
return {
content: response.content,
actions,
cost: this.calculateCost(response.usage)
}
}
private buildSystemPrompt(context: ConversationContext): string {
const { aiCharacter, businessContext } = context
const basePrompts = {
maya: `You are Maya, the AI assistant for NudgeCampaign. You help users create email campaigns through natural conversation.
Your personality:
- Friendly and helpful, never pushy
- Expert in email marketing and automation
- Focused on understanding business needs first
- Always ask clarifying questions when needed
- Explain complex concepts simply
Your capabilities:
- Create email campaigns from natural language descriptions
- Set up automation workflows
- Manage contact lists and segmentation
- Provide email marketing best practices
- Generate content and subject lines
Business Context:
- Company: ${businessContext.companyName}
- Industry: ${businessContext.industry}
- Previous campaigns: ${businessContext.campaignHistory?.length || 0}
- Contact list size: ${businessContext.totalContacts}
Always respond in a conversational, helpful tone. When the user wants to create something, ask for the necessary details naturally through conversation.`
}
return basePrompts[aiCharacter] || basePrompts.maya
}
private async extractActions(response: string, context: ConversationContext): Promise<ActionsTaken[]> {
// Use structured output parsing to extract actions
const actionsPrompt = `
Analyze this AI response and extract any actions that should be taken:
Response: "${response}"
Available actions:
- create_campaign: Create a new email campaign
- add_contacts: Add contacts to lists
- schedule_email: Schedule email for sending
- create_automation: Set up automation workflow
- update_settings: Update account settings
Respond with JSON array:
[
{
"action": "action_name",
"parameters": { ... },
"confidence": 0.0-1.0
}
]
`
const actionsResponse = await this.aiService.generateResponse(actionsPrompt, {
systemPrompt: 'You are an action extraction expert.',
temperature: 0.1
})
try {
return JSON.parse(actionsResponse.content)
} catch {
return []
}
}
}
Conversational Interface Implementation
1. React Components for Conversational UI
Replace traditional forms with conversational interface:
// ConversationalInterface.tsx
interface ConversationalInterfaceProps {
conversationId?: string
aiCharacter?: string
onActionTaken?: (action: ActionsTaken) => void
}
export function ConversationalInterface({
conversationId,
aiCharacter = 'maya',
onActionTaken
}: ConversationalInterfaceProps) {
const [messages, setMessages] = useState<ConversationMessage[]>([])
const [input, setInput] = useState('')
const [isLoading, setIsLoading] = useState(false)
const [currentConversationId, setCurrentConversationId] = useState(conversationId)
useEffect(() => {
initializeConversation()
}, [])
const initializeConversation = async () => {
if (!currentConversationId) {
const newConversationId = await conversationAPI.startConversation(aiCharacter)
setCurrentConversationId(newConversationId)
}
const conversation = await conversationAPI.getConversation(currentConversationId!)
setMessages(conversation.messages)
}
const sendMessage = async () => {
if (!input.trim() || isLoading) return
const userMessage = input.trim()
setInput('')
setIsLoading(true)
// Add user message immediately for better UX
const tempUserMessage: ConversationMessage = {
id: 'temp-' + Date.now(),
role: 'user',
content: userMessage,
timestamp: new Date()
}
setMessages(prev => [...prev, tempUserMessage])
try {
const response = await conversationAPI.sendMessage(currentConversationId!, userMessage)
// Replace temp message and add AI response
setMessages(prev => [
...prev.filter(m => m.id !== tempUserMessage.id),
{
...tempUserMessage,
id: response.userMessageId
},
response.message
])
// Execute any actions
if (response.actions?.length) {
response.actions.forEach(action => {
onActionTaken?.(action)
})
}
} catch (error) {
setMessages(prev => prev.filter(m => m.id !== tempUserMessage.id))
// Show error message
} finally {
setIsLoading(false)
}
}
return (
<div className="flex flex-col h-full max-w-4xl mx-auto">
{/* Messages Container */}
<div className="flex-1 overflow-y-auto p-4 space-y-4">
{messages.map((message) => (
<MessageBubble key={message.id} message={message} />
))}
{isLoading && (
<div className="flex items-center space-x-2 text-gray-500">
<div className="animate-spin rounded-full h-4 w-4 border-b-2 border-blue-500"></div>
<span>Maya is thinking...</span>
</div>
)}
</div>
{/* Input Area */}
<div className="border-t bg-white p-4">
<div className="flex space-x-2">
<VoiceInput onTranscript={setInput} />
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
placeholder="Tell Maya what you'd like to do..."
className="flex-1 border rounded-lg px-4 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
<button
onClick={sendMessage}
disabled={!input.trim() || isLoading}
className="px-6 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:opacity-50"
>
Send
</button>
</div>
</div>
</div>
)
}
// MessageBubble.tsx
interface MessageBubbleProps {
message: ConversationMessage
}
export function MessageBubble({ message }: MessageBubbleProps) {
const isUser = message.role === 'user'
return (
<div className={`flex ${isUser ? 'justify-end' : 'justify-start'}`}>
<div className={`max-w-xs lg:max-w-md px-4 py-2 rounded-lg ${
isUser
? 'bg-blue-500 text-white'
: 'bg-gray-100 text-gray-900'
}`}>
{!isUser && (
<div className="flex items-center space-x-2 mb-1">
<div className="w-6 h-6 bg-gradient-to-r from-purple-500 to-pink-500 rounded-full flex items-center justify-center text-white text-xs font-bold">
M
</div>
<span className="text-sm font-medium text-gray-600">Maya</span>
</div>
)}
<div className="prose prose-sm max-w-none">
<ReactMarkdown>{message.content}</ReactMarkdown>
</div>
{message.metadata?.actions?.length && (
<div className="mt-2 space-y-1">
{message.metadata.actions.map((action, index) => (
<ActionIndicator key={index} action={action} />
))}
</div>
)}
<div className={`text-xs mt-1 ${isUser ? 'text-blue-100' : 'text-gray-500'}`}>
{format(message.timestamp, 'HH:mm')}
</div>
</div>
</div>
)
}
// VoiceInput.tsx
interface VoiceInputProps {
onTranscript: (transcript: string) => void
}
export function VoiceInput({ onTranscript }: VoiceInputProps) {
const [isListening, setIsListening] = useState(false)
const [recognition, setRecognition] = useState<SpeechRecognition | null>(null)
useEffect(() => {
if (typeof window !== 'undefined' && 'webkitSpeechRecognition' in window) {
const speechRecognition = new webkitSpeechRecognition()
speechRecognition.continuous = false
speechRecognition.interimResults = false
speechRecognition.lang = 'en-US'
speechRecognition.onresult = (event) => {
const transcript = event.results[0][0].transcript
onTranscript(transcript)
setIsListening(false)
}
speechRecognition.onerror = () => {
setIsListening(false)
}
speechRecognition.onend = () => {
setIsListening(false)
}
setRecognition(speechRecognition)
}
}, [onTranscript])
const toggleListening = () => {
if (!recognition) return
if (isListening) {
recognition.stop()
} else {
recognition.start()
setIsListening(true)
}
}
if (!recognition) return null
return (
<button
onClick={toggleListening}
className={`p-2 rounded-lg ${
isListening
? 'bg-red-500 text-white animate-pulse'
: 'bg-gray-200 text-gray-700 hover:bg-gray-300'
}`}
>
π€
</button>
)
}
Intent Analysis Engine
1. Natural Language to Structured Data
Transform user input into actionable data structures:
// intent-analysis.ts
interface IntentAnalysis {
intent: 'create_campaign' | 'manage_contacts' | 'view_analytics' | 'ask_question' | 'modify_existing'
confidence: number
entities: Record<string, any>
followUpQuestions?: string[]
suggestedActions?: ActionSuggestion[]
}
interface CampaignCreationIntent {
campaignName?: string
campaignType?: 'welcome' | 'promotional' | 'newsletter' | 'abandoned_cart'
targetAudience?: string
emailSubject?: string
callToAction?: string
sendDate?: string
frequency?: string
goals?: string[]
}
class IntentAnalysisEngine {
private aiService: AIService
constructor(aiService: AIService) {
this.aiService = aiService
}
async analyzeIntent(userInput: string, context: BusinessContext): Promise<IntentAnalysis> {
const prompt = `
You are an expert intent analysis engine for email marketing automation.
User Input: "${userInput}"
Business Context:
- Company: ${context.companyName}
- Industry: ${context.industry}
- Previous campaigns: ${context.campaignHistory?.map(c => c.name).join(', ')}
Analyze the user's intent and extract structured data. Respond with JSON:
{
"intent": "create_campaign" | "manage_contacts" | "view_analytics" | "ask_question" | "modify_existing",
"confidence": 0.0-1.0,
"entities": {
// For create_campaign intent:
"campaignName": string,
"campaignType": "welcome" | "promotional" | "newsletter" | "abandoned_cart",
"targetAudience": string,
"emailSubject": string,
"callToAction": string,
"sendDate": string (ISO format or relative like "tomorrow"),
"frequency": "once" | "daily" | "weekly" | "monthly",
"goals": ["increase_sales", "improve_engagement", "build_awareness"]
// For manage_contacts intent:
"action": "add" | "remove" | "segment" | "import",
"contactEmails": string[],
"segmentCriteria": string,
"listName": string
// For view_analytics intent:
"metric": "open_rates" | "click_rates" | "revenue" | "growth",
"timeframe": "last_week" | "last_month" | "last_quarter",
"campaignName": string
},
"followUpQuestions": [
"What specific audience should we target?",
"When would you like to send this campaign?"
],
"suggestedActions": [
{
"action": "create_campaign",
"description": "Create a promotional campaign for new product launch",
"confidence": 0.9
}
]
}
Guidelines:
- Extract as much structured data as possible from natural language
- If information is missing, suggest follow-up questions
- Be confident in intent classification
- Provide helpful action suggestions
`
const response = await this.aiService.generateResponse(prompt, {
systemPrompt: 'You are an expert intent analysis engine. Always respond with valid JSON.',
temperature: 0.1
})
try {
const analysis = JSON.parse(response.content)
// Validate and enhance the analysis
return this.enhanceAnalysis(analysis, context)
} catch (error) {
console.error('Intent analysis parsing failed:', error)
// Fallback analysis
return {
intent: 'ask_question',
confidence: 0.5,
entities: {},
followUpQuestions: ['Could you please clarify what you\'d like to do?']
}
}
}
private enhanceAnalysis(analysis: IntentAnalysis, context: BusinessContext): IntentAnalysis {
// Add business context enhancements
if (analysis.intent === 'create_campaign') {
// Suggest campaign names if not provided
if (!analysis.entities.campaignName) {
analysis.followUpQuestions = analysis.followUpQuestions || []
analysis.followUpQuestions.push('What would you like to name this campaign?')
}
// Suggest default audience based on business
if (!analysis.entities.targetAudience && context.defaultAudience) {
analysis.entities.targetAudience = context.defaultAudience
}
}
return analysis
}
async generateFollowUpQuestions(analysis: IntentAnalysis): Promise<string[]> {
if (analysis.confidence > 0.8 && Object.keys(analysis.entities).length > 3) {
return [] // We have enough information
}
const prompt = `
Based on this intent analysis, what follow-up questions should we ask to gather the remaining information needed?
Intent: ${analysis.intent}
Confidence: ${analysis.confidence}
Current entities: ${JSON.stringify(analysis.entities)}
Generate 2-3 natural, conversational follow-up questions that would help complete the task.
Respond with JSON array: ["question1", "question2", "question3"]
`
const response = await this.aiService.generateResponse(prompt, {
systemPrompt: 'You are a conversational UX expert. Generate natural follow-up questions.',
temperature: 0.7
})
try {
return JSON.parse(response.content)
} catch {
return ['What additional details would you like to provide?']
}
}
}
AI Workflow Generation
1. Dynamic n8n Workflow Creation
Generate workflows from natural language descriptions:
// ai-workflow-generator.ts
interface WorkflowGenerationRequest {
userDescription: string
campaignData: CampaignData
businessContext: BusinessContext
integrations: AvailableIntegration[]
}
interface GeneratedWorkflow {
n8nWorkflow: N8nWorkflowJSON
description: string
estimatedPerformance: PerformancePrediction
optimizationSuggestions: string[]
}
class AIWorkflowGenerator {
private aiService: AIService
private n8nService: N8nService
constructor(aiService: AIService, n8nService: N8nService) {
this.aiService = aiService
this.n8nService = n8nService
}
async generateWorkflow(request: WorkflowGenerationRequest): Promise<GeneratedWorkflow> {
// Step 1: Analyze workflow requirements
const workflowAnalysis = await this.analyzeWorkflowRequirements(request)
// Step 2: Generate n8n workflow JSON
const n8nWorkflow = await this.generateN8nWorkflow(workflowAnalysis, request)
// Step 3: Optimize the workflow
const optimizedWorkflow = await this.optimizeWorkflow(n8nWorkflow, request)
// Step 4: Generate performance predictions
const performancePrediction = await this.predictPerformance(optimizedWorkflow, request)
return {
n8nWorkflow: optimizedWorkflow,
description: workflowAnalysis.description,
estimatedPerformance: performancePrediction,
optimizationSuggestions: workflowAnalysis.optimizationSuggestions
}
}
private async analyzeWorkflowRequirements(request: WorkflowGenerationRequest): Promise<WorkflowAnalysis> {
const prompt = `
Analyze this workflow request and create a detailed implementation plan:
User Description: "${request.userDescription}"
Campaign Data:
- Name: ${request.campaignData.name}
- Type: ${request.campaignData.type}
- Target Audience: ${request.campaignData.targetAudience}
- Goals: ${request.campaignData.goals}
Available Integrations:
${request.integrations.map(i => `- ${i.name}: ${i.capabilities.join(', ')}`).join('\n')}
Business Context:
- Industry: ${request.businessContext.industry}
- Company Size: ${request.businessContext.size}
- Previous Campaigns: ${request.businessContext.campaignHistory?.length || 0}
Create a detailed workflow analysis:
{
"workflowType": "welcome_series" | "abandoned_cart" | "promotional" | "nurture" | "custom",
"description": "Detailed description of what this workflow will do",
"steps": [
{
"stepNumber": 1,
"action": "Send welcome email",
"trigger": "New contact added",
"timing": "Immediately",
"conditions": ["Contact has email", "Contact opted in"]
}
],
"requiredIntegrations": ["postmark", "database", "webhook"],
"estimatedComplexity": "low" | "medium" | "high",
"optimizationSuggestions": [
"Add personalization based on signup source",
"Include A/B testing for subject lines"
],
"successMetrics": ["Open rate > 30%", "Click rate > 5%"],
"potentialIssues": [
"High email volume may hit rate limits",
"Database queries may be slow with large contact lists"
]
}
`
const response = await this.aiService.generateResponse(prompt, {
systemPrompt: 'You are an expert email marketing automation architect. Always respond with valid JSON.',
temperature: 0.3
})
return JSON.parse(response.content)
}
private async generateN8nWorkflow(analysis: WorkflowAnalysis, request: WorkflowGenerationRequest): Promise<N8nWorkflowJSON> {
const prompt = `
Generate a complete n8n workflow JSON based on this analysis:
${JSON.stringify(analysis, null, 2)}
Requirements:
- Use proper n8n node structure
- Include error handling and retry logic
- Add appropriate delays and conditions
- Use environment variables for sensitive data
- Include webhook endpoints for triggers
- Add data validation and transformation
Generate a complete n8n workflow JSON with:
1. Webhook trigger node
2. Condition nodes for filtering
3. Postmark email sending nodes
4. Database update nodes
5. Error handling nodes
6. Monitoring and logging nodes
Respond with valid n8n workflow JSON.
`
const response = await this.aiService.generateResponse(prompt, {
systemPrompt: 'You are an n8n workflow expert. Generate complete, working n8n workflow JSON.',
temperature: 0.1,
maxTokens: 4000
})
try {
const workflow = JSON.parse(response.content)
// Validate and enhance the workflow
return this.validateAndEnhanceWorkflow(workflow, analysis)
} catch (error) {
console.error('Workflow JSON parsing failed:', error)
throw new Error('Failed to generate valid n8n workflow')
}
}
private validateAndEnhanceWorkflow(workflow: N8nWorkflowJSON, analysis: WorkflowAnalysis): N8nWorkflowJSON {
// Add standard enhancements
workflow.settings = {
...workflow.settings,
executionOrder: 'v1',
saveManualExecutions: true,
callerPolicy: 'workflowsFromSameOwner'
}
// Add error handling if missing
if (!workflow.nodes.some(node => node.type === 'n8n-nodes-base.errorTrigger')) {
workflow.nodes.push({
parameters: {},
name: 'Error Handler',
type: 'n8n-nodes-base.errorTrigger',
typeVersion: 1,
position: [1000, 500]
})
}
// Add monitoring webhook
workflow.nodes.push({
parameters: {
httpMethod: 'POST',
path: '/workflow-status',
responseMode: 'onReceived'
},
name: 'Status Webhook',
type: 'n8n-nodes-base.webhook',
typeVersion: 1,
position: [1200, 300]
})
return workflow
}
async deployWorkflow(workflow: N8nWorkflowJSON, name: string): Promise<string> {
try {
// Deploy to n8n
const workflowId = await this.n8nService.createWorkflow({
name,
nodes: workflow.nodes,
connections: workflow.connections,
settings: workflow.settings
})
// Activate the workflow
await this.n8nService.activateWorkflow(workflowId)
return workflowId
} catch (error) {
console.error('Workflow deployment failed:', error)
throw new Error('Failed to deploy workflow to n8n')
}
}
}
AI Cost Management
1. Usage Tracking and Optimization
// ai-cost-management.ts
interface AIUsageMetrics {
userId: string
provider: string
model: string
operation: string
inputTokens: number
outputTokens: number
totalTokens: number
cost: number
timestamp: Date
conversationId?: string
}
interface UsageLimits {
dailyTokenLimit: number
monthlyCostLimit: number
rateLimitPerHour: number
maxConversationLength: number
}
class AICostManager {
private usage: Map<string, AIUsageMetrics[]> = new Map()
private limits: Map<string, UsageLimits> = new Map()
async trackUsage(metrics: AIUsageMetrics): Promise<void> {
const userUsage = this.usage.get(metrics.userId) || []
userUsage.push(metrics)
this.usage.set(metrics.userId, userUsage)
// Persist to database
await this.persistUsage(metrics)
// Check limits
await this.checkUsageLimits(metrics.userId)
}
async checkUsageLimits(userId: string): Promise<UsageLimitResult> {
const limits = this.limits.get(userId) || this.getDefaultLimits()
const usage = await this.getUserUsage(userId)
const today = new Date()
const thisMonth = new Date(today.getFullYear(), today.getMonth(), 1)
// Calculate daily usage
const dailyUsage = usage.filter(u =>
u.timestamp.toDateString() === today.toDateString()
)
const dailyTokens = dailyUsage.reduce((sum, u) => sum + u.totalTokens, 0)
// Calculate monthly cost
const monthlyUsage = usage.filter(u => u.timestamp >= thisMonth)
const monthlyCost = monthlyUsage.reduce((sum, u) => sum + u.cost, 0)
const result: UsageLimitResult = {
withinLimits: true,
warnings: [],
dailyTokensUsed: dailyTokens,
dailyTokensRemaining: Math.max(0, limits.dailyTokenLimit - dailyTokens),
monthlyCostUsed: monthlyCost,
monthlyCostRemaining: Math.max(0, limits.monthlyCostLimit - monthlyCost)
}
// Check limits
if (dailyTokens >= limits.dailyTokenLimit) {
result.withinLimits = false
result.warnings.push('Daily token limit exceeded')
}
if (monthlyCost >= limits.monthlyCostLimit) {
result.withinLimits = false
result.warnings.push('Monthly cost limit exceeded')
}
// Send alerts if approaching limits
if (dailyTokens >= limits.dailyTokenLimit * 0.8) {
result.warnings.push('Approaching daily token limit')
}
if (monthlyCost >= limits.monthlyCostLimit * 0.8) {
result.warnings.push('Approaching monthly cost limit')
}
return result
}
optimizePrompt(prompt: string): OptimizedPrompt {
// Remove unnecessary words and formatting
const optimized = prompt
.replace(/\s+/g, ' ') // Multiple spaces to single space
.replace(/\n\s*\n/g, '\n') // Multiple newlines to single
.trim()
const tokenReduction = (prompt.length - optimized.length) / prompt.length
return {
originalPrompt: prompt,
optimizedPrompt: optimized,
tokenReduction,
estimatedSavings: this.calculateTokenSavings(prompt.length - optimized.length)
}
}
async selectOptimalProvider(
operation: string,
requirements: AIRequirements
): Promise<string> {
const providers = {
'openai-gpt4': { cost: 0.03, quality: 0.95, speed: 0.8 },
'openai-gpt35': { cost: 0.002, quality: 0.8, speed: 0.95 },
'anthropic-claude': { cost: 0.025, quality: 0.92, speed: 0.85 }
}
// Score providers based on requirements
const scores = Object.entries(providers).map(([name, metrics]) => {
const score =
(requirements.priorityCost ? 1 - metrics.cost / 0.03 : 0) * 0.4 +
(requirements.priorityQuality ? metrics.quality : 0) * 0.4 +
(requirements.prioritySpeed ? metrics.speed : 0) * 0.2
return { provider: name, score }
})
return scores.sort((a, b) => b.score - a.score)[0].provider
}
}
AI Implementation Validation Checklist
Pre-Build Validation
- AI-first architecture planned - Core AI functionality defines product value
- LLM provider selected - OpenAI, Anthropic, or local model integration planned
- Conversational interface designed - Chat/voice interface replaces traditional forms
- AI character personality defined - Assistant personality and capabilities specified
- Intent analysis system planned - Natural language to structured data conversion
- AI workflow generation specified - Dynamic automation creation requirements
- AI safety measures planned - Content moderation, hallucination prevention
- Cost management strategy defined - Usage limits, optimization, monitoring
Implementation Validation
- LLM integration functional - API calls working, responses processed correctly
- Provider abstraction implemented - Can switch between AI providers
- Conversation management working - State persistence, context awareness
- Intent analysis operational - Natural language converted to actions
- AI character responding - Personality consistent, helpful responses
- Workflow generation functional - AI creates working automation
- Safety measures active - Content filtering, error handling working
- Cost tracking operational - Usage monitoring, limits enforced
Quality Validation
- AI responses coherent - Output makes sense and is helpful
- Intent analysis accurate - Correctly understands user requests >80% of time
- Conversation flows natural - Interactions feel human-like
- AI character consistent - Personality maintained across conversations
- Generated content quality - Workflows/content meet professional standards
- Error handling graceful - AI failures don't break user experience
- Performance acceptable - Response times under 3 seconds
- Cost optimization working - Staying within budget limits
Critical Success Criteria
AI-First Platform Must:
- Replace traditional interfaces with conversational AI
- Implement core AI character with consistent personality
- Convert natural language to structured actions
- Generate dynamic content (workflows, emails, etc.)
- Maintain conversation context across interactions
- Handle errors gracefully with fallback responses
- Track and optimize costs automatically
- Validate AI safety continuously
Failure Criteria:
- Traditional forms as primary interface = AI-Enhanced, not AI-First
- Missing AI character/personality = Generic chatbot
- No intent analysis = Simple Q&A system
- No dynamic generation = Static template system
- No conversation state = Stateless interactions
- Poor error handling = Broken user experience
- No cost controls = Budget overruns
- No safety measures = Content quality issues
This guide ensures AI-first platforms actually implement AI from day one, preventing the catastrophic AI architecture miss that occurred in build-v1.