microsoft / microsoft/agent-framework

.NET: [Bug]: DevUI always sends new session

Open
#7,435 2 comments 0 reactions 1 assignee Claimed by @chetantoshniwal View on GitHub
.NET devui likely-fixed
Dominant language
Python
Stars
13.6k
Forks
2.3k
Avg merge
2d 45m
Merged PRs (30d)
358

Description

### Description

Hi everyone,

I'm trying to save conversation messages to a database using ChatHistoryProvider. However, InvokeContext.Session.StateBag seems to reset with every new message, creating a fresh session context each time. As a result, I can't track or associate incoming messages with their parent conversation.

Is DevUI designed to spawn a new session per message, or is there a specific way I should be passing/maintaining the conversation ID across requests?

Thanks for any insights!

The conversationId is red in image below because it has been recreated
Image

### Code Sample

```markdown
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.DevUI;
using Microsoft.Agents.AI.Hosting;
using Microsoft.Extensions.AI;
using OpenAI;
using OpenAI.Chat;
using System.ClientModel;
using TestChatHistoryProvider;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring OpenAPI at https://aka.ms/aspnet/openapi
builder.Services.AddOpenApi();

var apiKey = builder.Configuration["ApiKey"]
?? throw new InvalidOperationException("Configuration value 'ApiKey' is missing.");

var openAIClient = new ChatClient(
model: "gpt-5-mini",
credential: new ApiKeyCredential(apiKey),
options: new OpenAIClientOptions()
{
Endpoint = new Uri("myendpoind")
}
).AsIChatClient();

var agentBuilder = builder.AddAIAgent("Alex", (sp, key) =>
{
return openAIClient.AsAIAgent(new ChatClientAgentOptions()
{
Name = "Alex",
ChatOptions = new ChatOptions()
{

Instructions = "You are a helpful assistant.",

},

ChatHistoryProvider = new CosmosChatHistoryProvider()

})
.AsBuilder()
.UseToolApproval(new ToolApprovalAgentOptions
{
AutoApprovalRules = [AgentSkillsProvider.AllToolsAutoApprovalRule],
})
.Build()
;
});

builder.Services.AddOpenAIResponses();
builder.Services.AddOpenAIConversations();
builder.AddDevUI();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}

app.MapOpenAIResponses();
app.MapOpenAIConversations();
app.MapDevUI();

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

namespace TestChatHistoryProvider
{
public class DummyChatHistoryProvider : ChatHistoryProvider, IAsyncDisposable
{
private readonly ProviderSessionState _sessionState;
public DummyChatHistoryProvider()
{
_sessionState = new ProviderSessionState((_ => new State(Guid.NewGuid().ToString("N"))), this.GetType().Name);

}

protected override ValueTask> ProvideChatHistoryAsync(InvokingContext context, CancellationToken cancellationToken = default)
{
//context.Session.StateBag here is recreated with new incoming messages
var state = _sessionState.GetOrInitializeState(context.Session);
return base.ProvideChatHistoryAsync(context, cancellationToken);
}
public ValueTask DisposeAsync()
{
return ValueTask.CompletedTask;
}

public sealed class State
{
public State(string conversationId)
{
this.ConversationId = conversationId ?? throw new ArgumentNullException(nameof(conversationId));
}
public string ConversationId { get; set; }
}
}
}
```

### Error Messages / Stack Traces

```markdown

```

### Package Versions

### .NET Version

.NET 10

### Additional Context

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.