@@ -101,6 +101,7 @@ protected override ProtocolBuilder ConfigureProtocol(ProtocolBuilder protocolBui
101101 return base . ConfigureProtocol ( protocolBuilder )
102102 . SendsMessage < ChatMessage > ( )
103103 . SendsMessage < ResetChatSignal > ( )
104+ . YieldsOutput < List < ChatMessage > > ( )
104105 . ConfigureRoutes ( ConfigureRoutes ) ;
105106
106107 void ConfigureRoutes ( RouteBuilder routeBuilder ) => routeBuilder . AddPortHandler < MagenticPlanReviewRequest , MagenticPlanReviewResponse > (
@@ -109,15 +110,15 @@ void ConfigureRoutes(RouteBuilder routeBuilder) => routeBuilder.AddPortHandler<M
109110 out this . _planReviewPort ) ;
110111 }
111112
112- private ValueTask SubmitPlanReviewRequestAsync ( MagenticTaskContext taskContext , IWorkflowContext workflowContext )
113+ private ValueTask SubmitPlanReviewRequestAsync ( MagenticTaskContext taskContext , IWorkflowContext workflowContext , bool replanAfterStall = false )
113114 {
114115 MagenticProgressLedger ? progressLedger = taskContext . ProgressLedger ;
115116 if ( progressLedger ? . IsStarted is not true )
116117 {
117118 progressLedger = null ;
118119 }
119120
120- MagenticPlanReviewRequest request = new ( taskContext . TaskLedger ! . CurrentPlan , progressLedger , taskContext . IsStalled ) ;
121+ MagenticPlanReviewRequest request = new ( taskContext . TaskLedger ! . CurrentPlan , progressLedger , replanAfterStall ) ;
121122
122123 return this . _planReviewPort ! . PostRequestAsync ( request ) ;
123124 }
@@ -146,7 +147,7 @@ to the conversation and enters the inner loop.
146147
147148 if ( this . _taskContext . IsTerminated )
148149 {
149- throw new InvalidOperationException ( "Magentic Orchestration has already been terminated and cannot process new messages. Please start a new session ." ) ;
150+ throw new InvalidOperationException ( "This Magentic orchestration has already terminated. To process new messages, create a new workflow instance ." ) ;
150151 }
151152
152153 if ( response . IsApproved )
@@ -161,7 +162,7 @@ to the conversation and enters the inner loop.
161162 }
162163 }
163164
164- private async ValueTask UpdatePlanAndDelegateAsync ( MagenticTaskContext taskContext , IWorkflowContext context , CancellationToken cancellationToken )
165+ private async ValueTask UpdatePlanAndDelegateAsync ( MagenticTaskContext taskContext , IWorkflowContext context , CancellationToken cancellationToken , bool replanAfterStall = false )
165166 {
166167 bool isReplan = taskContext . TaskLedger != null ;
167168
@@ -177,7 +178,7 @@ await context.AddEventAsync(isReplan
177178
178179 if ( requirePlanSignoff )
179180 {
180- await this . SubmitPlanReviewRequestAsync ( taskContext , context ) . ConfigureAwait ( false ) ;
181+ await this . SubmitPlanReviewRequestAsync ( taskContext , context , replanAfterStall ) . ConfigureAwait ( false ) ;
181182 }
182183 else
183184 {
@@ -187,9 +188,22 @@ await context.AddEventAsync(isReplan
187188
188189 protected override async ValueTask TakeTurnAsync ( List < ChatMessage > messages , IWorkflowContext context , bool ? emitEvents , CancellationToken cancellationToken = default )
189190 {
190- // First Turn: Initialize the task context and send the initial messages to the planner agent
191- this . _taskContext ??= new ( messages , team , limits , emitEvents , [ ] ) ;
192- await this . UpdatePlanAndDelegateAsync ( this . _taskContext , context , cancellationToken ) . ConfigureAwait ( false ) ;
191+ if ( this . _taskContext ? . IsTerminated == true )
192+ {
193+ throw new InvalidOperationException ( "This Magentic orchestration has already terminated. To process new messages, create a new workflow instance." ) ;
194+ }
195+
196+ if ( this . _taskContext == null )
197+ {
198+ // First Turn: Initialize the task context and create the initial plan
199+ this . _taskContext = new ( messages , team , limits , emitEvents , [ ] ) ;
200+ await this . UpdatePlanAndDelegateAsync ( this . _taskContext , context , cancellationToken ) . ConfigureAwait ( false ) ;
201+ }
202+ else
203+ {
204+ // Subsequent turns: agent returned control, go directly to coordination (progress ledger only, no replan)
205+ await this . RunCoordinationRoundAsync ( this . _taskContext , context , cancellationToken ) . ConfigureAwait ( false ) ;
206+ }
193207 }
194208
195209 private ChatMessage ? _fullTaskLedgerMessage ;
@@ -288,10 +302,11 @@ await context.AddEventAsync(new WorkflowWarningEvent($"Invalid next speaker: {ne
288302
289303 private async ValueTask ResetAndReplanAsync ( MagenticTaskContext taskContext , IWorkflowContext context , CancellationToken cancellationToken )
290304 {
305+ bool wasStalled = taskContext . IsStalled ;
291306 taskContext . Reset ( ) ;
292307 await context . SendMessageAsync ( new ResetChatSignal ( ) , cancellationToken : cancellationToken ) . ConfigureAwait ( false ) ;
293308
294- await this . UpdatePlanAndDelegateAsync ( taskContext , context , cancellationToken ) . ConfigureAwait ( false ) ;
309+ await this . UpdatePlanAndDelegateAsync ( taskContext , context , cancellationToken , replanAfterStall : wasStalled ) . ConfigureAwait ( false ) ;
295310 }
296311
297312 private async ValueTask PrepareFinalAnswerAsync ( MagenticTaskContext taskContext , IWorkflowContext context , CancellationToken cancellationToken )
0 commit comments