On September 25, 2026, Microsoft published something that may matter more than it first appears for teams building agent products: AG-UI now has a first-class .NET SDK.

Primary source: Microsoft .NET Blog — AG-UI Protocol now has a first-class .NET SDK

This is not merely another NuGet package. The proposal is that any .NET service can speak AG-UI directly and that an application can consume a remote agent through the normal Microsoft.Extensions.AI abstractions.

That enables a useful architecture:

interface
   │
   │ AG-UI
   ▼
agent / runtime

The interface no longer needs a private integration for every agent framework, and the runtime no longer needs to know how every event will be rendered.

From there, a particularly interesting combination appears for prototypes and internal tools:

Streamlit
   │
   │ AG-UI
   ▼
adapter
   │
   ▼
Codex

This article first looks at the .NET SDK Microsoft just introduced and then answers two practical questions: can Streamlit act as an AG-UI client? and can Codex sit behind that protocol?

The short answer to both is yes, with important caveats.

Status verified on September 27, 2026. AG-UI and Codex are moving quickly; review the linked primary sources before freezing a production architecture.

First: what exactly is in the AG-UI .NET SDK?

Microsoft built the SDK with CopilotKit and contributed it to the main AG-UI repository, next to the TypeScript and Python SDKs. It is published on NuGet under the MIT license.

The SDK ships as five packages:

PackageRole
AGUI.AbstractionsProtocol types: events, messages, tools, capabilities, interrupts, state, and serialization
AGUI.FormattingWire-format abstractions; includes default SSE support
AGUI.ProtobufOptional protobuf codec for a subset of events
AGUI.ClientConsumes AG-UI endpoints
AGUI.ServerExposes an agent as an AG-UI endpoint

Source: Microsoft .NET Blog — The packages

Most applications only need to decide which side they are on.

For a backend:

dotnet add package AGUI.Server

For a consumer:

dotnet add package AGUI.Client

IChatClient is the integration point

One of the most important design choices is the use of Microsoft.Extensions.AI.IChatClient.

An agent does not need to adopt an entirely separate API just to speak AG-UI. It can keep the abstraction already used across the .NET AI ecosystem.

On the server side:

IChatClient
   │
streaming response
   │
   ▼
AGUI.Server
   │
SSE / AG-UI events
   ▼
client

In the other direction, AGUI.Client includes AGUIChatClient, which also implements IChatClient.

So a .NET application can look like this:

.NET application
      │
   IChatClient
      │
AGUIChatClient
      │
    AG-UI
      │
Python / TypeScript / C# agent

Microsoft shows a client setup like:

using AGUI.Client;

using var httpClient = new HttpClient();

var chatClient = new AGUIChatClient(
    new(httpClient, "http://localhost:5001"));

Source: Microsoft .NET Blog — AG-UI .NET quickstart

Microsoft Agent Framework now builds on this SDK

Microsoft Agent Framework already had AG-UI support, but its .NET integration now depends on the shared AGUI.* packages.

The hosting model becomes compact:

builder.Services.AddAGUIServer();

AIAgent agent = chatClient.AsAIAgent(
    name: "AGUIAssistant",
    instructions: "You are a helpful assistant.");

app.MapAGUIServer("/", agent);

Microsoft says the wire format is unchanged, so existing frontends can continue working against an upgraded backend.

That matters because AG-UI is no longer just an implementation detail inside a specific Microsoft agent framework. It becomes a reusable protocol layer available to ordinary .NET services.

What problem is AG-UI trying to solve?

Agents break the traditional request-response pattern.

An agent may:

  • run for minutes;
  • stream text;
  • invoke tools;
  • request human approval;
  • update shared state;
  • delegate to subagents;
  • pause and continue;
  • emit intermediate results.

Without a common protocol, every backend invents its own stream.

The UI ends up coupled to framework-specific events:

LangGraph events ─┐
CrewAI events ────┼── custom UI logic
framework X ──────┤
runtime Y ────────┘

AG-UI tries to replace that with a shared contract.

The project describes itself as an open, lightweight, event-based protocol connecting agents to user-facing applications.

Source: AG-UI — README

Its events cover:

  • run lifecycle;
  • text messages;
  • tool calls;
  • state synchronization;
  • activity and progress;
  • subagents;
  • custom events.

Source: AG-UI — Events

Text, for example, follows an explicit lifecycle:

TEXT_MESSAGE_START
        ↓
TEXT_MESSAGE_CONTENT
        ↓
TEXT_MESSAGE_CONTENT
        ↓
TEXT_MESSAGE_END

Tool calls have a separate lifecycle:

TOOL_CALL_START
      ↓
TOOL_CALL_ARGS
      ↓
TOOL_CALL_END
      ↓
TOOL_CALL_RESULT

This is far easier for a UI to reason about than free-form output.

AG-UI does not replace MCP

The protocols solve different boundaries:

user
 │
 ▼
interface
 │
AG-UI
 │
 ▼
agent
 ├── MCP ── tools and data
 │
 └── A2A ── other agents

