Kraft102's picture
Initial deployment - WidgeTDC Cortex Backend v2.1.0
529090e
// AgentTeam – Phase 2 Week 5-6
// Role-based agent coordination system
import { unifiedMemorySystem } from './UnifiedMemorySystem.js';
import { hybridSearchEngine } from './HybridSearchEngine.js';
import { emotionAwareDecisionEngine } from './EmotionAwareDecisionEngine.js';
import { unifiedGraphRAG } from './UnifiedGraphRAG.js';
import { stateGraphRouter, AgentState } from './StateGraphRouter.js';
import { projectMemory } from '../../services/project/ProjectMemory.js';
import { eventBus } from '../EventBus.js';
export type AgentRole = 'data' | 'security' | 'memory' | 'pal' | 'orchestrator';
export interface AgentMessage {
from: AgentRole;
to: AgentRole | 'all';
type: 'query' | 'task' | 'result' | 'alert' | 'coordinate';
content: string;
metadata?: any;
timestamp: Date;
}
export interface AgentCapabilities {
canHandle: (message: AgentMessage) => boolean | Promise<boolean>;
execute: (message: AgentMessage) => Promise<any>;
getStatus: () => Promise<AgentStatus>;
}
export interface AgentStatus {
role: AgentRole;
active: boolean;
tasksCompleted: number;
lastActivity: Date;
capabilities: string[];
}
/**
* Data Agent - Handles data ingestion, transformation, and quality
*/
class DataAgent implements AgentCapabilities {
public readonly role: AgentRole = 'data';
private tasksCompleted = 0;
private lastActivity = new Date();
canHandle(message: AgentMessage): boolean {
return message.type === 'query' && (
message.content.includes('data') ||
message.content.includes('ingest') ||
message.content.includes('transform') ||
message.content.includes('quality')
);
}
async execute(message: AgentMessage): Promise<any> {
console.log(`📊 [DataAgent] Processing: ${message.content}`);
this.lastActivity = new Date();
this.tasksCompleted++;
// Use HybridSearchEngine to find relevant data
const searchResults = await hybridSearchEngine.search(message.content, {
userId: message.metadata?.userId || 'system',
orgId: message.metadata?.orgId || 'default',
limit: 10,
timestamp: new Date()
});
return {
role: this.role,
result: {
dataFound: searchResults.length,
sources: searchResults.map(r => ({
source: r.source,
relevance: r.score
})),
quality: this.assessDataQuality(searchResults)
}
};
}
private assessDataQuality(searchResults: any): {
completeness: number;
freshness: number;
reliability: number;
} {
// Simple quality assessment
const avgScore = searchResults.results.reduce((sum: number, r: any) => sum + r.score, 0) / searchResults.results.length || 0;
return {
completeness: Math.min(1.0, searchResults.results.length / 10),
freshness: avgScore,
reliability: avgScore * 0.9
};
}
async getStatus(): Promise<AgentStatus> {
return {
role: this.role,
active: true,
tasksCompleted: this.tasksCompleted,
lastActivity: this.lastActivity,
capabilities: ['data_ingestion', 'data_quality', 'data_transformation']
};
}
}
/**
* Security Agent - Handles security checks, threat detection, and compliance
*/
class SecurityAgent implements AgentCapabilities {
public readonly role: AgentRole = 'security';
private tasksCompleted = 0;
private lastActivity = new Date();
canHandle(message: AgentMessage): boolean {
return message.type === 'query' && (
message.content.includes('security') ||
message.content.includes('threat') ||
message.content.includes('compliance') ||
message.content.includes('vulnerability')
) || message.type === 'alert';
}
async execute(message: AgentMessage): Promise<any> {
console.log(`🔒 [SecurityAgent] Processing: ${message.content}`);
this.lastActivity = new Date();
this.tasksCompleted++;
// Use EmotionAwareDecisionEngine for security decisions
const decision = await emotionAwareDecisionEngine.makeDecision(
message.content,
{
orgId: message.metadata?.orgId || 'default',
userId: message.metadata?.userId || 'system',
boardId: message.metadata?.boardId
}
);
return {
role: this.role,
result: {
threatLevel: this.assessThreatLevel(message.content),
decision: decision,
recommendations: this.generateSecurityRecommendations(message.content)
}
};
}
private assessThreatLevel(content: string): 'low' | 'medium' | 'high' {
const threatKeywords = ['vulnerability', 'breach', 'attack', 'malware', 'exploit'];
const found = threatKeywords.filter(kw => content.toLowerCase().includes(kw)).length;
if (found >= 2) return 'high';
if (found >= 1) return 'medium';
return 'low';
}
private generateSecurityRecommendations(content: string): string[] {
const recommendations: string[] = [];
if (content.includes('vulnerability')) {
recommendations.push('Run security scan');
recommendations.push('Review access controls');
}
if (content.includes('compliance')) {
recommendations.push('Verify GDPR compliance');
recommendations.push('Check data retention policies');
}
return recommendations;
}
async getStatus(): Promise<AgentStatus> {
return {
role: this.role,
active: true,
tasksCompleted: this.tasksCompleted,
lastActivity: this.lastActivity,
capabilities: ['threat_detection', 'compliance_check', 'security_scan']
};
}
}
/**
* Memory Agent - Handles memory operations, retrieval, and consolidation
*/
class MemoryAgent implements AgentCapabilities {
public readonly role: AgentRole = 'memory';
private tasksCompleted = 0;
private lastActivity = new Date();
canHandle(message: AgentMessage): boolean {
return message.type === 'query' && (
message.content.includes('memory') ||
message.content.includes('remember') ||
message.content.includes('recall') ||
message.content.includes('forget')
);
}
async execute(message: AgentMessage): Promise<any> {
console.log(`🧠 [MemoryAgent] Processing: ${message.content}`);
this.lastActivity = new Date();
this.tasksCompleted++;
// Use UnifiedMemorySystem for memory operations
const memory = await unifiedMemorySystem.getWorkingMemory({
userId: message.metadata?.userId || 'system',
orgId: message.metadata?.orgId || 'default'
});
// Use GraphRAG for memory retrieval
const graphResult = await unifiedGraphRAG.query(message.content, {
userId: message.metadata?.userId || 'system',
orgId: message.metadata?.orgId || 'default'
});
return {
role: this.role,
result: {
workingMemory: memory,
graphContext: graphResult,
consolidation: await this.consolidateMemory(memory)
}
};
}
private async consolidateMemory(memory: any): Promise<{
patterns: number;
features: number;
events: number;
}> {
return {
patterns: memory.recentPatterns?.length || 0,
features: memory.recentFeatures?.length || 0,
events: memory.recentEvents?.length || 0
};
}
async getStatus(): Promise<AgentStatus> {
return {
role: this.role,
active: true,
tasksCompleted: this.tasksCompleted,
lastActivity: this.lastActivity,
capabilities: ['memory_retrieval', 'memory_consolidation', 'pattern_detection']
};
}
}
/**
* PAL Agent - Personal Assistant, Life Coach, Strategic & Political Advisor, Compensation Expert
* Inspired by CgentCore's L1 Director Agent architecture
*/
class PalAgent implements AgentCapabilities {
public readonly role: AgentRole = 'pal';
private conversationHistory: Array<{ role: string; content: string; timestamp: Date }> = [];
canHandle(message: AgentMessage): boolean {
const content = message.content.toLowerCase();
return message.type === 'query' && (
// Personal Assistant
content.includes('assistant') ||
content.includes('help me') ||
content.includes('remind') ||
content.includes('schedule') ||
// Coach
content.includes('coach') ||
content.includes('advice') ||
content.includes('guidance') ||
content.includes('improve') ||
// Strategic
content.includes('strategy') ||
content.includes('strategic') ||
content.includes('planning') ||
content.includes('roadmap') ||
// Political
content.includes('political') ||
content.includes('politics') ||
content.includes('policy') ||
content.includes('stakeholder') ||
// Compensation
content.includes('salary') ||
content.includes('compensation') ||
content.includes('gage') ||
content.includes('pay') ||
content.includes('bonus') ||
// Personal/workflow
content.includes('workflow') ||
content.includes('optimize') ||
content.includes('personal') ||
content.includes('preference') ||
content.includes('emotional')
);
}
async execute(message: AgentMessage): Promise<any> {
console.log(`👤 [PalAgent] Processing: ${message.content}`);
// Store conversation history
this.conversationHistory.push({
role: 'user',
content: message.content,
timestamp: new Date()
});
// Determine agent mode based on content
const mode = this.determineMode(message.content);
// Use EmotionAwareDecisionEngine for personal decisions
const decision = await emotionAwareDecisionEngine.makeDecision(
message.content,
{
orgId: message.metadata?.orgId || 'default',
userId: message.metadata?.userId || 'system',
boardId: message.metadata?.boardId
}
);
// Route to specialized handler
let result: any;
switch (mode) {
case 'coach':
result = await this.handleCoach(message, decision);
break;
case 'strategic':
result = await this.handleStrategic(message, decision);
break;
case 'political':
result = await this.handlePolitical(message, decision);
break;
case 'compensation':
result = await this.handleCompensation(message, decision);
break;
case 'assistant':
default:
result = await this.handleAssistant(message, decision);
break;
}
// Store agent response
this.conversationHistory.push({
role: 'assistant',
content: JSON.stringify(result),
timestamp: new Date()
});
return {
role: this.role,
mode,
result,
emotionalState: decision.emotionalState,
confidence: decision.confidence
};
}
/**
* Determine agent mode from message content
*/
private determineMode(content: string): 'assistant' | 'coach' | 'strategic' | 'political' | 'compensation' {
const lower = content.toLowerCase();
if (lower.includes('coach') || lower.includes('guidance') || lower.includes('improve')) {
return 'coach';
}
if (lower.includes('strategy') || lower.includes('strategic') || lower.includes('planning')) {
return 'strategic';
}
if (lower.includes('political') || lower.includes('politics') || lower.includes('policy') || lower.includes('stakeholder')) {
return 'political';
}
if (lower.includes('salary') || lower.includes('compensation') || lower.includes('gage') || lower.includes('pay') || lower.includes('bonus')) {
return 'compensation';
}
return 'assistant';
}
/**
* Personal Assistant Mode - Task management, reminders, scheduling
*/
private async handleAssistant(message: AgentMessage, decision: any): Promise<any> {
console.log(' 📋 [PalAgent] Assistant mode');
// Use UnifiedMemorySystem to recall user preferences
const memory = await unifiedMemorySystem.getWorkingMemory({
userId: message.metadata?.userId || 'system',
orgId: message.metadata?.orgId || 'default'
});
return {
type: 'assistant',
response: this.generateAssistantResponse(message.content),
recommendations: this.generateWorkflowRecommendations(message.content),
context: {
recentPatterns: memory.recentPatterns?.slice(0, 3) || [],
preferences: memory.recentFeatures?.slice(0, 3) || []
},
nextActions: [
'Review your calendar for conflicts',
'Check pending tasks',
'Update preferences based on feedback'
]
};
}
/**
* Coach Mode - Personal development, guidance, improvement
*/
private async handleCoach(message: AgentMessage, decision: any): Promise<any> {
console.log(' 🎯 [PalAgent] Coach mode');
// Use GraphRAG to find related coaching insights
const graphResult = await unifiedGraphRAG.query(`Coaching advice: ${message.content}`, {
userId: message.metadata?.userId || 'system',
orgId: message.metadata?.orgId || 'default'
});
return {
type: 'coach',
guidance: this.generateCoachingGuidance(message.content, decision),
insights: graphResult.nodes.slice(0, 3).map((n: any) => ({
insight: n.content,
confidence: n.score
})),
actionPlan: [
'Identify specific goals',
'Break down into actionable steps',
'Set measurable milestones',
'Schedule regular check-ins'
],
emotionalSupport: {
currentState: decision.emotionalState,
recommendations: this.getEmotionalRecommendations(decision.emotionalState)
}
};
}
/**
* Strategic Advisor Mode - Strategic planning, roadmaps, business strategy
*/
private async handleStrategic(message: AgentMessage, decision: any): Promise<any> {
console.log(' 🎲 [PalAgent] Strategic advisor mode');
// Use StateGraphRouter for strategic planning workflow
const state = stateGraphRouter.initState(`strategic-${Date.now()}`, message.content);
let currentState = state;
let iterations = 0;
while (currentState.status === 'active' && iterations < 5) {
currentState = await stateGraphRouter.route(currentState);
iterations++;
}
return {
type: 'strategic',
analysis: this.generateStrategicAnalysis(message.content),
roadmap: currentState.scratchpad.plan || [],
recommendations: [
'Define clear objectives',
'Identify key stakeholders',
'Assess risks and opportunities',
'Create timeline with milestones',
'Establish success metrics'
],
considerations: {
risks: ['Resource constraints', 'Timeline pressure', 'Stakeholder alignment'],
opportunities: ['Market timing', 'Competitive advantage', 'Innovation potential'],
dependencies: ['Team capacity', 'Technology readiness', 'Budget approval']
},
planningState: currentState.scratchpad
};
}
/**
* Political Advisor Mode - Stakeholder management, organizational politics
*/
private async handlePolitical(message: AgentMessage, decision: any): Promise<any> {
console.log(' 🏛️ [PalAgent] Political advisor mode');
return {
type: 'political',
analysis: this.generatePoliticalAnalysis(message.content),
stakeholderMap: [
{ role: 'Champion', influence: 'high', support: 'positive' },
{ role: 'Decision Maker', influence: 'high', support: 'neutral' },
{ role: 'Influencer', influence: 'medium', support: 'positive' }
],
recommendations: [
'Identify key decision makers',
'Build coalition of supporters',
'Address concerns proactively',
'Communicate value proposition clearly',
'Timing is critical - choose right moment'
],
tactics: {
communication: 'Tailor message to audience',
timing: 'Align with organizational cycles',
relationships: 'Leverage existing networks',
framing: 'Position as win-win solution'
},
warnings: [
'Avoid creating unnecessary opposition',
'Respect organizational hierarchy',
'Be transparent about intentions'
]
};
}
/**
* Compensation Expert Mode - Salary, benefits, negotiation
*/
private async handleCompensation(message: AgentMessage, decision: any): Promise<any> {
console.log(' 💰 [PalAgent] Compensation expert mode');
// Use HybridSearchEngine to find market data
const searchResults = await hybridSearchEngine.search(`compensation ${message.content}`, {
userId: message.metadata?.userId || 'system',
orgId: message.metadata?.orgId || 'default',
limit: 5,
timestamp: new Date()
});
return {
type: 'compensation',
analysis: this.generateCompensationAnalysis(message.content),
marketData: {
sources: searchResults.slice(0, 3).map((r: any) => ({
source: r.source,
relevance: r.score
})),
note: 'Market data should be verified from multiple sources'
},
recommendations: [
'Research market rates for your role and location',
'Consider total compensation package (salary + benefits)',
'Document your achievements and value',
'Prepare negotiation strategy',
'Know your walk-away point'
],
negotiationTips: [
'Focus on value delivered, not just time served',
'Use data to support your request',
'Consider non-monetary benefits',
'Practice your pitch',
'Be prepared to negotiate'
],
factors: {
baseSalary: 'Foundation of compensation',
bonuses: 'Variable compensation',
equity: 'Long-term value',
benefits: 'Health, retirement, etc.',
perks: 'Flexibility, development, etc.'
}
};
}
private generateAssistantResponse(content: string): string {
if (content.includes('remind')) {
return 'I can help you set reminders. What would you like to be reminded about?';
}
if (content.includes('schedule')) {
return 'I can help you manage your schedule. What would you like to schedule?';
}
return 'How can I assist you today?';
}
private generateCoachingGuidance(content: string, decision: any): string {
return `Based on your current emotional state (${decision.emotionalState}), I recommend focusing on clear, achievable goals. Let's break down your challenge into manageable steps.`;
}
private generateStrategicAnalysis(content: string): string {
return 'Strategic analysis requires understanding objectives, constraints, and opportunities. Let me help you develop a comprehensive strategy.';
}
private generatePoliticalAnalysis(content: string): string {
return 'Organizational politics require careful navigation. Key factors: stakeholder interests, power dynamics, and timing.';
}
private generateCompensationAnalysis(content: string): string {
return 'Compensation analysis should consider market rates, your value proposition, and total package (salary + benefits + equity).';
}
private getEmotionalRecommendations(emotionalState: string): string[] {
const recommendations: Record<string, string[]> = {
'positive': ['Maintain momentum', 'Set stretch goals', 'Share success'],
'neutral': ['Focus on growth', 'Seek feedback', 'Plan next steps'],
'negative': ['Take breaks', 'Seek support', 'Reframe challenges', 'Celebrate small wins']
};
return recommendations[emotionalState] || recommendations['neutral'];
}
private generateWorkflowRecommendations(content: string): string[] {
const recommendations: string[] = [];
if (content.includes('optimize')) {
recommendations.push('Review recent task patterns');
recommendations.push('Identify bottlenecks');
recommendations.push('Automate repetitive tasks');
}
if (content.includes('workflow')) {
recommendations.push('Analyze user preferences');
recommendations.push('Suggest workflow improvements');
recommendations.push('Implement time-blocking');
}
return recommendations;
}
async getStatus(): Promise<AgentStatus> {
return {
role: this.role,
active: true,
tasksCompleted: this.conversationHistory.filter(m => m.role === 'assistant').length,
lastActivity: this.conversationHistory.length > 0
? this.conversationHistory[this.conversationHistory.length - 1].timestamp
: new Date(),
capabilities: [
'personal_assistant',
'life_coach',
'strategic_advisor',
'political_advisor',
'compensation_expert',
'workflow_optimization',
'emotional_awareness',
'conversation_history'
]
};
}
/**
* Get conversation history
*/
public getConversationHistory(): Array<{ role: string; content: string; timestamp: Date }> {
return this.conversationHistory.slice(-20); // Last 20 messages
}
}
/**
* Orchestrator Agent - Coordinates other agents and manages task flow
*/
class OrchestratorAgent implements AgentCapabilities {
public readonly role: AgentRole = 'orchestrator';
private messageHistory: AgentMessage[] = [];
canHandle(message: AgentMessage): boolean {
return message.type === 'coordinate' || message.to === 'orchestrator';
}
async execute(message: AgentMessage): Promise<any> {
console.log(`🎯 [OrchestratorAgent] Coordinating: ${message.content}`);
this.messageHistory.push(message);
// Use StateGraphRouter for complex coordination
const state = stateGraphRouter.initState(`coord-${Date.now()}`, message.content);
let currentState = state;
let iterations = 0;
while (currentState.status === 'active' && iterations < 10) {
currentState = await stateGraphRouter.route(currentState);
iterations++;
}
return {
role: this.role,
result: {
coordination: {
state: currentState.status,
path: currentState.history,
iterations
},
messageHistory: this.messageHistory.slice(-10)
}
};
}
async getStatus(): Promise<AgentStatus> {
return {
role: this.role,
active: true,
tasksCompleted: this.messageHistory.length,
lastActivity: new Date(),
capabilities: ['coordination', 'task_routing', 'agent_management']
};
}
}
/**
* AgentTeam - Coordinates role-based agents
*/
export class AgentTeam {
private agents: Map<AgentRole, AgentCapabilities> = new Map();
private messageQueue: AgentMessage[] = [];
private coordinationHistory: AgentMessage[] = [];
constructor() {
// Initialize all agents
this.agents.set('data', new DataAgent());
this.agents.set('security', new SecurityAgent());
this.agents.set('memory', new MemoryAgent());
this.agents.set('pal', new PalAgent());
this.agents.set('orchestrator', new OrchestratorAgent());
console.log('👥 [AgentTeam] Initialized with 5 role-based agents');
}
/**
* Route message to appropriate agent(s)
*/
public async routeMessage(message: AgentMessage): Promise<any> {
console.log(`📨 [AgentTeam] Routing message from ${message.from} to ${message.to}`);
// If message is to orchestrator, handle directly
if (message.to === 'orchestrator') {
const orchestrator = this.agents.get('orchestrator');
if (orchestrator) {
return await orchestrator.execute(message);
}
}
// If message is to 'all', broadcast
if (message.to === 'all') {
const results: any[] = [];
for (const [role, agent] of this.agents.entries()) {
if (agent.canHandle(message)) {
const result = await agent.execute(message);
results.push(result);
}
}
return { results, broadcast: true };
}
// Route to specific agent
const targetAgent = this.agents.get(message.to as AgentRole);
if (!targetAgent) {
throw new Error(`Agent ${message.to} not found`);
}
if (!targetAgent.canHandle(message)) {
// Try to find alternative agent
for (const [role, agent] of this.agents.entries()) {
if (agent.canHandle(message)) {
console.log(`🔄 [AgentTeam] Rerouting from ${message.to} to ${role}`);
return await agent.execute(message);
}
}
throw new Error(`No agent can handle message: ${message.content}`);
}
return await targetAgent.execute(message);
}
/**
* Coordinate multiple agents for complex task
*/
public async coordinate(task: string, context?: any): Promise<any> {
const coordinationMessage: AgentMessage = {
from: 'orchestrator',
to: 'all',
type: 'coordinate',
content: task,
metadata: context,
timestamp: new Date()
};
this.coordinationHistory.push(coordinationMessage);
// Use orchestrator to coordinate
const orchestrator = this.agents.get('orchestrator');
if (orchestrator) {
const result = await orchestrator.execute(coordinationMessage);
// Log to ProjectMemory
projectMemory.logLifecycleEvent({
eventType: 'other',
status: 'success',
details: {
component: 'AgentTeam',
action: 'coordination',
task,
agentsInvolved: this.agents.size,
timestamp: new Date().toISOString()
}
});
return result;
}
throw new Error('Orchestrator agent not available');
}
/**
* Get status of all agents
*/
public async getAllStatuses(): Promise<AgentStatus[]> {
const statuses: AgentStatus[] = [];
for (const [role, agent] of this.agents.entries()) {
const status = await agent.getStatus();
statuses.push(status);
}
return statuses;
}
/**
* Get agent by role
*/
public getAgent(role: AgentRole): AgentCapabilities | undefined {
return this.agents.get(role);
}
}
export const agentTeam = new AgentTeam();