Microsoft Agent Framework at BUILD 2026: Agent Harness, Hosted Agents, CodeAct, and more

Microsoft used BUILD 2026 to push out a fairly large batch of updates to Agent Framework (MAF), the open source SDK for building AI agents and multi-agent workflows across .NET and Python. MAF reached 1.0 general availability on April 2, 2026, bringing together AutoGen and Semantic Kernel into one supported platform. The BUILD announcements build directly on that 1.0 base, and most of them are things teams running agents in production have been asking for: better handling of long-running sessions, an actual hosting story, and a faster execution path for agents that make lots of tool calls.

This post walks through the four pieces that matter most from a build-and-ship perspective: the Agent Harness, Foundry Hosted Agents, CodeAct, and the newly GA’d GitHub Copilot SDK integration and Handoff orchestration pattern. I have added my own observations on where each of these genuinely helps and where you should slow down before adopting them in a production agent.

Agent Harness: production patterns built into the SDK

Anyone who has shipped an agent past the demo stage knows the unglamorous part is not the model call, it is everything around it: giving the agent shell and filesystem access safely, adding human approval before a risky tool runs, and keeping the context window from blowing up during a long tool-calling chain. Until now, every team wrote this plumbing themselves, slightly differently each time. The Agent Harness turns this into a first class concept in MAF, and any chat client can be converted into a full harness agent with a single method call.

In .NET, that method is AsHarnessAgent, and it accepts the usual chat options plus a file store for persisted memory. The example below sets up a blog writing agent with a web browsing tool and runs it through a console helper.

AIAgent agent =
    chatClient.AsHarnessAgent(MaxContextWindowTokens, MaxOutputTokens, new HarnessAgentOptions
    {
        Name = "BlogWriterAgent",
        Description = "A blog writing assistant that researches a topic, plans an outline, and drafts a blog post.",
        FileMemoryStore = new FileSystemAgentFileStore(Path.Combine(AppContext.BaseDirectory, "artifacts")),
        ChatOptions = new ChatOptions
        {
            Instructions = instructions,
            Tools = [ new WebBrowsingTool() ],
        },
    });
 
await HarnessConsole.RunAgentAsync(
    agent,
    userPrompt: "Enter a blog topic to get started.",
    new HarnessConsoleOptions
    {
        Observers = [ new OpenAIResponsesWebSearchDisplayObserver(), new OpenAIResponsesErrorObserver() ],
        CommandHandlers = HarnessConsoleOptions.BuildDefaultCommandHandlers(agent),
    });

Notice that the agent itself is still just an AIAgent. The harness wraps around the chat client and layers on context management, storage, and console wiring, so none of your existing agent code needs to change. The Python side reads similarly, and MAF configures the sensible defaults for you rather than asking you to wire up ten separate providers.

agent = create_harness_agent(
    client=client,
    max_context_window_tokens=128_000,
    max_output_tokens=16_384,
    name="ResearchAgent",
    description="A research assistant that plans and executes research tasks.",
    agent_instructions=RESEARCH_INSTRUCTIONS,
)

One line and you get context compaction, todo tracking, plan versus execute modes, and telemetry, all configured with reasonable defaults. If you have hand-rolled any of this before, you will recognize how much boilerplate this quietly removes.

What actually ships inside the harness

The harness is not one feature, it is a bundle of building blocks that Microsoft has clearly pulled from real production agent deployments. Worth knowing what is included before you decide whether to adopt the whole thing or just the pieces you need.

  • Automatic context compaction: watches token usage and compacts chat history mid-loop so long tool-calling chains do not overflow the context window
  • Built-in default instructions with instruction merging: harness instructions run first, then your custom agent instructions layer on top
  • FileMemoryProvider: session-scoped file memory so the agent can persist notes across turns, stored under agent-file-memory/{session}/
  • FileAccessProvider: general file read and write access for the agent to operate on
  • TodoProvider: lets the agent add, complete, remove, and list work items as part of session state
  • AgentModeProvider: separates a planning mode from an execution mode
  • AgentSkillsProvider: discovers and runs skills from the filesystem for modular capability injection
  • BackgroundAgentsProvider: delegates subtasks to child agents running in parallel
  • Hosted web search, and on .NET, sandboxed shell execution through ShellExecutor
  • ToolApprovalAgent for don’t-ask-again approval rules on sensitive tool calls, and OpenTelemetryAgent for automatic tracing

