AI applications are moving beyond simple chat interfaces.
Modern AI agents can call tools, retrieve information, execute workflows, ask for additional input, and perform multiple steps before producing a final response. However, many applications still present all of that activity through a basic text box and a stream of messages.
That creates a disconnect between what the agent is doing and what the user can see.
A better approach is to build an agentic UI where the interface reacts to the agent's state, tool calls, progress, results, approvals, and errors.
For .NET developers, Blazor provides a practical way to build these experiences because application logic and UI components can be developed using C#. When combined with AI components and an agent orchestration layer, Blazor can provide an interactive interface for agent-driven applications.
This article explains the architecture behind agentic UIs and demonstrates how to build one using Blazor-style components and C#.
What Is an Agentic UI?
A traditional AI chat application usually follows a simple interaction model:
User
|
v
Chat Input
|
v
AI Model
|
v
Text Response
|
v
Chat Window
An agentic application is more dynamic.
The agent may:
Receive a user request.
Determine what action is required.
Select one or more tools.
Execute those tools.
Inspect the results.
Decide whether another action is necessary.
Return a final response.
The UI should represent this process.
A simplified architecture looks like this:
User
|
v
+------------------+
| Blazor UI |
+------------------+
|
v
+------------------+
| Agent Orchestrator|
+------------------+
/ | \
v v v
Search Database API
| | |
+-------+--------+
|
v
Agent Result
|
v
Blazor UI
Instead of showing only the final answer, the application can display useful intermediate states.
For example:
Analyzing request...
Searching customer records...
Checking order status...
Preparing response...
This makes the application feel more transparent and responsive.
Why Blazor Works Well for Agentic Applications
Blazor provides component-based UI development using .NET and C#.
That becomes particularly useful when the AI orchestration layer is also implemented in .NET.
A typical application can be organized like this:
Blazor Components
|
v
Application Services
|
v
Agent Orchestration
|
+---- LLM
|
+---- Tools
|
+---- APIs
|
+---- Databases
The UI does not need to know how every tool works.
Instead, it consumes application state such as:
public class AgentState
{
public string Status { get; set; } = "Idle";
public string CurrentStep { get; set; } = string.Empty;
public List<string> Messages { get; set; } = new();
public bool WaitingForApproval { get; set; }
public string? FinalResponse { get; set; }
}
The component can then render the state dynamically.
Designing the Agentic UI
A good agentic UI should expose the information users actually need.
A useful layout can contain four areas:
+------------------------------------------------+
| AI Assistant |
+------------------------------------------------+
| |
| User Request |
| "Find delayed orders for customer 1042" |
| |
| Agent Activity |
| ✓ Customer identified |
| ✓ Order database searched |
| ● Checking shipment status |
| |
| Tool Results |
| 3 delayed orders found |
| |
| Agent Response |
| "I found 3 delayed orders..." |
+------------------------------------------------+
The UI can use separate components for each responsibility.
For example:
AgentChat
├── MessageList
├── AgentStatus
├── ToolActivity
├── ToolResult
├── ApprovalPanel
└── ResponsePanel
This is easier to maintain than putting the entire agent experience into one large component.
Creating a Basic Agent Service
Start by defining an application service responsible for running the agent.
public interface IAgentService
{
Task<AgentResponse> RunAsync(
string request,
CancellationToken cancellationToken = default);
}
A simple response model could be:
public class AgentResponse
{
public string Message { get; set; } = string.Empty;
public List<AgentStep> Steps { get; set; } = new();
}
The step model describes what happened during execution.
public class AgentStep
{
public string Name { get; set; } = string.Empty;
public string Status { get; set; } = string.Empty;
public string? Result { get; set; }
}
In a real application, the agent service would connect to your selected AI model and tool infrastructure.
The important design principle is to keep that implementation separate from the UI.
Building the Blazor Component
A simple Blazor component can maintain the current request and agent state.
@page "/agent"
<h2>AI Agent</h2>
<div class="agent-container">
<input @bind="request"
placeholder="Ask the agent something..." />
<button @onclick="RunAgent"
disabled="@isRunning">
@(isRunning ? "Working..." : "Run Agent")
</button>
@if (isRunning)
{
<p>@currentStep</p>
}
@if (response is not null)
{
<div class="agent-response">
@response.Message
</div>
}
</div>
@code {
private string request = string.Empty;
private string currentStep = "Starting...";
private bool isRunning;
private AgentResponse? response;
private async Task RunAgent()
{
if (string.IsNullOrWhiteSpace(request))
return;
isRunning = true;
currentStep = "Analyzing request...";
try
{
response = await AgentService.RunAsync(request);
}
finally
{
isRunning = false;
currentStep = "Completed";
}
}
}
This is intentionally simple.
Production applications should provide richer state management and streaming updates, but the component demonstrates the core pattern.
Showing Agent Progress
One of the biggest differences between a chatbot and an agentic UI is progress visibility.
Instead of waiting silently for a potentially long-running operation, show the current operation.
For example:
public class AgentStep
{
public string Name { get; set; } = string.Empty;
public AgentStepStatus Status { get; set; }
public DateTimeOffset StartedAt { get; set; }
public DateTimeOffset? CompletedAt { get; set; }
}
An enumeration can make the UI logic easier to understand.
public enum AgentStepStatus
{
Pending,
Running,
Completed,
Failed
}
The Blazor component can translate these states into visual indicators.
@foreach (var step in steps)
{
<div class="agent-step">
<strong>@step.Name</strong>
@switch (step.Status)
{
case AgentStepStatus.Pending:
<span>Waiting</span>
break;
case AgentStepStatus.Running:
<span>Running...</span>
break;
case AgentStepStatus.Completed:
<span>Completed</span>
break;
case AgentStepStatus.Failed:
<span>Failed</span>
break;
}
</div>
}
This gives users visibility into the agent's workflow without exposing unnecessary internal reasoning.
Jasen FiciPosted Oct 8, 2026, 12:48 PM
This one is in DotNetNews today: https://dotnetnews.beehiiv.com/p/new-post-e766