Microsoft.Agents.Ai Hits 1.0 — What It Means for FabrCore

Eric Brasher April 7, 2026 at 9:00 AM 5 min read
Release

The Microsoft Agent Framework has shipped its 1.0.0 GA release of Microsoft.Agents.AI and Microsoft.Agents.AI.Abstractions. FabrCore has been tracking the RC builds since the early previews, and today we are pinned to the stable 1.0 packages. Here is what the framework provides, how FabrCore uses it, and what the GA milestone means for teams building production agents.

What Microsoft.Agents.AI Provides

The framework defines a small, focused set of abstractions for building LLM-powered agents. At the center is AIAgent — an abstract base class that handles session management, execution (both streaming and non-streaming), and service resolution. The concrete implementation that ships out of the box is ChatClientAgent, which wraps any IChatClient from Microsoft.Extensions.AI.

The key types across the two packages:

TypePackageRole
AIAgentAbstractionsAbstract base — session management, RunAsync, RunStreamingAsync
AgentSessionAbstractionsConversation state container with StateBag for arbitrary key-value data
AgentResponseAbstractionsComplete response from a non-streaming run
AgentResponseUpdateAbstractionsIndividual chunk from a streaming run
ChatClientAgentMicrosoft.Agents.AISealed implementation wrapping IChatClient with instructions, tools, history
ChatClientAgentOptionsMicrosoft.Agents.AIConfiguration — name, description, chat options, history provider
AIAgentBuilderMicrosoft.Agents.AIMiddleware pipeline for intercepting agent runs

The framework intentionally stays thin. It does not prescribe how you host agents, how you persist sessions, or which LLM provider you use. That is where FabrCore steps in.

How FabrCore Uses the Framework

Every FabrCore agent extends FabrCoreAgentProxy, which provides a CreateChatClientAgent helper method. Under the hood, this method does three things: it creates an IChatClient for the configured model via FabrCoreChatClientService, wraps it in a ChatClientAgent with your system prompt and tools, and creates an AgentSession backed by FabrCoreChatHistoryProvider for automatic chat history persistence.

C# — Agent initialization with CreateChatClientAgent
private AIAgent? _agent;
private AgentSession? _session;

public override async Task OnInitialize()
{
    var tools = await ResolveConfiguredToolsAsync();
    var result = await CreateChatClientAgent(
        chatClientConfigName: config.Models ?? "default",
        threadId: config.Handle ?? fabrcoreAgentHost.GetHandle(),
        tools: tools);

    _agent = result.Agent;     // AIAgent (ChatClientAgent)
    _session = result.Session; // AgentSession with auto-persisted history
}

Once initialized, your OnMessage handler calls either RunAsync for a complete response or RunStreamingAsync to stream tokens as they arrive:

C# — Non-streaming with RunAsync
public override async Task<AgentMessage> OnMessage(AgentMessage message)
{
    var response = message.Response();
    var chatMessage = new ChatMessage(ChatRole.User, message.Message);

    var result = await _agent!.RunAsync(chatMessage, _session!);
    response.Message = result.Text;

    return response;
}
C# — Streaming with RunStreamingAsync
public override async Task<AgentMessage> OnMessage(AgentMessage message)
{
    var response = message.Response();
    var chatMessage = new ChatMessage(ChatRole.User, message.Message);

    await foreach (var update in _agent!.RunStreamingAsync(chatMessage, _session!))
    {
        response.Message += update.Text;
    }

    return response;
}

FabrCore also automatically tracks LLM usage across all calls within a single OnMessage invocation — input tokens, output tokens, reasoning tokens, call count, and duration — attaching them to the response AgentMessage.Args without any extra code.

Session Management and Serialization

AgentSession holds the conversation state between agent runs. FabrCore backs each session with a FabrCoreChatHistoryProvider that automatically persists chat history to Orleans grain state, so sessions survive grain deactivation and reactivation without any manual save/load code.

The session also carries a StateBag for arbitrary key-value data that your agent can read and write during a conversation:

C# — Session StateBag usage
// Store custom state in the session
_session!.StateBag.SetValue("userPreferences", new UserPrefs { Theme = "dark" });

// Read it back in a later turn
var prefs = _session!.StateBag.GetValue<UserPrefs>("userPreferences");

For advanced scenarios, sessions can be serialized to JSON and restored later using SerializeSessionAsync and DeserializeSessionAsync on AIAgent. This is useful for migrating conversation state between agent instances or storing session snapshots externally.

What the 1.0 GA Release Means

Moving from RC to GA brings three practical benefits:

  • Stable API surface. The core types — AIAgent, AgentSession, ChatClientAgent, AgentResponse, and AgentResponseUpdate — are now under semantic versioning. Breaking changes require a major version bump, which means FabrCore agents built today will not need rewrites for framework updates.
  • Production-ready middleware. The AIAgentBuilder middleware pipeline is stable. You can intercept agent runs for logging, security checks, or response modification without worrying about the API changing under you.
  • Ecosystem alignment. With Microsoft.Extensions.AI already at GA and Microsoft.Agents.AI now joining it, the full stack from IChatClient up through agent orchestration is stable. FabrCore sits on top of both, and having stable foundations underneath means fewer dependency conflicts and smoother upgrades.

FabrCore's FabrCore.Sdk package includes Microsoft.Agents.AI and Microsoft.Agents.AI.Abstractions as transitive dependencies, so upgrading is automatic when you update the FabrCore NuGet packages.


Built with FabrCore on .NET 10.


Eric Brasher

Builder of FabrCore and OpenCaddis.