The part I would flag for anyone evaluating this: storage is pluggable. FileMemoryStore and FileAccessStore can be swapped for any AgentFileStore implementation, including blob storage, so you are not locked into local disk if you are running this in a container that gets recycled.

Foundry Hosted Agents: from local to production

Once an MAF agent runs on your laptop, the next problem is always deployment: where does it run, how does it scale, who is watching it. Hosted Agents in Foundry Agent Service packages your agent code as a container and deploys it onto Foundry-managed infrastructure, with identity, autoscaling, session state, and observability handled for you.

Four things stand out in what you get by default. The agent scales to zero and costs nothing while idle, then scales back up on the next request. When it resumes, the filesystem, disk state, and session identity are all intact, so the agent picks up exactly where it stopped rather than starting cold. Every session runs in its own VM-isolated sandbox with persistent state, and MAF’s OpenTelemetry traces flow into Application Insights without any extra wiring on your part.

Turning a local agent into a hosted one is a small amount of code. In .NET, it is a couple of service registrations and a route mapping.

using Microsoft.Agents.AI.Foundry.Hosting;
 
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddFoundryResponses(agent);
 
var app = builder.Build();
app.MapFoundryResponses();
 
app.Run();

In Python it is even shorter, a single wrapper class around your existing agent object.

server = ResponsesHostServer(agent)
 
server.run()

This is convenient, but it is worth being clear-eyed about what you are signing up for. Scale-to-zero with persistent filesystem state across sessions means Microsoft is managing storage and identity on your behalf, which is exactly what most teams want, but it also ties your hosting story to Foundry. If you already run agents on your own Kubernetes cluster or another cloud, weigh the operational savings here against the migration cost before committing an entire fleet of agents to this path.

CodeAct: cutting down model turns for tool-heavy agents

This is the part of the announcement I found most interesting from a cost and latency angle. A typical tool-calling agent picks a tool, waits for the model to see the result, picks the next tool, and so on. Each of those steps is a separate model turn, and when a task needs dozens of small tool calls, that adds up fast in both latency and token spend.

CodeAct changes the pattern. Instead of choosing tools one at a time, the model writes a single short Python program that calls your tools through call_tool(…), the program runs once inside a sandbox, and the agent gets back one consolidated result. It ships in the new agent-framework-hyperlight package, currently in alpha, which runs the generated code inside a fresh Hyperlight micro-VM per call. That gives you strong isolation per tool-calling round without the usual overhead of spinning up a full VM each time.

Wiring this in does not require restructuring your tools, just registering them with a different provider.

from agent_framework import Agent, tool
from agent_framework_hyperlight import HyperlightCodeActProvider
 
@tool
def get_weather(city: str) -> dict[str, float | str]:
    """Return the current weather for a city."""
    return {"city": city, "temperature_c": 21.5, "conditions": "partly cloudy"}
 
codeact = HyperlightCodeActProvider(
    tools=[get_weather],
    approval_mode="never_require",
)
 
agent = Agent(
    client=client,
    name="CodeActAgent",
    instructions="You are a helpful assistant.",
    context_providers=[codeact],
)
 
result = await agent.run(
    "Get the weather for Seattle and Amsterdam and compare them."
)

The @tool function itself is unchanged, the only new piece is the HyperlightCodeActProvider that gets passed to the agent as a context provider. Microsoft published benchmark numbers from a representative multi-step workload, computing order totals across many users with dozens of tool calls involved.

  • Traditional tool-calling wiring: 27.81 seconds, 6,890 tokens
  • CodeAct wiring: 13.23 seconds, 2,489 tokens
  • Improvement: 52.4% faster, 63.9% fewer tokens

