diff --git a/dotnet/samples/03-workflows/Agents/CustomAgentExecutors/Program.cs b/dotnet/samples/03-workflows/Agents/CustomAgentExecutors/Program.cs
index e2dec8505b..41b622fdad 100644
--- a/dotnet/samples/03-workflows/Agents/CustomAgentExecutors/Program.cs
+++ b/dotnet/samples/03-workflows/Agents/CustomAgentExecutors/Program.cs
@@ -61,6 +61,12 @@ public static class Program
{
Console.WriteLine($"{outputEvent}");
}
+
+ if (evt is WorkflowErrorEvent errorEvent)
+ {
+ Console.WriteLine($"Workflow error: {errorEvent.Exception?.Message}");
+ Console.WriteLine($"Details: {errorEvent.Exception}");
+ }
}
}
}
@@ -175,7 +181,9 @@ internal sealed class FeedbackEvent(FeedbackResult feedbackResult) : WorkflowEve
///
/// A custom executor that uses an AI agent to provide feedback on a slogan.
///
-internal sealed class FeedbackExecutor : Executor
+[SendsMessage(typeof(FeedbackResult))]
+[YieldsOutput(typeof(string))]
+internal sealed partial class FeedbackExecutor : Executor
{
private readonly AIAgent _agent;
private AgentSession? _session;
diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows.Generators/Analysis/SemanticAnalyzer.cs b/dotnet/src/Microsoft.Agents.AI.Workflows.Generators/Analysis/SemanticAnalyzer.cs
index b62377a971..c116587507 100644
--- a/dotnet/src/Microsoft.Agents.AI.Workflows.Generators/Analysis/SemanticAnalyzer.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Workflows.Generators/Analysis/SemanticAnalyzer.cs
@@ -212,6 +212,7 @@ internal static class SemanticAnalyzer
bool isPartialClass = IsPartialClass(classSymbol, cancellationToken);
bool derivesFromExecutor = DerivesFromExecutor(classSymbol);
bool hasManualConfigureProtocol = HasConfigureProtocolDefined(classSymbol);
+ bool baseHasConfigureProtocol = BaseHasConfigureProtocol(classSymbol);
string? @namespace = classSymbol.ContainingNamespace?.IsGlobalNamespace == true
? null
@@ -241,6 +242,7 @@ internal static class SemanticAnalyzer
isPartialClass,
derivesFromExecutor,
hasManualConfigureProtocol,
+ baseHasConfigureProtocol,
classLocation,
typeName,
attributeKind));
@@ -321,7 +323,7 @@ internal static class SemanticAnalyzer
first.GenericParameters,
first.IsNested,
first.ContainingTypeChain,
- BaseHasConfigureProtocol: false, // Not relevant for protocol-only
+ first.BaseHasConfigureProtocol,
Handlers: ImmutableEquatableArray.Empty,
ClassSendTypes: new ImmutableEquatableArray(sendTypes.ToImmutable()),
ClassYieldTypes: new ImmutableEquatableArray(yieldTypes.ToImmutable()));
diff --git a/dotnet/src/Microsoft.Agents.AI.Workflows.Generators/Models/ClassProtocolInfo.cs b/dotnet/src/Microsoft.Agents.AI.Workflows.Generators/Models/ClassProtocolInfo.cs
index df9205cc5f..90e5762890 100644
--- a/dotnet/src/Microsoft.Agents.AI.Workflows.Generators/Models/ClassProtocolInfo.cs
+++ b/dotnet/src/Microsoft.Agents.AI.Workflows.Generators/Models/ClassProtocolInfo.cs
@@ -16,6 +16,7 @@ namespace Microsoft.Agents.AI.Workflows.Generators.Models;
/// Whether the class is declared as partial.
/// Whether the class derives from Executor.
/// Whether the class has a manually defined ConfigureRoutes method.
+/// Whether a base class already overrides ConfigureProtocol.
/// Location info for diagnostics.
/// The fully qualified type name from the attribute.
/// Whether this is from a SendsMessage or YieldsOutput attribute.
@@ -29,6 +30,7 @@ internal sealed record ClassProtocolInfo(
bool IsPartialClass,
bool DerivesFromExecutor,
bool HasManualConfigureRoutes,
+ bool BaseHasConfigureProtocol,
DiagnosticLocationInfo? ClassLocation,
string TypeName,
ProtocolAttributeKind AttributeKind)
@@ -38,5 +40,5 @@ internal sealed record ClassProtocolInfo(
///
public static ClassProtocolInfo Empty { get; } = new(
string.Empty, null, string.Empty, null, false, string.Empty,
- false, false, false, null, string.Empty, ProtocolAttributeKind.Send);
+ false, false, false, false, null, string.Empty, ProtocolAttributeKind.Send);
}