microsoft / microsoft/agent-framework
.NET: [Bug]: ChatClientAgent.RunStreamingAsync ends with no assistant text on multi-tool turns (reasoning model + stateless Responses API)
@giles17 is already working on this.
Since Jun 2, 2026.
- Dominant language
- Python
- Stars
- 13.6k
- Forks
- 2.3k
- Avg merge
- 2d 45m
- Merged PRs (30d)
- 358
Description
Description
What happened?
Using ChatClientAgent.RunStreamingAsync with a reasoning deployment (GPT-5 family) over the Azure Foundry Responses API in stateless mode (AsIChatClientWithStoredOutputDisabled, i.e. StoredOutputEnabled=false), a turn that involves MULTIPLE tool calls frequently ends with NO final assistant TextContent.
- The tools execute fine and return results.
- The continuation request to
/openai/responsesreturns HTTP 200, but the stream produces no answer text. - The last update has
FinishReason = ToolCalls, andOutputTokenCountis tiny (~15–125). - Single-tool / simple turns work correctly. The problem is specific to turns that fan out into several tool calls.
All tools are ordinary invocable AIFunctions created via AIFunctionFactory.Create (no hosted/server-side tools). The framework defaults for MaximumIterationsPerRequest (40) and MaximumConsecutiveErrorsPerRequest (3) are not reached.
What did you expect to happen?
After the tool calls and tool results, the FunctionInvokingChatClient continuation request should return a final assistant message containing answer text. Instead the loop ends on a tool-call turn with no text.
Steps to reproduce
- Create a
ChatClientAgentover a reasoning deployment usingGetResponsesClient().AsIChatClientWithStoredOutputDisabled(deployment)(store=false; reasoning encrypted content included by default). - Register a few invocable function tools and use an
InMemoryChatHistoryProvider. - Stream via
RunStreamingAsyncand ask a question that drives several tool calls in one turn. - Observe: tools run, then the stream ends with
FinishReason=ToolCallsand no assistantTextContent.
Code Sample
[Description("Gets the current weather for a city.")]
static string GetWeather(string city) => $"{city}: 18°C, cloudy";
[Description("Looks up the population of a city.")]
static string GetPopulation(string city) => $"{city}: 1,200,000";
var chatClient = new AzureOpenAIClient(new Uri(endpoint), new AzureKeyCredential(apiKey))
.GetResponsesClient()
.AsIChatClientWithStoredOutputDisabled(deploymentName); // store=false + ReasoningEncryptedContent (default)
var agent = new ChatClientAgent(chatClient, new ChatClientAgentOptions
{
ChatOptions = new ChatOptions
{
Tools = new AITool[]
{
AIFunctionFactory.Create(GetWeather),
AIFunctionFactory.Create(GetPopulation),
}
},
ChatHistoryProvider = new InMemoryChatHistoryProvider()
});
var session = agent.GetNewSession();
// A prompt that drives multiple tool calls in one turn:
await foreach (var update in agent.RunStreamingAsync(
"Compare the weather and population of London and Paris.", session))
{
// On the failing turn: update.Text is empty and
// update.FinishReason == ChatFinishReason.ToolCalls (no final answer text).
Console.Write(update.Text);
}
Error Messages / Stack Traces
No exception is surfaced to the caller on the failing turn — the stream simply ends with no TextContent
(FinishReason=ToolCalls, small OutputTokenCount, continuation request == HTTP 200).
Intermittently, on the failing turn only, disposing the streaming enumerator throws:
System.NotSupportedException: Specified method is not supported.
at Microsoft.Agents.AI.AIAgent.RunStreamingAsync(IEnumerable`1 messages, AgentSession session, AgentRunOptions options, CancellationToken cancellationToken)+System.IAsyncDisposable.DisposeAsync()
Package Versions
Microsoft.Agents.AI: 1.8.0 Microsoft.Agents.AI.OpenAI: 1.8.0 Microsoft.Extensions.AI: 10.5.1 Microsoft.Extensions.AI.OpenAI: 10.5.1 OpenAI: 2.10.0 Azure.AI.OpenAI: 2.9.0-beta.1
.NET Version
.NET 10
Additional Context
Questions:
- Under stateless Responses API + reasoning model + multiple tool calls in STREAMING, is there a known case where the continuation returns HTTP 200 with only a reasoning item and no output text, leaving the loop to end on
FinishReason=ToolCalls? Isreasoning.encrypted_contentexpected to round-trip reliably
through theFunctionInvokingChatClientstreaming loop at these versions? - What causes
AIAgent.RunStreamingAsync's enumeratorDisposeAsyncto throwNotSupportedException? Is it a symptom of an aborted/incomplete inner stream? - Is persisting and replaying reasoning items across turns (via a serialized
AgentSession) supported underStoredOutputEnabled=false, or should reasoning items be excluded before persistence?
The problem reproduces consistently for tool-heavy prompts.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.