Microsoft Agent Framework — overview
MAF is Microsoft's unified agent framework, replacing AutoGen and Semantic Kernel. Here's the shape of a first agent and the four building blocks you'll use.
What you'll learn
- Why MAF exists and what it replaces (AutoGen + Semantic Kernel)
- The four building blocks — ChatAgent, tools, threads, workflows
- The shape of a minimum agent in MAF
- When MAF is the right choice over LangGraph or ADK
Before you start
If you’re building agents on Azure, you’ll meet Microsoft Agent
Framework (MAF) — the agent-framework Python package that Microsoft
shipped in 2025 to replace its previous two agent libraries. Before MAF
there was AutoGen (research-flavored, multi-agent conversations) and
Semantic Kernel (enterprise-flavored, plugins and orchestration).
They overlapped, confused customers, and split the docs. MAF is the
merger — one SDK, one mental model.
What MAF actually is
MAF is a Python (and .NET) SDK with four building blocks:
| Block | What it is |
|---|---|
| ChatAgent | An LLM + instructions + tools. The unit of agency. |
| Tools | Python functions the agent can call. Hosted ones too — code interpreter, file search, web search. |
| Threads | Conversation state. A thread persists messages so the agent can hold context across turns. |
| Workflows | Graphs of agents (and other executors) for multi-agent orchestration. |
If you’ve used LangChain or ADK, the shape is familiar. What MAF gets
right is the Azure integration: AzureOpenAIChatClient is a
first-class object, Entra ID auth is built in, and the framework ships
with conventions for Foundry, Bot Service, and Azure Functions hosting.
The hello-world agent
Here’s the smallest useful MAF program. You give it an Azure OpenAI client, instructions, and call it.
# requires: pip install agent-framework
# This is the shape of MAF code — a reference you'd paste into a real
# Python file and run against Azure with your own credentials.
from agent_framework import ChatAgent
from agent_framework.azure import AzureOpenAIChatClient
from azure.identity import AzureCliCredential
# 1. The model client. Auth via Entra ID — no API key in code.
chat_client = AzureOpenAIChatClient(
credential=AzureCliCredential(),
endpoint="https://my-foundry-resource.openai.azure.com",
deployment_name="gpt-4.1",
)
# 2. The agent. Instructions = system prompt; no tools yet.
agent = ChatAgent(
chat_client=chat_client,
name="data-explainer",
instructions=(
"You explain data engineering concepts in two sentences. "
"Never use marketing language."
),
)
# 3. Call it. .run() is one-shot; .run_stream() yields tokens.
async def main():
result = await agent.run("What is a window function in SQL?")
print(result.messages[-1].text)
# In real code: asyncio.run(main())
print("Shape only — real run needs Azure creds.")
Three objects: client, agent, call. That’s the whole API surface for a
non-tool agent. Notice there’s no separate “session” or “memory” object
yet — agent.run() is stateless by default. Conversation state lives
in threads, the next building block.
Threads — conversation persistence
A ChatAgent on its own forgets between calls. If you want a follow-up
question to know what the user just asked, you pass a thread — a
named container that accumulates the message history across multiple
agent.run() calls.
thread = agent.get_new_thread() # in-memory by default
await agent.run("What is a window function?", thread=thread)
await agent.run("Show me one in PySpark", thread=thread)
# Second call has the first in context.
Threads can be backed by a store — Azure Cosmos DB, Redis, or a custom
backend — so conversations survive process restarts. For production,
you almost always want a persisted thread keyed by user_id +
conversation_id.
Tools and workflows in one minute
Tools come from plain Python functions. You write def get_weather(city: str) -> dict: with a docstring, pass it to ChatAgent(tools=[...]),
and MAF generates the JSON schema, handles the tool-call loop, and
gives you result back. The next lesson covers tools in depth.
Workflows are where multiple agents collaborate as a graph — a researcher agent feeds a writer agent feeds a critic agent. Workflows have explicit nodes (“executors”), edges, and conditions. They’re overkill for a single chat agent but essential when you need agent-to-agent handoffs.
When MAF wins
Be honest about when to reach for MAF versus the alternatives:
- You’re on Azure already. Foundry, Azure OpenAI, AKS, Entra ID
— MAF is the path of least resistance. Auth, telemetry (via OpenTelemetry
- App Insights), and deployment are all wired up.
- Your team uses .NET. MAF has full .NET parity, unlike LangGraph (Python/JS only) or ADK (Python-first).
- You need enterprise-grade governance. Microsoft ships content filtering, PII detection, and audit logging as first-class middleware — see the middleware lesson.
When not to reach for MAF:
- You’re on AWS or GCP with no Azure footprint. The integration value evaporates and you’re left with a perfectly fine but generic SDK.
- You want the largest community/ecosystem. LangChain still wins on tutorials, integrations, and StackOverflow answers.
API stability note
In one breath
- MAF is Microsoft’s unified
agent-frameworkSDK (Python + .NET), the GA successor that merges AutoGen and Semantic Kernel (now maintenance-mode). - Four building blocks: ChatAgent (LLM + instructions + tools), Tools (Python functions + hosted ones), Threads (conversation state), Workflows (multi-agent graphs).
- A minimal agent is three objects — client, agent, call — and
agent.run()is stateless by default; pass a thread to carry history across turns. - Its edge is Azure integration (AzureOpenAIChatClient, Entra ID auth, Foundry/Functions hosting) and full .NET parity.
- Reach for it on Azure or .NET; off Azure, LangGraph or the OpenAI Agents SDK are the vendor-neutral defaults — and threads are history containers, not auth sessions.
Quick check
Quick check
Next
The next lesson covers tools — how Python functions become agent tools, how human-in-the-loop approval works, and the hosted tools MAF gives you for free.
Practice this in an interview
All questionsAn agent is an LLM placed in a loop where it reasons, chooses and calls tools or actions, observes the results, and repeats until a goal is met, rather than producing one response and stopping. The key differences are autonomy, tool use, memory and state, and multi-step control flow driven by the model's own decisions.
Tool calling extends the LLM's output space to include structured function invocations. The model emits a JSON object naming a tool and its arguments; the runtime executes the tool and feeds the result back as a new message. An agent is a loop that repeats this cycle — observe, think, act — until the task is complete or a stopping condition is met.
Key risks include prompt injection, especially indirect injection via tool or retrieval outputs, hijacking the agent, excessive tool permissions enabling damaging actions, data exfiltration, confused-deputy privilege escalation, and unbounded loops driving cost or harm. Mitigations include least-privilege tools, sandboxing, input and output guardrails, human-in-the-loop approval for sensitive actions, and audit logging.
AutoML automates parts of the ML pipeline such as data preprocessing, feature engineering, model selection, hyperparameter tuning, and sometimes neural architecture search, lowering the barrier to building models. It falls short on problem framing, data quality, domain feature engineering, careful evaluation against leakage, fairness, and deployment concerns, which still need human expertise. It's best as an accelerator and strong baseline generator, not a replacement for an ML engineer.