Some checks are pending
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
dotnet-build-and-test / paths-filter (push) Waiting to run
dotnet-build-and-test / dotnet-build-and-test (Debug, windows-latest, net9.0) (push) Blocked by required conditions
dotnet-build-and-test / dotnet-build-and-test (Release, integration, true, ubuntu-latest, net10.0) (push) Blocked by required conditions
dotnet-build-and-test / dotnet-build-and-test (Release, integration, true, windows-latest, net472) (push) Blocked by required conditions
dotnet-build-and-test / dotnet-build-and-test (Release, ubuntu-latest, net8.0) (push) Blocked by required conditions
dotnet-build-and-test / dotnet-build-and-test-check (push) Blocked by required conditions
96 lines
5.1 KiB
Markdown
96 lines
5.1 KiB
Markdown
---
|
|
status: accepted
|
|
contact: javiercn
|
|
date: 2025-10-29
|
|
deciders: javiercn, DeagleGross, moonbox3, markwallace-microsoft
|
|
consulted: Agent Framework team
|
|
informed: .NET community
|
|
---
|
|
|
|
# AG-UI Protocol Support for .NET Agent Framework
|
|
|
|
## Context and Problem Statement
|
|
|
|
The .NET Agent Framework needed a standardized way to enable communication between AI agents and user-facing applications with support for streaming, real-time updates, and bidirectional communication. Without AG-UI protocol support, .NET agents could not interoperate with the growing ecosystem of AG-UI-compatible frontends and agent frameworks (LangGraph, CrewAI, Pydantic AI, etc.), limiting the framework's adoption and utility.
|
|
|
|
The AG-UI (Agent-User Interaction) protocol is an open, lightweight, event-based protocol that addresses key challenges in agentic applications including streaming support for long-running agents, event-driven architecture for nondeterministic behavior, and protocol interoperability that complements MCP (tool/context) and A2A (agent-to-agent) protocols.
|
|
|
|
## Decision Drivers
|
|
|
|
- Need for streaming communication between agents and client applications
|
|
- Requirement for protocol interoperability with other AI frameworks
|
|
- Support for long-running, multi-turn conversation sessions
|
|
- Real-time UI updates for nondeterministic agent behavior
|
|
- Standardized approach to agent-to-UI communication
|
|
- Framework abstraction to protect consumers from protocol changes
|
|
|
|
## Considered Options
|
|
|
|
1. **Implement AG-UI event types as public API surface** - Expose AG-UI event models directly to consumers
|
|
2. **Use custom AIContent types for lifecycle events** - Create new content types (RunStartedContent, RunFinishedContent, RunErrorContent)
|
|
3. **Current approach** - Internal event types with framework-native abstractions
|
|
|
|
## Decision Outcome
|
|
|
|
Chosen option: "Current approach with internal event types and framework-native abstractions", because it:
|
|
|
|
- Protects consumers from protocol changes by keeping AG-UI events internal
|
|
- Maintains framework abstractions through conversion at boundaries
|
|
- Uses existing framework types (AgentResponseUpdate, ChatMessage) for public API
|
|
- Focuses on core text streaming functionality
|
|
- Leverages existing properties (ConversationId, ResponseId, ErrorContent) instead of custom types
|
|
- Provides bidirectional client and server support
|
|
|
|
### Implementation Details
|
|
|
|
**In Scope:**
|
|
1. **Client-side AG-UI consumption** (`Microsoft.Agents.AI.AGUI` package)
|
|
- `AGUIAgent` class for connecting to remote AG-UI servers
|
|
- `AGUIAgentThread` for managing conversation threads
|
|
- HTTP/SSE streaming support
|
|
- Event-to-framework type conversion
|
|
|
|
2. **Server-side AG-UI hosting** (`Microsoft.Agents.AI.Hosting.AGUI.AspNetCore` package)
|
|
- `MapAGUIAgent` extension method for ASP.NET Core
|
|
- Server-Sent Events (SSE) response formatting
|
|
- Framework-to-event type conversion
|
|
- Agent factory pattern for per-request instantiation
|
|
|
|
3. **Text streaming events**
|
|
- Lifecycle events: `RunStarted`, `RunFinished`, `RunError`
|
|
- Text message events: `TextMessageStart`, `TextMessageContent`, `TextMessageEnd`
|
|
- Thread and run ID management via `ConversationId` and `ResponseId`
|
|
|
|
### Key Design Decisions
|
|
|
|
1. **Event Models as Internal Types** - AG-UI event types are internal with conversion via extension methods; public API uses the existing types in Microsoft.Extensions.AI as those are the abstractions people are familiar with
|
|
|
|
2. **No Custom Content Types** - Run lifecycle communicated through existing `ChatResponseUpdate` properties (`ConversationId`, `ResponseId`) and standard `ErrorContent` type
|
|
|
|
3. **Agent Factory Pattern** - `MapAGUIAgent` uses factory function `(messages) => AIAgent` to allow request-specific agent configuration supporting multi-tenancy
|
|
|
|
4. **Bidirectional Conversion Architecture** - Symmetric conversion logic in shared namespace compiled into both packages for server (`AgentResponseUpdate` → AG-UI events) and client (AG-UI events → `AgentResponseUpdate`)
|
|
|
|
5. **Thread Management** - `AGUIAgentThread` stores only `ThreadId` with thread ID communicated via `ConversationId`; applications manage persistence for parity with other implementations and to be compliant with the protocol. Future extensions will support having the server manage the conversation.
|
|
|
|
6. **Custom JSON Converter** - Uses custom polymorphic deserialization via `BaseEventJsonConverter` instead of built-in System.Text.Json support to handle AG-UI protocol's flexible discriminator positioning
|
|
|
|
### Consequences
|
|
|
|
**Positive:**
|
|
- .NET developers can consume AG-UI servers from any framework
|
|
- .NET agents accessible from any AG-UI-compatible client
|
|
- Standardized streaming communication patterns
|
|
- Protected from protocol changes through internal implementation
|
|
- Symmetric conversion logic between client and server
|
|
- Framework-native public API surface
|
|
|
|
**Negative:**
|
|
- Custom JSON converter required (internal implementation detail)
|
|
- Shared code uses preprocessor directives (`#if ASPNETCORE`)
|
|
- Additional abstraction layer between protocol and public API
|
|
|
|
**Neutral:**
|
|
- Initial implementation focused on text streaming
|
|
- Applications responsible for thread persistence
|