widgetdc-cortex / apps /backend /src /mcp /cognitive /SelfReflectionEngine.ts
Kraft102's picture
Initial deployment - WidgeTDC Cortex Backend v2.1.0
529090e
import { neo4jService } from '../../database/Neo4jService';
/**
* Self-Reflection Engine
* Enables agents to assess their own performance and improve
*/
export interface PerformanceMetrics {
taskId: string;
agentId: string;
success: boolean;
duration: number;
errorType?: string;
timestamp: Date;
context: Record<string, any>;
}
export interface ReflectionInsight {
pattern: string;
frequency: number;
impact: 'positive' | 'negative' | 'neutral';
recommendation: string;
confidence: number;
}
export class SelfReflectionEngine {
private performanceLog: PerformanceMetrics[] = [];
private insights: ReflectionInsight[] = [];
/**
* Log performance data
*/
logPerformance(metrics: PerformanceMetrics): void {
this.performanceLog.push(metrics);
// Keep only last 1000 entries
if (this.performanceLog.length > 1000) {
this.performanceLog.shift();
}
}
/**
* Analyze error patterns
*/
analyzeErrorPatterns(agentId?: string): Map<string, number> {
const errors = this.performanceLog.filter(log =>
!log.success && (!agentId || log.agentId === agentId)
);
const errorCounts = new Map<string, number>();
errors.forEach(error => {
if (error.errorType) {
errorCounts.set(error.errorType, (errorCounts.get(error.errorType) || 0) + 1);
}
});
return errorCounts;
}
/**
* Evaluate strategy effectiveness
*/
evaluateStrategyEffectiveness(
strategy: string,
timeWindow: number = 7 * 24 * 60 * 60 * 1000 // 7 days
): {
successRate: number;
avgDuration: number;
totalAttempts: number;
} {
const cutoff = new Date(Date.now() - timeWindow);
const relevant = this.performanceLog.filter(log =>
log.timestamp > cutoff &&
log.context.strategy === strategy
);
if (relevant.length === 0) {
return { successRate: 0, avgDuration: 0, totalAttempts: 0 };
}
const successes = relevant.filter(log => log.success).length;
const totalDuration = relevant.reduce((sum, log) => sum + log.duration, 0);
return {
successRate: successes / relevant.length,
avgDuration: totalDuration / relevant.length,
totalAttempts: relevant.length,
};
}
/**
* Generate improvement recommendations
*/
async generateRecommendations(agentId: string): Promise<ReflectionInsight[]> {
const errorPatterns = this.analyzeErrorPatterns(agentId);
const recommendations: ReflectionInsight[] = [];
// Analyze error patterns
errorPatterns.forEach((count, errorType) => {
if (count > 5) {
recommendations.push({
pattern: `Frequent ${errorType} errors`,
frequency: count,
impact: 'negative',
recommendation: `Implement better error handling for ${errorType}`,
confidence: Math.min(count / 10, 1),
});
}
});
// Analyze performance trends
const recentPerformance = this.performanceLog
.filter(log => log.agentId === agentId)
.slice(-50);
if (recentPerformance.length > 10) {
const successRate = recentPerformance.filter(log => log.success).length / recentPerformance.length;
if (successRate < 0.7) {
recommendations.push({
pattern: 'Low success rate',
frequency: recentPerformance.length,
impact: 'negative',
recommendation: 'Review task assignment criteria and agent capabilities',
confidence: 1 - successRate,
});
} else if (successRate > 0.95) {
recommendations.push({
pattern: 'High success rate',
frequency: recentPerformance.length,
impact: 'positive',
recommendation: 'Consider taking on more complex tasks',
confidence: successRate,
});
}
}
this.insights = recommendations;
return recommendations;
}
/**
* Continuous improvement loop
*/
async runImprovementCycle(agentId: string): Promise<void> {
const recommendations = await this.generateRecommendations(agentId);
// Store insights in Neo4j for long-term learning
try {
await neo4jService.connect();
for (const insight of recommendations) {
await neo4jService.runQuery(
`MERGE (a:Agent {id: $agentId})
CREATE (i:Insight {
pattern: $pattern,
recommendation: $recommendation,
confidence: $confidence,
timestamp: datetime()
})
CREATE (a)-[:HAS_INSIGHT]->(i)`,
{
agentId,
pattern: insight.pattern,
recommendation: insight.recommendation,
confidence: insight.confidence,
}
);
}
await neo4jService.disconnect();
} catch (error) {
console.error('Failed to store insights:', error);
}
console.log(`🔍 Generated ${recommendations.length} improvement recommendations for ${agentId}`);
}
/**
* Get performance summary
*/
getPerformanceSummary(agentId: string, days: number = 7): {
totalTasks: number;
successRate: number;
avgDuration: number;
errorBreakdown: Map<string, number>;
} {
const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
const relevant = this.performanceLog.filter(log =>
log.agentId === agentId && log.timestamp > cutoff
);
const successes = relevant.filter(log => log.success).length;
const totalDuration = relevant.reduce((sum, log) => sum + log.duration, 0);
return {
totalTasks: relevant.length,
successRate: relevant.length > 0 ? successes / relevant.length : 0,
avgDuration: relevant.length > 0 ? totalDuration / relevant.length : 0,
errorBreakdown: this.analyzeErrorPatterns(agentId),
};
}
}
export const selfReflectionEngine = new SelfReflectionEngine();