Introduction
Calling a language model is easy. Building an agent that can work through a multi-step task, keep its context, request approval before using tools, and continue after another turn is harder.
Microsoft Agent Framework is Microsoft’s set of APIs and abstractions for building agents, sessions, messages, tools, and workflows. The Agent Harness is one runtime capability in that framework: it wraps an IChatClient and coordinates agent execution around model calls.
This is the first article in the Microsoft Agent Framework series. You do not need a separate framework introduction before reading it; this post introduces only the concepts needed for the Harness. We will build a small .NET API that keeps an agent session across requests.
What You Will Build
You will build a small customer support resolution assistant. It is backed by DeepSeek and the Agent Harness. A support agent can start with a customer issue, then continue with focused questions without resending the original context.
Session 1: "A customer cannot complete checkout after a card payment. Summarize the issue and suggest safe troubleshooting steps."
Session 2: “Turn those troubleshooting steps into a customer-facing reply and include when to escalate.”
Expected result: the second response builds on the first case because both turns use the same AgentSession.
What Is Agent Harness?
An Agent Harness is the execution layer around an agent. The model still decides what to say or which tool to call, but the Harness coordinates the work around those model calls.
In this sample, the most visible Harness behavior is session continuity. The sample does not yet add custom functions, approval workflows, durable storage, or a multi-step plan. Those capabilities are useful extensions for later articles in the series.
Without a Harness, an application commonly has to assemble these concerns itself:
- Store chat history between turns.
- Decide how multi-step work is planned and tracked.
- Invoke functions and apply approval policies.
- Control context growth and compact old history.
- Expose progress and operational state to the host application.
The Microsoft Agent Framework Harness gives these concerns a standard runtime surface. It does not replace the model, provide a model key, or decide where the application is hosted.
Agent Framework, Harness, and Hosting
These terms describe different layers:
| Layer | Responsibility |
|---|---|
| Agent Framework | APIs and abstractions for agents, sessions, messages, tools, and workflows |
| Agent Harness | Runtime scaffolding that coordinates planning, context, tools, approvals, and session state |
| Hosting | The place and infrastructure where the application runs, such as an ASP.NET Core process or a managed agent service |
The Harness can run inside a console application, an ASP.NET Core service, or another host. The host owns authentication, persistence, networking, and deployment.
Real-World Example: Customer Support Resolution Assistant
Imagine a support agent handling a customer who cannot complete checkout after a card payment. The case may require clarifying questions, safe troubleshooting, a customer-facing explanation, and escalation when the issue involves a payment or account risk. A single model response can suggest ideas, but the agent needs to continue the case while preserving the original details.
The Harness is useful here for three reasons:
- The first turn can summarize the issue and propose safe troubleshooting steps.
- The session keeps the customer and case details available during follow-up questions.
- The application can add tools later for knowledge-base search, ticket lookup, or escalation, with approval policies around consequential actions.
Start the sample and send the first prompt:
Session 1: "A customer cannot complete checkout after a card payment. Summarize the issue and suggest safe troubleshooting steps."
Session 2: “Turn those troubleshooting steps into a customer-facing reply and include when to escalate.”
Expected result: the second response refines the support case using the details from Session 1.
The API returns a sessionId. Send that value with Session 2 so the Harness can continue the same conversation.
The second request is not a new conversation. The Harness receives the same AgentSession, so the response can refine the original support case. This is a practical starting point: begin with conversation state, then add domain-specific tools as the workflow becomes more automated.
Harness Request Lifecycle
The sample architecture is:
AgentSession is important. It is the state container passed to each run. Reusing the same session lets the Harness preserve conversation history and Harness-managed state across turns. Creating a new session for every request creates a new conversation.
Create a Harness Agent
The entry point is the AsHarnessAgent extension method. It accepts an IChatClient and returns an agent with Harness behavior configured around it. This example uses DeepSeek’s OpenAI-compatible API, so the Harness code stays independent from the model provider.
|
|
The sample disables the built-in web search capability so the example has an explicit, predictable tool boundary. Enable and govern capabilities deliberately when an application needs them.
The Sample Application
AgentHarnesscontains the agent runtime and Harness configuration.AgentHarness.Apicontains the HTTP host and endpoint.AgentSessioninstances are held in an in-memory dictionary for clarity.
The runtime creates one Harness agent and reuses it for requests. Each request supplies a session ID. The first request creates a session; later requests with that ID reuse it:
|
|
In a real service, replace the dictionary with a durable session store. Also authenticate the caller and verify that the caller owns the session before resuming it. A session ID is a lookup key, not an authorization boundary.
Configure and Run
From the sample directory:
|
|
The sample reads the API key from the DS_KEY environment variable. It uses https://api.deepseek.com and deepseek-v4-flash by default. Both endpoint and model are configurable through DeepSeek:Endpoint and DeepSeek:Model.
Send a first request:
|
|
The response contains a sessionId. Send it with the next request to continue the conversation:
|
|
When to Use Agent Harness
Use a Harness when work naturally spans multiple steps or turns and the application benefits from consistent session and tool behavior. Examples include research assistants, coding agents, data analysis workflows, and operations assistants.
A plain chat client may be a better fit for a single request and response, especially when the application owns all state and does not need tool orchestration. The Harness adds useful behavior, but it also adds runtime policy that should be understood before production use.
Production Considerations
The sample is intentionally small. Production systems need additional decisions:
- Persist and version sessions instead of keeping them in process memory.
- Authenticate users and authorize every session resume.
- Restrict tools and require approval for consequential actions.
- Set execution, timeout, and token budgets.
- Record traces, tool calls, errors, and model usage.
- Pin package versions and review release notes because provider APIs are evolving.
Conclusion
Microsoft Agent Framework Agent Harness is a runtime layer that turns an IChatClient into a more capable, stateful agent. Its central idea is simple: create the Harness agent once, create a session for a conversation, and reuse that session across runs.
The next posts in this series can build on this foundation with function tools, approvals, durable sessions, context providers, and observability.