Those are meaningful savings, but two caveats are worth keeping in mind. First, the package is alpha, so treat it as something to pilot on a non-critical workflow rather than something to put in front of customers immediately. Second, CodeAct trades a very predictable, individually-observable tool call sequence for a single generated program, which makes step-by-step debugging and per-call approval gates harder to reason about. For agents where every tool call needs a human sign-off, or where you need to trace exactly which call failed and why, the traditional loop is still the safer default. For high-volume batch style workflows like the benchmark above, CodeAct looks like a genuinely good trade.

Also reaching 1.0: GitHub Copilot SDK and Handoff orchestration

Two more features moved from preview to general availability alongside the harness and hosting work. The first is support for building MAF agents on top of the GitHub Copilot SDK as a backend, which brings Copilot’s coding-oriented capabilities such as shell execution, file operations, URL fetching, and MCP server integration into the standard MAF programming model.

import asyncio
from agent_framework.github import GitHubCopilotAgent
 
async def basic_example():
    agent = GitHubCopilotAgent(
        default_options={"instructions": "You are a helpful assistant."},
    )
 
    async with agent:
        result = await agent.run("What is Microsoft Agent Framework?")
        print(result)

The .NET equivalent starts a Copilot client and wraps it as a standard AIAgent, so from that point on it supports the same tools, sessions, and OpenTelemetry tracing as any other MAF agent.

using GitHub.Copilot.SDK;
using Microsoft.Agents.AI;
 
await using CopilotClient copilotClient = new();
await copilotClient.StartAsync();
 
AIAgent agent = copilotClient.AsAIAgent();
 
Console.WriteLine(await agent.RunAsync("What is Microsoft Agent Framework?"));

The second GA feature is the Handoff orchestration pattern for multi-agent systems. Most multi-agent setups start as a simple router that forwards a request to a specialist agent, and that pattern tends to break the first time a specialist needs a follow-up question or realizes mid-conversation that the request actually belongs somewhere else. Handoff orchestration addresses this by having you declare the agents and the directed edges between them, while the framework injects the actual handoff tools each agent uses to pass control along.

AIAgent triage = chatClient.AsAIAgent(
    instructions: "You receive a user request and route it to the right specialist.",
    name: "Triage");
 
AIAgent billing = chatClient.AsAIAgent(
    instructions: "You handle billing questions.", name: "Billing");
 
AIAgent tech = chatClient.AsAIAgent(
    instructions: "You handle technical support questions.", name: "Tech");
 
Workflow workflow = AgentWorkflowBuilder
    .CreateHandoffBuilderWith(triage)
    .WithHandoff(triage, billing)
    .WithHandoff(triage, tech)
    .Build();

The topology (who can hand off to whom) stays in your code as a declared graph, while the actual decision of when to hand off is left to the agents themselves at runtime. Python developers get the same graph through a HandoffBuilder.

from agent_framework_orchestrations import HandoffBuilder
 
workflow = (
    HandoffBuilder(participants=[triage, billing, tech])
    .with_start_agent(triage)
    .add_handoff(triage, [billing, tech])
    .build()
)

Practical takeaways

Taken together, this release is less about a single new capability and more about closing gaps that showed up once teams tried to run MAF agents in production rather than in a notebook. The Agent Harness is the one I would adopt first for any new agent, since context compaction and approval flows are things you will build eventually anyway, and getting them for one method call is a straightforward win.

Foundry Hosted Agents is worth a pilot if you are already committed to Azure, less so if your infrastructure lives elsewhere, since the scale-to-zero and persistent state benefits come bundled with a Foundry dependency. CodeAct is the one to watch rather than adopt immediately, given the alpha label on the Hyperlight package, but the token and latency numbers make a strong case for tool-heavy batch workloads once it stabilizes. Handoff orchestration and the Copilot SDK integration are both safe to use today since they are GA, and Handoff in particular is a cleaner mental model than hand-rolled routing logic if you are running more than two or three specialist agents.

Leave a Reply

Discover more from Behind the Stack

Subscribe now to keep reading and get access to the full archive.

Continue reading