microsoft / microsoft/agent-framework
.NET: [Bug]: ChatClientAgent drops ResponseFormat before invoking underlying IChatClient
@moonbox3 is already working on this.
Since Sep 13, 2026.
- Dominant language
- Python
- Stars
- 13.6k
- Forks
- 2.3k
- Avg merge
- 2d 45m
- Merged PRs (30d)
- 358
Description
### Description
### Minimal reproduction
The issue can be reproduced without relying on any provider-specific behavior.
A decorating `IChatClient` captures the `ChatOptions` that ultimately reach the underlying chat client.
When `ResponseFormat` is supplied through `AgentRunOptions`:
```csharp
var options = new AgentRunOptions
{
ResponseFormat =
ChatResponseFormat.ForJsonSchema()
};
await agent.RunAsync(
"Return a structured response.",
options: options);
```
the captured `ChatOptions.ResponseFormat` is `null`.
However, when the same response format is supplied directly to `IChatClient.GetResponseAsync`:
```csharp
var options = new ChatOptions
{
ResponseFormat =
ChatResponseFormat.ForJsonSchema()
};
await chatClient.GetResponseAsync(messages, options);
```
`ResponseFormat` reaches the underlying client correctly.
I originally discovered this using the Anthropic provider. Calling the Anthropic `IChatClient` directly correctly generates Anthropic's `output_config.format`, while routing the same request through `ChatClientAgent` / `AIAgent.RunAsync` causes the response format to disappear before the provider is invoked.
I also reproduced it:
* with and without tools
* on the initial model call
* after a tool-call/result turn
* using `RunAsync()`
* using explicit `AgentRunOptions.ResponseFormat`
* with the response format configured at agent construction time
This suggests the problem is in `ChatClientAgent` response-format propagation rather than in the Anthropic adapter or tool-calling path.
### Expected
`AgentRunOptions.ResponseFormat` and the response format implied by `RunAsync()` should be propagated into the `ChatOptions.ResponseFormat` passed to the underlying `IChatClient`.
### Actual
`ChatOptions.ResponseFormat` is absent when the underlying `IChatClient` is invoked.
### Questions
1. Is `ChatClientAgent` expected to propagate `AgentRunOptions.ResponseFormat` into the underlying `ChatOptions.ResponseFormat`?
2. Should `RunAsync()` result in the same provider-level structured-output configuration as directly setting `ChatOptions.ResponseFormat`?
3. Is there a supported workaround that preserves the `ChatClientAgent` pipeline while ensuring `ResponseFormat` reaches the underlying client?
### Code Sample
```markdown
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
// The following is the error case
public sealed class CapturingChatClient : DelegatingChatClient
{
public ChatOptions? LastOptions { get; private set; }
public CapturingChatClient(IChatClient inner)
: base(inner)
{
}
public override Task GetResponseAsync(
IEnumerable messages,
ChatOptions? options = null,
CancellationToken cancellationToken = default)
{
LastOptions = options?.Clone();
return InnerClient.GetResponseAsync(
messages,
options,
cancellationToken);
}
}
public sealed record StructuredResponse(
string Message,
bool Success);
public static async Task ReproAsync(IChatClient rawClient)
{
var capturingClient = new CapturingChatClient(rawClient);
var agent = capturingClient.AsAIAgent(
name: "structured-output-repro",
instructions: "Return the requested structured response.");
var responseFormat =
ChatResponseFormat.ForJsonSchema();
var runOptions = new AgentRunOptions
{
ResponseFormat = responseFormat
};
await agent.RunAsync(
"Return Message='hello' and Success=true.",
options: runOptions);
Console.WriteLine(
capturingClient.LastOptions?.ResponseFormat is null
? "BUG: ResponseFormat was dropped"
: "OK: ResponseFormat reached IChatClient");
}
// The following is the working control case
public static async Task DirectChatClientControlAsync(
IChatClient chatClient)
{
var options = new ChatOptions
{
ResponseFormat =
ChatResponseFormat.ForJsonSchema()
};
await chatClient.GetResponseAsync(
[
new ChatMessage(
ChatRole.User,
"Return Message='hello' and Success=true.")
],
options);
// ResponseFormat reaches the underlying provider correctly here.
}
```
### Error Messages / Stack Traces
```markdown
```
### Package Versions
Microsoft.Agents.AI 1.19.0 and 1.21.0
### .NET Version
10.0.203
### Additional Context
_No response_
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.