Skip to content

.NET: valkey streaming support dotnet - #5576

Open
Matthias Howell (MatthiasHowellYopp) wants to merge 3 commits into
microsoft:mainfrom
MatthiasHowellYopp:issue-5544
Open

.NET: valkey streaming support dotnet#5576
Matthias Howell (MatthiasHowellYopp) wants to merge 3 commits into
microsoft:mainfrom
MatthiasHowellYopp:issue-5544

Conversation

@MatthiasHowellYopp

Copy link
Copy Markdown
Contributor

Motivation and Context

The Microsoft.Agents.AI.Valkey package provides ValkeyChatHistoryProvider and ValkeyContextProvider for persistent conversation history and memory context. However, the framework currently has no storage-backed resumable streaming component — if a client disconnects during a streamed agent response (RunStreamingAsync), partial output is lost and must be regenerated. This is the final piece of the Valkey integration story, delivering parity with the Python agent-framework-valkey package.

Valkey Streams (XADD/XRANGE) are a natural fit: each entry gets an auto-generated ID that serves as a continuation token, entries are append-only and durable, and XRANGE with an exclusive start ID gives exact resume-from-here semantics — all with core commands, no modules required.

Fixes issue #5544

Description

Adds ValkeyStreamBuffer to the Microsoft.Agents.AI.Valkey package — a resumable streaming buffer backed by Valkey Streams.

The component writes serialized AgentResponseUpdate chunks to a Valkey Stream via XADD and replays missed entries via XRANGE from a caller-provided entry ID. The stream entry ID returned by each AppendAsync call serves as the continuation token for resumption.

Public API:

  • AppendAsync(responseId, update) — writes a chunk, returns the entry ID
  • ReadAsync(responseId, afterEntryId) — replays entries after a given ID as IAsyncEnumerable
  • GetEntryCountAsync(responseId) — returns stream length
  • DeleteStreamAsync(responseId) — removes a stream
  • MaxLength property — caps stream size via approximate XTRIM after each XADD

Follows the same patterns as the existing Valkey providers: dual constructors (connection string + IConnectionMultiplexer for DI), IAsyncDisposable with disposed-state guard, CancellationToken forwarding, malformed JSON resilience, trimming/AOT attributes, and ILogger integration at appropriate levels (Debug for per-request, Warning for skipped entries).

Includes a self-contained sample (AgentWithMemory_Step06_ResumableStreamingWithValkey) that demonstrates the full workflow — stream, disconnect, resume, full replay — against a live Valkey instance with no LLM or cloud credentials required.

64 unit tests passing, covering constructor validation, append/read round-trips, entry ID incrementing, MaxLength pass-through, malformed entry handling, cancellation, disposal guards, and empty stream edge cases.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.

Copilot AI review requested due to automatic review settings April 29, 2026 19:13
@moonbox3 Evan Mattson (moonbox3) added documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs .NET Usage: [Issues, PRs], Target: .Net labels Apr 29, 2026
@github-actions github-actions Bot changed the title valkey streaming support dotnet .NET: valkey streaming support dotnet Apr 29, 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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@MatthiasHowellYopp

Copy link
Copy Markdown
Contributor Author

westey (@westey-m) Hoping I can get a review on this this week, tks

@MatthiasHowellYopp

Copy link
Copy Markdown
Contributor Author

westey (@westey-m) Hoping I can get a review on this this week, tks

/// </list>
/// </para>
/// </remarks>
public sealed class ValkeyStreamBuffer

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.

Matthias Howell (@MatthiasHowellYopp), thanks for the PR. While I think the problem space you are describing is definitely interesting, just the buffer component on it's own is not that useful in the AF context. If you replaced AgentResponseUpdate with a generic type, this component could equally live in the Valkey .net lib.

I think most users would actually be looking for the integration into Agent Framework via some middleware that automatically deals with failures. However, that has some challenges. E.g. the service itself would need to have built in support for resumption. There is some support in Microsoft.Extensions.AI for this already, via ChatClient.AllowBackgroundResponses, which if the service supports this will use continuation tokens to allow the caller to resume reading. I'm not entirely sure how this would fit in with that though and would like to hear more about what you were thinking.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

westey (@westey-m) After reviewing the PR and the initial issue I see that this PR is not complete. I'd like to update this PR with a more complete solution to the issue, which should basically match what you describe. Let me know if it is ok to proceed.

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.

I think this is quite a challenging feature in many ways, and I'm actually not super clear on how it would integrate with agent framework, but happy to see what you have in mind. To save you time, effort and tokens, it may makes sense to create a small design doc of what you have in mind first. Or join our office hours and come discuss. See https://github.com/microsoft/agent-framework/blob/main/COMMUNITY.md for the office hours details.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I've added a design doc in tis pr in docs/design/valkey-stream-buffer.md. I hope it has enough info for you to assess properly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

westey (@westey-m) Hoping you can have a look at the design doc.

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.

Things are a bit busy here. I'll try and get to it next week.

Adds ValkeyStreamBuffer — a resumable streaming buffer backed by Valkey
Streams (XADD/XRANGE). Enables clients to disconnect and reconnect
mid-stream without data loss using entry ID-based continuation tokens.

- ValkeyStreamBuffer with AppendAsync, ReadAsync, GetEntryCountAsync, DeleteStreamAsync
- ValkeyStreamBufferOptions (KeyPrefix, MaxLength, JsonSerializerOptions)
- Uses Valkey.Glide with type-safe JSON serialization
- Unit tests with mocked client
- Sample demonstrating append, disconnect, and resume workflow

Signed-off-by: Matthias Howell <matthias.howell@improving.com>
Signed-off-by: Matthias Howell <matthias.howell@improving.com>
Upstream added AgentWithMemory_Step08_MemoryUsingCosmosNoSql, which
collides with this sample's step number. Bump to Step09 to avoid the
naming conflict.

Signed-off-by: MatthiasHowellYopp <matthias.howell@improving.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs .NET Usage: [Issues, PRs], Target: .Net

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants