Skip to content

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

Description

@hintdesk

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

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<State> _sessionState;
        public DummyChatHistoryProvider()
        {
            _sessionState = new ProviderSessionState<State>((_ => new State(Guid.NewGuid().ToString("N"))), this.GetType().Name);

        }

        protected override ValueTask<IEnumerable<ChatMessage>> 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

Package Versions

<PackageReference Include="Microsoft.Agents.AI" Version="1.15.0" />     <PackageReference Include="Microsoft.Agents.AI.DevUI" Version="1.15.0-preview.260722.1" />     <PackageReference Include="Microsoft.Agents.AI.Hosting.OpenAI" Version="1.15.0-alpha.260722.1" />     <PackageReference Include="Microsoft.Agents.AI.OpenAI" Version="1.15.0" />     <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.10" />

.NET Version

.NET 10

Additional Context

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    .NETUsage: [Issues, PRs], Target: .Netlikely-fixedtriageUsage: [Issues], Target: All issues that still need to be triaged

    Type

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions