Skip to content

Fix Activity.Current nulled during streaming tool invocation#7321

Merged
stephentoub merged 4 commits intodotnet:mainfrom
flaviocdc:fix/streaming-activity-current-null
Feb 20, 2026
Merged

Fix Activity.Current nulled during streaming tool invocation#7321
stephentoub merged 4 commits intodotnet:mainfrom
flaviocdc:fix/streaming-activity-current-null

Conversation

@flaviocdc
Copy link
Contributor

@flaviocdc flaviocdc commented Feb 19, 2026

Summary

Fix Activity.Current being set to null during streaming tool invocation when an invoke_agent span with a name suffix is the parent activity.

Fixes #7320
Downstream impact: microsoft/agent-framework#4074

Problem

PR #7224 broadened CurrentActivityIsInvokeAgent to match display names like "invoke_agent MyAgent(id)" (prefix + space). When it matches, the orchestrate_tools activity is not created and the local activity variable is null. The six Activity.Current = activity workaround sites (for dotnet/runtime#47802) in GetStreamingResponseAsync then set Activity.Current = null after each yield return, disconnecting all subsequent spans from the trace.

Fix

Capture the current activity (the invoke_agent parent) before it can be lost:

Activity? activityToRestore = activity ?? Activity.Current;

Then restore that value instead of null after each yield return.

Testing

Added StreamingPreservesTraceContextWhenInvokeAgentWithNameIsParent — a streaming test that creates an invoke_agent MyAgent(agent-123) parent span, triggers LLM call → tool call → second LLM call, and verifies all child spans share the same TraceId. This test fails on main and passes with the fix.

Full M.E.AI test suite: 442 passed, 0 failed across net10.0, net9.0, net8.0, net462.

Fixes dotnet#7320

When an invoke_agent span with a name suffix is the current
activity (e.g. "invoke_agent MyAgent(id)"),
CurrentActivityIsInvokeAgent returns true and the
orchestrate_tools activity is not created. The local
activity variable is null, and all Activity.Current =
activity workaround sites for dotnet/runtime#47802 set
Activity.Current to null after each yield return. This
disconnects subsequent spans from the trace.

Capture the current activity before it can be lost and
restore that value instead of null after each yield.

Co-authored-by: Copilot <[email protected]>
Copilot AI review requested due to automatic review settings February 19, 2026 15:13
@flaviocdc flaviocdc requested a review from a team as a code owner February 19, 2026 15:13
@github-actions github-actions bot added the area-ai Microsoft.Extensions.AI libraries label Feb 19, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request fixes a regression introduced in PR #7224 where Activity.Current was being set to null during streaming tool invocation when an invoke_agent span with a name suffix is the parent activity. When CurrentActivityIsInvokeAgent matches (for names like "invoke_agent MyAgent(id)"), the orchestrate_tools activity is not created and the local activity variable becomes null. The workaround code Activity.Current = activity then disconnects all subsequent spans from the trace after each yield return.

Changes:

  • Captures the current activity before entering the streaming loop: Activity? activityToRestore = activity ?? Activity.Current;
  • Updates all 6 Activity.Current = activity workaround sites to use activityToRestore instead
  • Adds a streaming test that verifies trace context is preserved when an invoke_agent MyAgent(agent-123) parent span is active

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs Captures activityToRestore before streaming loop and uses it to restore Activity.Current after each yield return, preventing trace context loss when activity is null
test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/FunctionInvokingChatClientTests.cs Adds StreamingPreservesTraceContextWhenInvokeAgentWithNameIsParent test that creates an invoke_agent parent span, triggers streaming with tool calls, and verifies all child spans share the same TraceId

@flaviocdc
Copy link
Contributor Author

@dotnet-policy-service agree company="Microsoft"

Use a null check around Activity.Current assignment instead
of capturing a separate activityToRestore variable, per
reviewer feedback.

Co-authored-by: Copilot <[email protected]>
Copy link
Member

@stephentoub stephentoub left a comment

Choose a reason for hiding this comment

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

Thanks!

@stephentoub stephentoub enabled auto-merge (squash) February 19, 2026 22:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-ai Microsoft.Extensions.AI libraries

Projects

None yet

Development

Successfully merging this pull request may close these issues.

FunctionInvokingChatClient streaming sets Activity.Current = null when parent is an invoke_agent <name> span

3 participants