Skip to content

Improve streaming timeout handling and keep-alive logic - #950

Merged
MattB-msft merged 11 commits into
mainfrom
users/mbarbour/bizChatTeamsSTreamingFixes
Jul 31, 2026
Merged

Improve streaming timeout handling and keep-alive logic#950
MattB-msft merged 11 commits into
mainfrom
users/mbarbour/bizChatTeamsSTreamingFixes

Conversation

@MattB-msft

@MattB-msft MattB-msft commented Jul 30, 2026

Copy link
Copy Markdown
Member

Enhances StreamingResponse to better handle streaming timeouts and keep-alive messages, especially for M365 Copilot (BizChat). Adds customizable timeout messages, periodic "working" notices, and clearer distinction between user cancellations and timeouts. Refactors interface docs and switches Release debug symbols to portable for improved cross-platform support.

This pull request updates the IStreamingResponse interface to improve support for handling streaming timeouts and cancellation notifications, and makes minor build configuration changes. The main changes are the addition of new properties and methods for timeout messaging and cancellation, and a small update to the build debug type.

Streaming timeout and cancellation handling:

  • Added a StreamingTakingTooLongMessage property to IStreamingResponse to allow specifying a message that is sent to the user when a stream exceeds a timeout.
  • Added a SendStreamTimedOutNotification method to IStreamingResponse to enable sending a final message to the client when a stream is cancelled, without stopping the underlying operation.

Other interface changes:

  • Removed the unused citations parameter comment from the QueueTextChunk method in IStreamingResponse.

Build configuration:

  • Changed the DebugType for Release builds in Build.Shared.props from pdbonly to portable for both AnyCPU and x64 platforms, improving debugging support across platforms. [1] [2]

Enhances StreamingResponse to better handle streaming timeouts and keep-alive messages, especially for M365 Copilot (BizChat). Adds customizable timeout messages, periodic "working" notices, and clearer distinction between user cancellations and timeouts. Refactors interface docs and switches Release debug symbols to portable for improved cross-platform support.
Copilot AI review requested due to automatic review settings July 30, 2026 21:47
@MattB-msft
MattB-msft requested review from a team, ceciliaavila and sw-joelmut as code owners July 30, 2026 21:47
@github-actions github-actions Bot added the ML: Core Tags changes to core libraries label Jul 30, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the Builder’s StreamingResponse / IStreamingResponse surface to better handle channel-specific streaming timeouts (notably M365 Copilot/BizChat) by adding a customizable “taking too long” message, a new API to send a stream-timeout notification without canceling underlying work, and by adjusting streaming timer behavior. It also tweaks Release build PDB generation to improve cross-platform debugging.

Changes:

  • Added timeout/keep-alive behaviors to StreamingResponse (BizChat working notices + timeout handling) and introduced SendStreamTimedOutNotification and StreamingTakingTooLongMessage.
  • Updated IStreamingResponse API surface (new property + method; removed unused citations param from QueueTextChunk).
  • Changed Release DebugType to portable in Build.Shared.props.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/libraries/Builder/Microsoft.Agents.Builder/StreamingResponse.cs Adds BizChat keep-alive/timeout logic, new stream-timeout notification API, and update-vs-send behavior on timeout.
src/libraries/Builder/Microsoft.Agents.Builder/IStreamingResponse.cs Extends interface with timeout message + timeout notification method; removes unused param from QueueTextChunk.
src/Build.Shared.props Switches Release PDB format to portable for better cross-platform debugging.
Comments suppressed due to low confidence (3)

src/libraries/Builder/Microsoft.Agents.Builder/StreamingResponse.cs:817

  • SendIntermediateMessage uses _streamStartTime.Value without a null-guard. If _streamStartTime is cleared concurrently (e.g., ResetAsync disposing the timer while a callback is still queued/running), this can throw inside an async void timer callback and crash the process. Make the timer callback resilient by snapshotting/initializing _streamStartTime before computing elapsed time, and avoid .Value here.
                IActivity activity = null;

                // update run elapsed time
                _streamElapsedTime = DateTime.UtcNow - _streamStartTime.Value;

src/libraries/Builder/Microsoft.Agents.Builder/StreamingResponse.cs:445

  • SendStreamTimedOutNotification calls StopStream() and flips IsStreamingChannel without taking the same lock (this) used by the timer path. This can race with SendIntermediateMessage (which calls _timer.Change(...) under lock) and produce intermittent NullReferenceException/ObjectDisposed failures while streaming is active. Synchronize the stop/disable with the existing lock (and set _queueEmpty so any EndStreamAsync waiter can complete).
            await SendActivityAsync(CreateStreamStoppedMessage(message), cancellationToken).ConfigureAwait(false);
            IsStreamingChannel = false; // Disabled Streaming for this channel / Switch to Async Mode.
            StopStream(); // stop the stream timers
            return true;

src/libraries/Builder/Microsoft.Agents.Builder/StreamingResponse.cs:836

  • BizChat keep-alive logic can queue a "working" notice even when a new text chunk is already pending. At this point in the callback _queue.Count may still be 0 because QueueNextChunkActivity() hasn't run yet, while _messageUpdated may already be true (new content buffered). This can cause redundant keep-alive messages to be injected during active streaming.
                    TimeSpan timeSinceLastPass = DateTime.UtcNow - (_lastPassTime ?? _streamStartTime.Value);
                    if (timeSinceLastPass > BizChatWorkingNoticeInterval
                        && _queue.Count == 0)
                    {

Comment thread src/libraries/Builder/Microsoft.Agents.Builder/StreamingResponse.cs
tracyboehrer
tracyboehrer previously approved these changes Jul 31, 2026
MattB-msft and others added 7 commits July 31, 2026 12:15
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a23f6452-2f7b-436a-adc5-988f577ca1a2
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a23f6452-2f7b-436a-adc5-988f577ca1a2
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: a23f6452-2f7b-436a-adc5-988f577ca1a2
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a23f6452-2f7b-436a-adc5-988f577ca1a2
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: a23f6452-2f7b-436a-adc5-988f577ca1a2
@github-actions github-actions Bot added the ML: Tests Tags changes to tests label Jul 31, 2026
@MattB-msft
MattB-msft enabled auto-merge (squash) July 31, 2026 23:22
@MattB-msft
MattB-msft merged commit f9ec629 into main Jul 31, 2026
11 checks passed
@MattB-msft
MattB-msft deleted the users/mbarbour/bizChatTeamsSTreamingFixes branch July 31, 2026 23:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ML: Core Tags changes to core libraries ML: Tests Tags changes to tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants