Middleware

Wrapping an agent run to observe, guard, or short-circuit it — without touching the agent's logic.

Part 9 of 72 Microsoft Agent Framework Python — Every Lesson

What it demonstrates

Middleware is the seam for cross-cutting concerns: logging, guardrails, caching, retries. In Microsoft Agent Framework a middleware is a plain async def mw(context, call_next), and there are three kinds:

One middleware=[...] list may mix all three; the framework sorts them by type.

The code

@function_middleware
async def block_dangerous_locations(context: FunctionInvocationContext, call_next) -> None:
    """Guard a TOOL call: refuse to run get_weather for a blocked location."""
    if context.function.name == "get_weather" and context.arguments.get("location") == "Mordor":
        context.result = "Refused: weather service does not cover Mordor."
        raise MiddlewareTermination(result=context.result)  # short-circuit — tool never runs
    await call_next()

An @agent_middleware timing and this block_dangerous_locations both go into Agent(..., middleware=[timing, block_dangerous_locations]). Ask for Pune and the tool runs; ask for Mordor and the function middleware refuses before the tool executes.

The gotcha

Two things trip people up. call_next takes no arguments and returns None — all state rides on context, not on a return value. And there is no context.terminate: to stop early you set context.result and raise MiddlewareTermination(result=...).

Azure / MAF mapping

The guarded agent is built on FoundryChatClient(project_endpoint=..., model=..., credential=AzureCliCredential()) pointed at Azure AI Foundry. Middleware sits entirely outside the client, so the same guard works regardless of the underlying model provider.

Run it

uv run tutorial/02-agents/01_middleware.py — needs Foundry credentials (az login plus FOUNDRY_PROJECT_ENDPOINT / FOUNDRY_MODEL). It worked if Pune returns weather and Mordor is refused.


Next: Mcp Tools

Sources & References

The Python SDK this lesson exercises
Agent middleware for observing, modifying, and short-circuiting runs