AG-UI itself presents the stack this way: MCP gives agents tools, A2A connects agents, and AG-UI brings agents into user-facing applications.

Source: AG-UI — protocol stack

They can coexist in one system.

What about Streamlit?

This is the first important caveat.

Streamlit is not currently listed as a first-class supported AG-UI client.

The main repository lists clients such as CopilotKit, terminal, chat platforms, and React Native.

Source: AG-UI — Clients

There is also a community discussion specifically asking about Streamlit and Gradio support.

Source: AG-UI discussion #538 — Streamlit or Gradio frontend support thoughts

But that does not make Streamlit incompatible.

AG-UI’s client quickstart explicitly says that a client does not have to be a web application. Anything capable of consuming the event stream and presenting it to a user can be a client.

Source: AG-UI — Build clients

So Streamlit can become an AG-UI client through an adapter.

Streamlit
   │
   │ HTTP / SSE
   ▼
AG-UI endpoint
   │
   ▼
agent

Mapping AG-UI into Streamlit

A first version can handle only a small event set:

AG-UI                         Streamlit

TEXT_MESSAGE_CONTENT   →     st.chat_message / st.empty
TOOL_CALL_START        →     st.status
TOOL_CALL_RESULT       →     st.expander / st.json
STATE_DELTA            →     st.session_state
RUN_STARTED            →     working indicator
RUN_FINISHED           →     finalize status

Conceptually:

async for event in agui_stream:
    match event["type"]:
        case "TEXT_MESSAGE_CONTENT":
            render_text_delta(event)

        case "TOOL_CALL_START":
            show_tool_started(event)

        case "TOOL_CALL_RESULT":
            show_tool_result(event)

        case "STATE_DELTA":
            update_session_state(event)

        case "RUN_FINISHED":
            finish_run(event)

This covers a large part of the value for a prototype.

The harder problems begin with multi-agent updates, interrupts, frontend tools, approvals, and highly concurrent state. Streamlit has a different execution model from a typical React application, so richer agent experiences may require custom components or an additional state layer.

AG-UI does not remove that constraint. It removes the need to invent the protocol too.

Can Codex sit behind AG-UI?

Yes.

The simplest model is to treat Codex as another runtime producing structured events.

Streamlit
   │
 AG-UI
   │
adapter
   │
Codex
   │
repo / shell / tools

The real design choice is which Codex surface to use.

There are three especially relevant options.

Option 1: codex exec —json

This is the simplest integration for automation and headless workloads.

Codex can run non-interactively and emit structured JSONL events.

An adapter can launch:

codex exec --json --ephemeral "Diagnose the failing tests"

and translate the stdout stream into AG-UI.

Conceptually:

Codex                         AG-UI

thread.started        →       metadata / start
turn.started          →       RUN_STARTED
agent_message         →       TEXT_MESSAGE_*
command_execution     →       TOOL_CALL_*
file_change           →       state/custom event
turn.completed        →       RUN_FINISHED
turn.failed           →       RUN_ERROR

A Python adapter could look roughly like:

proc = await asyncio.create_subprocess_exec(
    "codex",
    "exec",
    "--json",
    "--ephemeral",
    prompt,
    stdout=asyncio.subprocess.PIPE,
)

async for line in proc.stdout:
    codex_event = json.loads(line)
    for agui_event in translate(codex_event):
        yield agui_event

This route is attractive because it requires little infrastructure and works well for CI jobs, disposable runs, and isolated automation.

The —ephemeral flag is especially useful when the run does not need to be resumed.

But exec JSONL is not the full internal event model

Structured output does not automatically mean full fidelity.

Open Codex issues document information that gets lost when internal events are projected into exec JSONL.

Issue #30190 notes that exec drops the phase distinguishing commentary from final_answer.

Source: openai/codex #30190

Issue #35415 documents limitations in structured web-search metadata exposed through codex exec —json.

Source: openai/codex #35415

Issue #45773 describes additional web_search information lost or collapsed by the exec projection.

Source: openai/codex #45773

So:

codex exec —json is a strong automation surface, but a rich UI should not assume it exposes every piece of state available inside Codex.

Option 2: @openai/codex-sdk

OpenAI also maintains a TypeScript SDK for embedding Codex in applications.

Source: Codex TypeScript SDK

The SDK is revealing: it wraps the Codex CLI, spawns it, and exchanges JSONL events through stdin/stdout.

Its higher-level API works with a Thread:

import { Codex } from "@openai/codex-sdk";

const codex = new Codex();
const thread = codex.startThread();

const turn = await thread.run(
  "Diagnose the test failure and propose a fix"
);

For a UI, runStreamed() is the interesting part:

const { events } = await thread.runStreamed(
  "Diagnose the failure"
);

for await (const event of events) {
  // translate event → AG-UI
}

OpenAI documents intermediate tool calls, streaming responses, and file-change notifications.

That removes a lot of direct subprocess handling.

