From eb673790338d3c977e1744e88280e8289cbb6bf7 Mon Sep 17 00:00:00 2001 From: alliscode Date: Fri, 3 Apr 2026 11:17:21 -0700 Subject: [PATCH] Catch agent errors and emit response.failed with real error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, unhandled exceptions from agent execution would bubble up to the SDK orchestrator, which emits a generic 'An internal server error occurred.' message — hiding the actual cause (e.g., 401 auth failures, model not found, etc.). Now AgentFrameworkResponseHandler catches non-cancellation exceptions and emits a proper response.failed event containing the real error message, making it visible to clients and in logs. OperationCanceledException still propagates for proper cancellation handling by the SDK. Also bumps package version to 0.9.0-hosted.260403.2. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dotnet/nuget/nuget-package.props | 2 +- .../FoundryResponsesHosting.csproj | 2 +- .../Hosting/AgentFrameworkResponseHandler.cs | 21 +++++++++++++++++++ .../AgentFrameworkResponseHandlerTests.cs | 19 ++++++++++------- 4 files changed, 35 insertions(+), 9 deletions(-) diff --git a/dotnet/nuget/nuget-package.props b/dotnet/nuget/nuget-package.props index 6d1c657fa8..2cbd1356bc 100644 --- a/dotnet/nuget/nuget-package.props +++ b/dotnet/nuget/nuget-package.props @@ -8,7 +8,7 @@ $(VersionPrefix)-preview.260402.1 $(VersionPrefix) - 0.9.0-hosted.260403.1 + 0.9.0-hosted.260403.2 1.0.0 Debug;Release;Publish diff --git a/dotnet/samples/04-hosting/FoundryResponsesHosting/FoundryResponsesHosting.csproj b/dotnet/samples/04-hosting/FoundryResponsesHosting/FoundryResponsesHosting.csproj index 3dfab4ad48..269754203d 100644 --- a/dotnet/samples/04-hosting/FoundryResponsesHosting/FoundryResponsesHosting.csproj +++ b/dotnet/samples/04-hosting/FoundryResponsesHosting/FoundryResponsesHosting.csproj @@ -6,7 +6,7 @@ enable enable false - $(NoWarn);NU1903;NU1605 + $(NoWarn);NU1903;NU1605;MAAIW001 diff --git a/dotnet/src/Microsoft.Agents.AI.Foundry/Hosting/AgentFrameworkResponseHandler.cs b/dotnet/src/Microsoft.Agents.AI.Foundry/Hosting/AgentFrameworkResponseHandler.cs index 3423a0b4a3..eaacbc67a3 100644 --- a/dotnet/src/Microsoft.Agents.AI.Foundry/Hosting/AgentFrameworkResponseHandler.cs +++ b/dotnet/src/Microsoft.Agents.AI.Foundry/Hosting/AgentFrameworkResponseHandler.cs @@ -95,6 +95,7 @@ public class AgentFrameworkResponseHandler : ResponseHandler while (true) { bool shutdownDetected = false; + ResponseStreamEvent? failedEvent = null; ResponseStreamEvent? evt = null; try { @@ -109,6 +110,26 @@ public class AgentFrameworkResponseHandler : ResponseHandler { shutdownDetected = true; } + catch (Exception ex) when (ex is not OperationCanceledException && !emittedTerminal) + { + // Catch agent execution errors and emit a proper failed event + // with the real error message instead of letting the SDK emit + // a generic "An internal server error occurred." + if (this._logger.IsEnabled(LogLevel.Error)) + { + this._logger.LogError(ex, "Agent execution failed for response {ResponseId}.", context.ResponseId); + } + + failedEvent = stream.EmitFailed( + ResponseErrorCode.ServerError, + ex.Message); + } + + if (failedEvent is not null) + { + yield return failedEvent; + yield break; + } if (shutdownDetected) { diff --git a/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Hosting/AgentFrameworkResponseHandlerTests.cs b/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Hosting/AgentFrameworkResponseHandlerTests.cs index dc38c42739..b1bdd31916 100644 --- a/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Hosting/AgentFrameworkResponseHandlerTests.cs +++ b/dotnet/tests/Microsoft.Agents.AI.Foundry.UnitTests/Hosting/AgentFrameworkResponseHandlerTests.cs @@ -538,7 +538,7 @@ public class AgentFrameworkResponseHandlerTests } [Fact] - public async Task CreateAsync_AgentThrows_ExceptionPropagates() + public async Task CreateAsync_AgentThrows_EmitsFailedEventWithErrorMessage() { // Arrange var agent = new ThrowingAgent(new InvalidOperationException("Agent crashed")); @@ -561,13 +561,18 @@ public class AgentFrameworkResponseHandlerTests mockContext.Setup(x => x.GetInputItemsAsync(It.IsAny())) .ReturnsAsync(Array.Empty()); - // Act & Assert - await Assert.ThrowsAsync(async () => + // Act — collect all events + var events = new List(); + await foreach (var evt in handler.CreateAsync(request, mockContext.Object, CancellationToken.None)) { - await foreach (var _ in handler.CreateAsync(request, mockContext.Object, CancellationToken.None)) - { - } - }); + events.Add(evt); + } + + // Assert — should contain created, in_progress, and failed (with real error message) + Assert.Contains(events, e => e is ResponseCreatedEvent); + Assert.Contains(events, e => e is ResponseInProgressEvent); + var failedEvent = Assert.Single(events.OfType()); + Assert.Contains("Agent crashed", failedEvent.Response.Error.Message); } [Fact]