ag-ui-protocol / ag-ui-protocol/ag-ui
[Bug]: .NET AGUI.Client buffers tool-call updates until all TOOL_CALL_RESULT events arrive
- Linguagem predominante
- Python
- Estrelas
- 15.9k
- Forks
- 1.4k
- Merge médio
- 1d 17h
- PRs com merge (30d)
- 163
Descrição
### Pre-flight Checklist
- [x] I have searched [existing issues](https://github.com/ag-ui-protocol/ag-ui/issues) and this hasn't been reported yet.
- [x] I am using the **latest** version AG-UI.
### Describe the Bug
## Summary
`AGUI.Client`'s `IChatClient` adapter does not surface a `FunctionCallContent` update when the corresponding `TOOL_CALL_END` event is received. Instead, it buffers the call until a `TOOL_CALL_RESULT` arrives. With parallel tool calls, it waits until **all** pending results arrive before releasing any of the buffered call/result updates.
This makes long-running backend tools invisible to consumers while they are executing. A UI cannot show an in-progress state: the tool call and result appear together only after execution has completed.
The AG-UI wire stream contains the lifecycle events at the expected times; the observable delay is introduced while converting `BaseEvent` objects into `ChatResponseUpdate` objects.
### Steps to Reproduce
1. Install `AGUI.Client` 0.0.6 and consume an AG-UI endpoint through `AGUIChatClient.GetStreamingResponseAsync(...)`.
2. Have the endpoint emit a backend tool lifecycle with a noticeable delay before the result:
```text
RUN_STARTED
TOOL_CALL_START(call_1, slow_tool)
TOOL_CALL_ARGS(call_1, {...})
TOOL_CALL_END(call_1)
# wait several seconds while the tool executes
TOOL_CALL_RESULT(call_1, ...)
RUN_FINISHED
```
3. Enumerate the returned `ChatResponseUpdate` stream and log the arrival time and content type of every update.
4. Observe that no update containing `FunctionCallContent` is yielded after `TOOL_CALL_END`.
5. Observe that after `TOOL_CALL_RESULT`, the buffered `FunctionCallContent` and `FunctionResultContent` updates are yielded together.
6. Repeat with two parallel tool calls. Even if the first tool finishes earlier, no buffered tool update is released until the last pending result arrives.
### Expected Behavior
After `TOOL_CALL_END` has completed the tool name and arguments, the client should immediately yield a `ChatResponseUpdate` containing `FunctionCallContent`. This gives consumers a window in which the call exists without a result and can be displayed as running.
When `TOOL_CALL_RESULT` arrives later, the client should yield the corresponding `FunctionResultContent` update.
Parallel calls should be surfaced and completed independently by `toolCallId`; one slow tool should not delay visibility of unrelated calls.
### Environment
```text
AG-UI packages:
- AGUI.Client 0.0.6
- AGUI.Abstractions 0.0.6
- AGUI.Formatting 0.0.6
Runtime:
- .NET 10.0
- Blazor UI consuming IChatClient streaming updates
Server used during reproduction:
- Microsoft.Agents.AI.Hosting.AGUI.AspNetCore 1.19.0-preview.260822.1
```
### Screenshots
_No response_
### Logs & Errors
```shell
```
### Additional Context
## Root cause
In the source commit packaged by `AGUI.Client` 0.0.6 (`9f393021ecbd6bcc62dc4b1ad5a6ac4b797565f4`):
- [`ToolCallBuilder.EndToolCall`](https://github.com/ag-ui-protocol/ag-ui/blob/9f393021ecbd6bcc62dc4b1ad5a6ac4b797565f4/sdks/dotnet/src/AGUI.Client/Internal/ToolCallBuilder.cs#L62-L93) creates the `FunctionCallContent` but adds its update to `_buffer`.
- [`ToolCallBuilder.AddResult`](https://github.com/ag-ui-protocol/ag-ui/blob/9f393021ecbd6bcc62dc4b1ad5a6ac4b797565f4/sdks/dotnet/src/AGUI.Client/Internal/ToolCallBuilder.cs#L102-L115) returns the buffered updates only when `_pendingToolCallIds.Count == 0`.
Consequently, a single call is hidden until its result and a parallel batch is hidden until the final result.
## Impact
- Progress indicators and running/pulse states cannot be implemented through the `IChatClient` streaming surface.
- Long-running tools make the UI appear stalled.
- Parallel tool activity arrives in a burst rather than reflecting actual execution timing.
## Related issues
This resembles #1668 at the UX/protocol level, but that issue concerned the Spring integration. It is also distinct from #2359, which concerns .NET server-side suppression on continuation runs. This report concerns buffering in the .NET `AGUI.Client` event-to-`ChatResponseUpdate` conversion.
A possible fix would be to yield the completed `FunctionCallContent` update at `TOOL_CALL_END` and yield each result independently, while retaining any special buffering needed for interrupt/approval handling.
Guia de contribuição
Avaliação
Esta issue ainda não foi avaliada.