1313namespace FlowVision . lib . Classes
1414{
1515 /// <summary>
16- /// Multi-agent actioner that coordinates between a planner agent and an execution agent
16+ /// Multi-agent actioner that coordinates between a coordinator, planner agent and an execution agent
1717 /// </summary>
1818 public class MultiAgentActioner
1919 {
20+ private IChatCompletionService coordinatorChat ;
2021 private IChatCompletionService plannerChat ;
2122 private IChatCompletionService executorChat ;
23+ private ChatHistory coordinatorHistory ;
2224 private ChatHistory plannerHistory ;
2325 private ChatHistory executorHistory ;
26+ private Kernel coordinatorKernel ;
2427 private Kernel plannerKernel ;
2528 private Kernel executorKernel ;
29+ private AgentCoordinator agentCoordinator ;
2630
2731 // Configuration constants
2832 private const string TOOL_CONFIG = "toolsconfig" ;
@@ -33,8 +37,10 @@ public class MultiAgentActioner
3337
3438 public MultiAgentActioner ( Form1 . PluginOutputHandler outputHandler )
3539 {
40+ coordinatorHistory = new ChatHistory ( ) ;
3641 plannerHistory = new ChatHistory ( ) ;
3742 executorHistory = new ChatHistory ( ) ;
43+ agentCoordinator = new AgentCoordinator ( ) ;
3844
3945 // Load tool configuration when the MultiAgentActioner is initialized
4046 toolConfig = ToolConfig . LoadConfig ( TOOL_CONFIG ) ;
@@ -73,20 +79,33 @@ public async Task<string> ExecuteAction(string actionPrompt)
7379 toolConfig = ToolConfig . LoadConfig ( TOOL_CONFIG ) ;
7480
7581 PluginLogger . NotifyTaskStart ( "Multi-Agent Action" , "Planning and executing your request" ) ;
76- PluginLogger . StartLoadingIndicator ( "planning " ) ;
82+ PluginLogger . StartLoadingIndicator ( "coordination " ) ;
7783
7884 try
7985 {
80- // Configure planner first
86+ // Configure coordinator first
87+ coordinatorHistory . Clear ( ) ;
88+ coordinatorHistory . AddSystemMessage ( toolConfig . CoordinatorSystemPrompt ) ;
89+ coordinatorHistory . AddUserMessage ( actionPrompt ) ;
90+
91+ // Configure planner for later use
8192 plannerHistory . Clear ( ) ;
8293 plannerHistory . AddSystemMessage ( toolConfig . PlannerSystemPrompt ) ;
83- plannerHistory . AddUserMessage ( actionPrompt ) ;
84-
94+
8595 // Configure executor for later use
8696 executorHistory . Clear ( ) ;
8797 executorHistory . AddSystemMessage ( toolConfig . ExecutorSystemPrompt ) ;
8898
99+ // Clear agent coordinator message history
100+ agentCoordinator . Clear ( ) ;
101+ agentCoordinator . AddMessage ( AgentRole . User , AgentRole . Coordinator ,
102+ "USER_REQUEST" , actionPrompt ) ;
103+
89104 // Load model configurations - use either custom configs or default
105+ APIConfig coordinatorConfig = toolConfig . UseCustomCoordinatorConfig
106+ ? APIConfig . LoadConfig ( toolConfig . CoordinatorConfigName )
107+ : APIConfig . LoadConfig ( ACTIONER_CONFIG ) ;
108+
90109 APIConfig plannerConfig = toolConfig . UseCustomPlannerConfig
91110 ? APIConfig . LoadConfig ( toolConfig . PlannerConfigName )
92111 : APIConfig . LoadConfig ( ACTIONER_CONFIG ) ;
@@ -95,6 +114,15 @@ public async Task<string> ExecuteAction(string actionPrompt)
95114 ? APIConfig . LoadConfig ( toolConfig . ExecutorConfigName )
96115 : APIConfig . LoadConfig ( ACTIONER_CONFIG ) ;
97116
117+ // Verify coordinator config
118+ if ( string . IsNullOrWhiteSpace ( coordinatorConfig . DeploymentName ) ||
119+ string . IsNullOrWhiteSpace ( coordinatorConfig . EndpointURL ) ||
120+ string . IsNullOrWhiteSpace ( coordinatorConfig . APIKey ) )
121+ {
122+ PluginLogger . NotifyTaskComplete ( "Multi-Agent Action" , false ) ;
123+ return "Error: Coordinator model not configured" ;
124+ }
125+
98126 // Verify planner config
99127 if ( string . IsNullOrWhiteSpace ( plannerConfig . DeploymentName ) ||
100128 string . IsNullOrWhiteSpace ( plannerConfig . EndpointURL ) ||
@@ -113,6 +141,16 @@ public async Task<string> ExecuteAction(string actionPrompt)
113141 return "Error: Executor model not configured" ;
114142 }
115143
144+ // Setup the kernel for coordinator (no tools, only coordination capabilities)
145+ var coordinatorBuilder = Kernel . CreateBuilder ( ) ;
146+ coordinatorBuilder . AddAzureOpenAIChatCompletion (
147+ coordinatorConfig . DeploymentName ,
148+ coordinatorConfig . EndpointURL ,
149+ coordinatorConfig . APIKey ) ;
150+
151+ coordinatorKernel = coordinatorBuilder . Build ( ) ;
152+ coordinatorChat = coordinatorKernel . GetRequiredService < IChatCompletionService > ( ) ;
153+
116154 // Setup the kernel for planner (no tools, only planning capabilities)
117155 var plannerBuilder = Kernel . CreateBuilder ( ) ;
118156 plannerBuilder . AddAzureOpenAIChatCompletion (
@@ -164,12 +202,18 @@ public async Task<string> ExecuteAction(string actionPrompt)
164202 executorKernel = executorBuilder . Build ( ) ;
165203 executorChat = executorKernel . GetRequiredService < IChatCompletionService > ( ) ;
166204
167- // Get initial plan from planner agent
205+ // Get initial coordination from coordinator agent
168206 PluginLogger . StopLoadingIndicator ( ) ;
169- PluginLogger . LogPluginUsage ( "🧠 Planning approach ..." ) ;
170- PluginLogger . StartLoadingIndicator ( "planning " ) ;
207+ PluginLogger . LogPluginUsage ( "🗣️ Coordinating request ..." ) ;
208+ PluginLogger . StartLoadingIndicator ( "coordination " ) ;
171209
172- var planSettings = new OpenAIPromptExecutionSettings
210+ var coordinatorSettings = new OpenAIPromptExecutionSettings
211+ {
212+ Temperature = 0.2 ,
213+ // No tools for coordinator
214+ } ;
215+
216+ var plannerSettings = new OpenAIPromptExecutionSettings
173217 {
174218 Temperature = 0.2 ,
175219 // No tools for planner
@@ -183,15 +227,34 @@ public async Task<string> ExecuteAction(string actionPrompt)
183227 : ToolCallBehavior . EnableKernelFunctions
184228 } ;
185229
230+ // Get the initial coordination
231+ string coordinatorResponse = await GetAgentResponseAsync ( coordinatorChat , coordinatorHistory , coordinatorSettings , coordinatorKernel ) ;
232+ PluginLogger . LogPluginUsage ( "🎯 Coordinator Assessment:\n " + coordinatorResponse ) ;
233+
234+ agentCoordinator . AddMessage ( AgentRole . Coordinator , AgentRole . Planner ,
235+ "COORDINATION_RESPONSE" , coordinatorResponse ) ;
236+
237+ // Send the task to the planner
238+ plannerHistory . AddUserMessage ( coordinatorResponse ) ;
239+
240+ PluginLogger . StopLoadingIndicator ( ) ;
241+ PluginLogger . LogPluginUsage ( "🧠 Planning approach..." ) ;
242+ PluginLogger . StartLoadingIndicator ( "planning" ) ;
243+
186244 // Get the initial plan
187- string plan = await GetAgentResponseAsync ( plannerChat , plannerHistory , planSettings , plannerKernel ) ;
245+ string plan = await GetAgentResponseAsync ( plannerChat , plannerHistory , plannerSettings , plannerKernel ) ;
188246 PluginLogger . LogPluginUsage ( "📝 Initial Plan:\n " + plan ) ;
189247
248+ agentCoordinator . AddMessage ( AgentRole . Planner , AgentRole . Executor ,
249+ "PLAN_RESPONSE" , plan ) ;
250+
190251 // Now execute the plan step by step
191252 bool isComplete = false ;
192253 int maxIterations = 10 ; // Safety limit
193254 int currentIteration = 0 ;
194255 string finalResult = "" ;
256+ // Store all execution results for final response
257+ List < string > executionResults = new List < string > ( ) ;
195258
196259 while ( ! isComplete && currentIteration < maxIterations )
197260 {
@@ -201,15 +264,24 @@ public async Task<string> ExecuteAction(string actionPrompt)
201264 // Ask executor to perform the current step
202265 executorHistory . AddUserMessage ( $ "Please execute the following step of our plan: { plan } ") ;
203266
267+ agentCoordinator . AddMessage ( AgentRole . Planner , AgentRole . Executor ,
268+ "EXECUTION_REQUEST" , plan ) ;
269+
204270 PluginLogger . StopLoadingIndicator ( ) ;
205271 PluginLogger . LogPluginUsage ( "🔧 Executing step..." ) ;
206272 PluginLogger . StartLoadingIndicator ( "executing" ) ;
207273
208274 // Get executor response with tools
209275 string executionResult = await GetAgentResponseAsync ( executorChat , executorHistory , executorSettings , executorKernel ) ;
210276
277+ // Store the execution result for the final response
278+ executionResults . Add ( executionResult ) ;
279+
211280 PluginLogger . LogPluginUsage ( "📊 Execution result:\n " + executionResult ) ;
212281
282+ agentCoordinator . AddMessage ( AgentRole . Executor , AgentRole . Planner ,
283+ "EXECUTION_RESPONSE" , executionResult ) ;
284+
213285 // Add the execution result to the planner's history
214286 plannerHistory . AddUserMessage ( $ "The executor agent performed the requested step. Here is the result:\n \n { executionResult } \n \n Is the task fully completed, or do we need additional steps? If additional steps are needed, provide just the next step to execute. If the task is complete, respond with 'TASK COMPLETED' followed by a summary of what was accomplished.") ;
215287
@@ -218,16 +290,39 @@ public async Task<string> ExecuteAction(string actionPrompt)
218290 PluginLogger . StartLoadingIndicator ( "planning" ) ;
219291
220292 // Get planner's evaluation of the result
221- plan = await GetAgentResponseAsync ( plannerChat , plannerHistory , planSettings , plannerKernel ) ;
293+ plan = await GetAgentResponseAsync ( plannerChat , plannerHistory , plannerSettings , plannerKernel ) ;
294+
295+ agentCoordinator . AddMessage ( AgentRole . Planner , AgentRole . Coordinator ,
296+ "STATUS_UPDATE" , plan ) ;
222297
223298 // Check if the task is complete
224299 if ( plan . Contains ( "TASK COMPLETED" ) )
225300 {
226301 isComplete = true ;
227- finalResult = plan ;
302+
303+ // Extract the summary from the "TASK COMPLETED" message
304+ string taskSummary = plan . Replace ( "TASK COMPLETED" , "" ) . Trim ( ) ;
305+
306+ // Send all execution results to the coordinator for final formatting
307+ string executionSummary = string . Join ( "\n \n " , executionResults ) ;
308+
309+ coordinatorHistory . AddUserMessage ( $ "The task has been completed. Here are the detailed results from execution:\n \n { executionSummary } \n \n Please provide a comprehensive response for the user that includes the actual results and information obtained during execution. Do not include phrases like 'TASK_COMPLETE' or similar tags.") ;
310+
311+ PluginLogger . StopLoadingIndicator ( ) ;
312+ PluginLogger . LogPluginUsage ( "✅ Task completed, generating detailed response..." ) ;
313+ PluginLogger . StartLoadingIndicator ( "coordination" ) ;
314+
315+ // Get coordinator's final response with detailed results
316+ finalResult = await GetAgentResponseAsync ( coordinatorChat , coordinatorHistory , coordinatorSettings , coordinatorKernel ) ;
317+
318+ // Store this as a completed response but without the TASK_COMPLETE tag
319+ agentCoordinator . AddMessage ( AgentRole . Coordinator , AgentRole . User ,
320+ "USER_RESPONSE" , finalResult ) ;
321+ }
322+ else
323+ {
324+ PluginLogger . LogPluginUsage ( "🔍 Progress evaluation:\n " + plan ) ;
228325 }
229-
230- PluginLogger . LogPluginUsage ( "🔍 Progress evaluation:\n " + plan ) ;
231326 }
232327
233328 PluginLogger . StopLoadingIndicator ( ) ;
@@ -239,8 +334,24 @@ public async Task<string> ExecuteAction(string actionPrompt)
239334 }
240335 else
241336 {
337+ // Compile all execution results into a comprehensive response
338+ string allResults = string . Join ( "\n \n " , executionResults ) ;
339+
340+ // Get coordinator to explain the incomplete task status with the results
341+ coordinatorHistory . AddUserMessage ( $ "The task could not be completed within { maxIterations } iterations, but here are the execution results so far:\n \n { allResults } \n \n Please provide a detailed response for the user that contains all the information gathered, even though the task wasn't fully completed.") ;
342+
343+ PluginLogger . LogPluginUsage ( "⚠️ Maximum iterations reached, generating explanation with results..." ) ;
344+ PluginLogger . StartLoadingIndicator ( "coordination" ) ;
345+
346+ // Get coordinator's explanation with detailed results
347+ string resultWithExplanation = await GetAgentResponseAsync ( coordinatorChat , coordinatorHistory , coordinatorSettings , coordinatorKernel ) ;
348+
349+ agentCoordinator . AddMessage ( AgentRole . Coordinator , AgentRole . User ,
350+ "STATUS_UPDATE" , resultWithExplanation ) ;
351+
352+ PluginLogger . StopLoadingIndicator ( ) ;
242353 PluginLogger . NotifyTaskComplete ( "Multi-Agent Action" , false ) ;
243- return $ "Task execution reached maximum iterations ( { maxIterations } ) without completion. Last status: { plan } " ;
354+ return resultWithExplanation ;
244355 }
245356 }
246357 catch ( Exception ex )
@@ -283,18 +394,23 @@ private async Task<string> GetAgentResponseAsync(
283394
284395 internal void SetChatHistory ( List < LocalChatMessage > chatHistory )
285396 {
397+ // Set up coordinator history with system prompt
398+ coordinatorHistory . Clear ( ) ;
399+ coordinatorHistory . AddSystemMessage ( toolConfig . CoordinatorSystemPrompt ) ;
400+
401+ // Set up planner history with system prompt
286402 plannerHistory . Clear ( ) ;
287403 plannerHistory . AddSystemMessage ( toolConfig . PlannerSystemPrompt ) ;
288404
289405 foreach ( var message in chatHistory )
290406 {
291407 if ( message . Author == "You" )
292408 {
293- plannerHistory . AddUserMessage ( message . Content ) ;
409+ coordinatorHistory . AddUserMessage ( message . Content ) ;
294410 }
295411 else if ( message . Author == "AI" )
296412 {
297- plannerHistory . AddAssistantMessage ( message . Content ) ;
413+ coordinatorHistory . AddAssistantMessage ( message . Content ) ;
298414 }
299415 }
300416 }
0 commit comments