coordinator.tsā¢14.4 kB
import { WorksonaAgent, AgentExecutionResult } from '../agents/types';
import { AgentExecutor } from '../agents/executor';
import { AgentRegistry } from '../agents/registry';
import { WorksonaAgentMemory } from './memory';
export type CoordinationType = 'sequential' | 'parallel' | 'review' | 'executive';
export interface WorkflowRequest {
agents: string[];
task: string;
coordination: CoordinationType;
context?: any;
}
export interface WorkflowResult {
coordinationType: CoordinationType;
agents: string[];
results: AgentExecutionResult[];
summary: string;
recommendations: string[];
executionTime: number;
success: boolean;
}
export class WorkflowCoordinator {
constructor(
private agentRegistry: AgentRegistry,
private agentExecutor: AgentExecutor
) {}
async executeWorkflow(request: WorkflowRequest): Promise<WorkflowResult> {
const startTime = Date.now();
console.error(`š Starting ${request.coordination} workflow with agents: ${request.agents.join(', ')}`);
try {
let result: WorkflowResult;
switch (request.coordination) {
case 'sequential':
result = await this.executeSequential(request);
break;
case 'parallel':
result = await this.executeParallel(request);
break;
case 'review':
result = await this.executeReview(request);
break;
case 'executive':
result = await this.executeExecutive(request);
break;
default:
throw new Error(`Unknown coordination type: ${request.coordination}`);
}
result.executionTime = Date.now() - startTime;
result.success = true;
console.error(`ā
${request.coordination} workflow completed in ${result.executionTime}ms`);
return result;
} catch (error) {
console.error(`ā Workflow failed:`, error);
return {
coordinationType: request.coordination,
agents: request.agents,
results: [],
summary: `Workflow failed: ${error instanceof Error ? error.message : String(error)}`,
recommendations: ['Check agent availability', 'Verify request parameters', 'Review error logs'],
executionTime: Date.now() - startTime,
success: false
};
}
}
private async executeSequential(request: WorkflowRequest): Promise<WorkflowResult> {
const results: AgentExecutionResult[] = [];
let cumulativeContext = request.task;
const memory = request.context?.memory || new WorksonaAgentMemory();
for (const agentName of request.agents) {
const agent = this.agentRegistry.getAgent(agentName);
if (!agent) {
console.error(`ā ļø Agent ${agentName} not found, skipping`);
continue;
}
// Each agent builds on the previous agent's work
let enhancedRequest = cumulativeContext;
if (results.length > 0) {
const previousResult = results[results.length - 1];
enhancedRequest += `\\n\\n## Previous Agent Work (${previousResult.agentName})\\n`;
enhancedRequest += previousResult.response.substring(0, 1000);
if (previousResult.response.length > 1000) {
enhancedRequest += '\\n\\n[Previous response truncated for context]';
}
}
const result = await this.agentExecutor.executeAgent(agent, enhancedRequest, {
availableTools: agent.requirements.tools,
memory,
projectContext: request.context?.project_context
});
results.push(result);
// Update cumulative context for next agent
cumulativeContext = enhancedRequest;
}
return {
coordinationType: 'sequential',
agents: request.agents,
results,
summary: this.generateSequentialSummary(results),
recommendations: this.extractRecommendations(results),
executionTime: 0, // Will be set by caller
success: true
};
}
private async executeParallel(request: WorkflowRequest): Promise<WorkflowResult> {
const agents = request.agents
.map(name => this.agentRegistry.getAgent(name))
.filter(agent => agent !== undefined) as WorksonaAgent[];
const memory = request.context?.memory || new WorksonaAgentMemory();
// Execute all agents simultaneously
const promises = agents.map(agent =>
this.agentExecutor.executeAgent(agent, request.task, {
availableTools: agent.requirements.tools,
memory,
projectContext: request.context?.project_context
})
);
const results = await Promise.all(promises);
return {
coordinationType: 'parallel',
agents: request.agents,
results,
summary: this.generateParallelSummary(results),
recommendations: this.extractRecommendations(results),
executionTime: 0, // Will be set by caller
success: true
};
}
private async executeReview(request: WorkflowRequest): Promise<WorkflowResult> {
if (request.agents.length < 2) {
throw new Error('Review workflow requires at least 2 agents');
}
// First agent provides initial work
const primaryAgent = this.agentRegistry.getAgent(request.agents[0]);
if (!primaryAgent) throw new Error(`Primary agent ${request.agents[0]} not found`);
const memory = request.context?.memory || new WorksonaAgentMemory();
const initialResult = await this.agentExecutor.executeAgent(primaryAgent, request.task, {
availableTools: primaryAgent.requirements.tools,
memory,
projectContext: request.context?.project_context
});
const results = [initialResult];
// Other agents review and provide feedback
for (let i = 1; i < request.agents.length; i++) {
const reviewerAgent = this.agentRegistry.getAgent(request.agents[i]);
if (!reviewerAgent) {
console.error(`ā ļø Reviewer agent ${request.agents[i]} not found, skipping`);
continue;
}
const reviewRequest = `Please review the following work and provide detailed feedback, suggestions for improvement, and validation:\\n\\n## Original Task\\n${request.task}\\n\\n## Work to Review\\n${initialResult.response}`;
const reviewResult = await this.agentExecutor.executeAgent(reviewerAgent, reviewRequest, {
availableTools: reviewerAgent.requirements.tools,
memory,
projectContext: request.context?.project_context
});
results.push(reviewResult);
}
return {
coordinationType: 'review',
agents: request.agents,
results,
summary: this.generateReviewSummary(results),
recommendations: this.extractRecommendations(results),
executionTime: 0, // Will be set by caller
success: true
};
}
private async executeExecutive(request: WorkflowRequest): Promise<WorkflowResult> {
// Executive coordination involves C-suite agents for strategic oversight
const executiveAgents = request.agents.filter(name =>
name.includes('ceo') || name.includes('cto') || name.includes('cfo') ||
name.includes('board') || name.includes('investor')
);
const operationalAgents = request.agents.filter(name =>
!executiveAgents.includes(name)
);
const memory = request.context?.memory || new WorksonaAgentMemory();
const allResults: AgentExecutionResult[] = [];
// Executive briefing first
if (executiveAgents.length > 0) {
console.error(`š Executive briefing with: ${executiveAgents.join(', ')}`);
for (const agentName of executiveAgents) {
const agent = this.agentRegistry.getAgent(agentName);
if (!agent) continue;
const execRequest = `## Executive Briefing Required\\n\\n**Strategic Initiative**: ${request.task}\\n\\nPlease provide executive-level guidance including:\\n- Strategic alignment assessment\\n- Resource allocation recommendations\\n- Risk evaluation\\n- Success criteria definition\\n- Stakeholder considerations`;
const result = await this.agentExecutor.executeAgent(agent, execRequest, {
availableTools: agent.requirements.tools,
memory,
projectContext: request.context?.project_context
});
allResults.push(result);
}
}
// Operational execution based on executive guidance
if (operationalAgents.length > 0) {
console.error(`āļø Operational execution with: ${operationalAgents.join(', ')}`);
const executiveGuidance = allResults.length > 0
? allResults.map(r => `**${r.agentName}**: ${r.response.substring(0, 300)}...`).join('\\n\\n')
: 'No executive guidance provided';
for (const agentName of operationalAgents) {
const agent = this.agentRegistry.getAgent(agentName);
if (!agent) continue;
const contextualRequest = `## Task with Executive Guidance\\n\\n**Primary Task**: ${request.task}\\n\\n**Executive Guidance**:\\n${executiveGuidance}\\n\\n**Your Role**: Execute the task following executive guidance and strategic direction provided above.`;
const result = await this.agentExecutor.executeAgent(agent, contextualRequest, {
availableTools: agent.requirements.tools,
memory,
projectContext: request.context?.project_context
});
allResults.push(result);
}
}
return {
coordinationType: 'executive',
agents: request.agents,
results: allResults,
summary: this.generateExecutiveSummary(allResults, executiveAgents.length),
recommendations: this.extractExecutiveRecommendations(allResults),
executionTime: 0, // Will be set by caller
success: true
};
}
private generateSequentialSummary(results: AgentExecutionResult[]): string {
if (results.length === 0) return 'No agents executed successfully.';
const agentNames = results.map(r => r.agentName);
return `Sequential workflow completed with ${results.length} agents working in sequence. Each agent built upon the previous work: ${agentNames.join(' ā ')}, creating a comprehensive integrated solution.`;
}
private generateParallelSummary(results: AgentExecutionResult[]): string {
if (results.length === 0) return 'No agents executed successfully.';
const agentNames = results.map(r => r.agentName);
return `Parallel workflow completed with ${results.length} agents working simultaneously on different aspects of the task: ${agentNames.join(', ')}. Results can be integrated for a comprehensive solution.`;
}
private generateReviewSummary(results: AgentExecutionResult[]): string {
if (results.length === 0) return 'No agents executed successfully.';
const primaryAgent = results[0].agentName;
const reviewers = results.slice(1).map(r => r.agentName);
if (reviewers.length === 0) {
return `Review workflow completed with initial work by ${primaryAgent}. No reviewers provided feedback.`;
}
return `Review workflow completed. Initial work provided by ${primaryAgent}, reviewed and validated by ${reviewers.length} specialist(s): ${reviewers.join(', ')}.`;
}
private generateExecutiveSummary(results: AgentExecutionResult[], execCount: number): string {
if (results.length === 0) return 'No agents executed successfully.';
const opCount = results.length - execCount;
return `Executive workflow completed with ${execCount} executive-level agent(s) providing strategic guidance and ${opCount} operational agent(s) executing the strategy. Ready for board presentation and stakeholder communication.`;
}
private extractRecommendations(results: AgentExecutionResult[]): string[] {
const recommendations: string[] = [];
// Extract recommendations from agent responses
results.forEach(result => {
result.metadata.suggestedNextAgents.forEach(agent => {
const rec = `Consider consulting with: ${agent}`;
if (!recommendations.includes(rec)) {
recommendations.push(rec);
}
});
// Extract recommendations from response content
const recommendationSections = result.response.match(/## (?:Recommendations?|Next Steps)[\\s\\S]*?(?=##|$)/gi);
if (recommendationSections) {
recommendationSections.forEach(section => {
const lines = section.split('\\n').filter(line => line.startsWith('- '));
lines.forEach(line => {
const rec = line.substring(2).trim();
if (rec && !recommendations.includes(rec) && recommendations.length < 8) {
recommendations.push(rec);
}
});
});
}
});
return recommendations.slice(0, 5);
}
private extractExecutiveRecommendations(results: AgentExecutionResult[]): string[] {
const recommendations = this.extractRecommendations(results);
// Add executive-specific recommendations
const executiveRecs = [
'Schedule board presentation of results',
'Prepare stakeholder communication plan',
'Define success metrics and KPIs',
'Establish project governance structure'
];
executiveRecs.forEach(rec => {
if (!recommendations.includes(rec) && recommendations.length < 8) {
recommendations.push(rec);
}
});
return recommendations;
}
// Utility method to suggest optimal coordination type based on agents and task
suggestCoordinationType(agents: string[], task: string): CoordinationType {
const taskLower = task.toLowerCase();
// Executive coordination if C-suite agents are involved
if (agents.some(agent => agent.includes('ceo') || agent.includes('board') || agent.includes('investor'))) {
return 'executive';
}
// Review coordination for quality assurance tasks
if (taskLower.includes('review') || taskLower.includes('audit') || taskLower.includes('validate')) {
return 'review';
}
// Sequential for complex multi-step tasks
if (taskLower.includes('implement') || taskLower.includes('build') || taskLower.includes('create')) {
return 'sequential';
}
// Parallel for analysis and research tasks
if (taskLower.includes('research') || taskLower.includes('analyze') || taskLower.includes('compare')) {
return 'parallel';
}
// Default to sequential for unknown tasks
return 'sequential';
}
}