There is an operational caveat for disposable automation, though. Issue #34760 asks for an ephemeral SDK option equivalent to codex exec —ephemeral because startThread can otherwise persist session rollouts under CODEX_HOME.

Source: openai/codex #34760

That matters for long-running services that start many independent jobs.

Option 3: Codex App Server

For a deeper integration, App Server is likely the most interesting surface.

Codex exposes a richer application protocol around threads, turns, items, approvals, and notifications.

The current thread/start schema can configure things such as:

  • model;
  • cwd;
  • approval policy;
  • sandbox;
  • instructions;
  • configuration;
  • ephemeral mode.

Source: Codex app-server protocol — ThreadStartParams

An architecture could look like:

Streamlit
   │
 AG-UI
   │
AG-UI ↔ Codex adapter
   │
Codex App Server
   │
repo / shell / MCP / tools

This avoids depending only on the simplified exec projection and gives the adapter a model much closer to threads and turns.

It is a better foundation when we need:

  • persistent conversations;
  • interrupts;
  • approvals;
  • resume;
  • granular state;
  • multiple turns;
  • richer UI semantics.

But it is still an evolving interface. Issue #21982, for example, documents a case where a sandbox approval was not surfaced correctly to an App Server client.

Source: openai/codex #21982

That means integrations should include regression tests around approvals and cancellation instead of assuming every edge case is already solved.

The architecture I would start with

For an experiment:

Streamlit
   │
   │ AG-UI
   ▼
Python adapter
   │
codex exec --json --ephemeral
   │
workspace

It has few moving pieces and lets us validate:

  1. streaming;
  2. tool visualization;
  3. file changes;
  4. completion and errors.

If the UI later needs deep bidirectional interaction:

Streamlit
   │
   │ AG-UI
   ▼
adapter
   │
Codex App Server
   │
workspace

And when the surrounding service is TypeScript:

UI
 │
AG-UI
 │
TypeScript adapter
 │
@openai/codex-sdk
 │
Codex CLI

The key is that Streamlit should not know Codex’s private event schema.

It should know AG-UI.

That lets us replace:

Codex → another agent runtime

without rewriting the interface.

It also lets us replace:

Streamlit → React / mobile / terminal

without rewriting the agent runtime.

Where does .NET fit?

This is exactly where Microsoft’s new SDK becomes useful.

We can build an ASP.NET Core adapter:

Streamlit
   │
 AG-UI
   │
ASP.NET Core
   │
Codex adapter
   │
Codex

Or use .NET as the client:

.NET application
   │
AGUI.Client / IChatClient
   │
AG-UI
   │
Codex backend

Or keep Microsoft Agent Framework as the main orchestrator and call Codex for specialized engineering tasks:

UI
 │
AG-UI
 │
Microsoft Agent Framework
 ├── normal tools
 ├── MCP
 └── Codex worker

The boundaries become explicit.

AG-UI as an ABI for agent experiences

The analogy is imperfect, but useful.

In native software, an ABI lets independently built components cooperate through a common contract.

AG-UI is trying to play a similar role between agent runtimes and applications:

UI               runtime
 │                  │
 └──── AG-UI ───────┘

If the contract remains stable, both sides can evolve more independently.

That is valuable because the naive alternative creates one integration for every pair:

Streamlit × Codex
Streamlit × LangGraph
React × Codex
React × MAF
mobile × Codex
terminal × LangGraph
...

A shared protocol reduces the problem to:

each UI       → AG-UI
each runtime  → AG-UI

That is the real architectural potential.

What I would implement first

An MVP does not need every AG-UI feature.

Start with:

  1. RUN_STARTED / RUN_FINISHED / RUN_ERROR;
  2. TEXT_MESSAGE_*;
  3. tool calls;
  4. minimal state;
  5. cancellation.

That already enables an experience like:

User: fix the failing tests

Codex is working...
 ├─ inspected 12 files
 ├─ ran pytest
 ├─ changed parser.py
 ├─ ran 84 tests
 └─ all passed

Answer:
I fixed the race condition...

Then add approvals and interrupts.

Only after that would I invest in generative UI or sophisticated shared-state synchronization.

Conclusion

The new AG-UI .NET SDK matters because it makes the protocol natural inside the Microsoft ecosystem: IChatClient can produce or consume AG-UI, Microsoft Agent Framework now builds on the shared SDK, and ordinary .NET services can expose agents without inventing their own wire protocol.

Streamlit does not yet have a first-class official integration, but it can act as a client because AG-UI standardizes events rather than a specific rendering technology.

And Codex can fit behind that boundary in several ways:

MVP / automation
→ codex exec --json --ephemeral

TypeScript application
→ @openai/codex-sdk

deep bidirectional integration
→ Codex App Server

The most valuable architectural decision is not any one of those choices.

It is preserving this boundary:

interface
   │
 AG-UI
   │
agent runtime

If that boundary works, we can prototype with Streamlit today, move to another UI tomorrow, and change the agent runtime later without reinventing the entire integration.

That is exactly the kind of decoupling the agent ecosystem needs.