mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Catch agent errors and emit response.failed with real error message
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>
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
<PackageVersion Condition="'$(IsReleaseCandidate)' != 'true' AND '$(VersionSuffix)' == ''">$(VersionPrefix)-preview.260402.1</PackageVersion>
|
||||
<PackageVersion Condition="'$(IsReleased)' == 'true'">$(VersionPrefix)</PackageVersion>
|
||||
<!-- Branch-specific override to distinguish from mainline packages -->
|
||||
<PackageVersion>0.9.0-hosted.260403.1</PackageVersion>
|
||||
<PackageVersion>0.9.0-hosted.260403.2</PackageVersion>
|
||||
<GitTag>1.0.0</GitTag>
|
||||
|
||||
<Configurations>Debug;Release;Publish</Configurations>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<CentralPackageTransitivePinningEnabled>false</CentralPackageTransitivePinningEnabled>
|
||||
<NoWarn>$(NoWarn);NU1903;NU1605</NoWarn>
|
||||
<NoWarn>$(NoWarn);NU1903;NU1605;MAAIW001</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
+12
-7
@@ -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<CancellationToken>()))
|
||||
.ReturnsAsync(Array.Empty<OutputItem>());
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(async () =>
|
||||
// Act — collect all events
|
||||
var events = new List<ResponseStreamEvent>();
|
||||
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<ResponseFailedEvent>());
|
||||
Assert.Contains("Agent crashed", failedEvent.Response.Error.Message);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user