-
Notifications
You must be signed in to change notification settings - Fork 475
.NET: introduce API to manage the thread in Hosting scenarios #1392
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
.NET: introduce API to manage the thread in Hosting scenarios #1392
Conversation
There was a problem hiding this 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 PR introduces an API for managing agent threads in hosting scenarios, enabling persistent storage and retrieval of conversation threads across HTTP requests and application restarts.
- Introduces the
IAgentThreadStore
interface for persistent thread storage - Provides
NoContextAgentThreadStore
(no-op) andInMemoryAgentThreadStore
implementations - Adds
AIHostAgent
wrapper that combines agents with thread persistence capabilities
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
File | Description |
---|---|
IAgentThreadStore.cs | Defines the interface contract for thread storage operations |
NoContextAgentThreadStore.cs | Provides a no-op implementation that returns null threads |
InMemoryAgentThreadStore.cs | Implements in-memory thread storage using ConcurrentDictionary |
AIHostAgent.cs | Wraps AIAgent with thread persistence capabilities |
HostAgentBuilderExtensions.cs | Extension methods for configuring thread stores with agents |
AIAgentExtensions.cs | Updates A2A messaging to support thread persistence |
WebApplicationExtensions.cs | Updates ASP.NET Core integration to use thread stores |
Program.cs | Sample showing in-memory thread store configuration |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
public ValueTask<JsonElement?> GetOrCreateThreadAsync(string conversationId, string agentId, CancellationToken cancellationToken = default) | ||
{ | ||
// this is OK, Agents should be prepared to handle null threads. | ||
return new ValueTask<JsonElement?>(result: null!); |
Copilot
AI
Oct 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The null-forgiving operator !
is unnecessary here since null
is already being explicitly passed. This should be return new ValueTask<JsonElement?>(result: null);
return new ValueTask<JsonElement?>(result: null!); | |
return new ValueTask<JsonElement?>(result: null); |
Copilot uses AI. Check for mistakes.
CancellationToken cancellationToken = default) | ||
{ | ||
var key = GetKey(conversationId, agentId); | ||
var threadContent = this._threads.GetOrAdd(key, value: JsonDocument.Parse("{}").RootElement); |
Copilot
AI
Oct 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creating a new JsonDocument
on every call to GetOrAdd
is inefficient. Consider creating a static readonly instance of the empty JSON element to reuse across all calls.
Copilot uses AI. Check for mistakes.
var contextId = messageSendParams.Message.ContextId ?? Guid.NewGuid().ToString("N"); | ||
var parts = response.Messages.ToParts(); | ||
|
||
await hostAgent.SaveThreadAsync(contextId, thread!, cancellationToken).ConfigureAwait(false); |
Copilot
AI
Oct 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The null-forgiving operator !
is used on thread
but thread
can be null from RestoreThreadAsync
. This could cause a NullReferenceException. Check if thread
is null before saving or handle the null case appropriately.
await hostAgent.SaveThreadAsync(contextId, thread!, cancellationToken).ConfigureAwait(false); | |
if (thread == null) | |
{ | |
throw new InvalidOperationException("Failed to restore thread: thread is null."); | |
} | |
await hostAgent.SaveThreadAsync(contextId, thread, cancellationToken).ConfigureAwait(false); |
Copilot uses AI. Check for mistakes.
[heavy wip]