{
  "source_file": "0930",
  "source_platform": "Ghost",
  "author": "Peng Qian / Data Leads Future",
  "title_listed": "Microsoft Agent Framework (MAF) Middleware Basics: Add Compliance Fences to Your Agent",
  "keywords": "",
  "domain": "大模型算法",
  "content_type": "工程实践",
  "is_paid_flag": "否",
  "url": "https://www.dataleadsfuture.com/microsoft-agent-framework-maf-middleware-basics-add-compliance-fences-to-your-agent/",
  "publish_date": "2026-01",
  "corpus_stage": "",
  "notes": "",
  "id": "1403947dbb28",
  "collected_at": "2026-10-02T12:27:15",
  "title": "Microsoft Agent Framework (MAF) Middleware Basics: Add Compliance Fences to Your Agent",
  "body_markdown": "Agentic AI\nMicrosoft Agent Framework (MAF) Middleware Basics: Add Compliance Fences to Your Agent\nPrinciples, usage, and development standards\nPeng Qian\n09 Jan 2026\n—\n10 min read\nShare\nMicrosoft Agent Framework (MAF) Middleware Basics: Add Compliance Fences to Your Agent. Image by DALL-E-3\nIntroduction\nThe recent incident where Tencent’s Yuanbao AI insulted users once again shows that no matter how powerful an agent is, you must set up compliance guardrails and carefully review its inputs and outputs before going live.\nWhen we build enterprise-grade agent applications, we often work on a large-scale system involving multiple teams. Beyond the parts handled by our own team, we also need to dynamically plug in features from other teams—such as permissions, logging, billing, and compliance review.\nThese features should not interfere with the agent system’s core capabilities, yet they must be easy to install and remove. In traditional web frameworks like FastAPI, middleware provides exactly this kind of dynamic code injection capability. So, does something similar exist in agent systems?\nActually, yes.\nIn today’s tutorial, I’ll show you how I used Microsoft Agent Framework’s middleware and AG-UI features to add compliance review for user inputs into my agent.\nInducing an agent will be blocked by compliance rules specific to certain business scenarios. Image by Author\nThis will teach you how to use middleware in enterprise agent applications and give you a first look at using AG-UI for microservice distributed agent development. Let’s start.\nYou can get all the source code at the end. 👇\nDon’t forget to follow my blog to stay updated on my latest progress in AI application practices.\nSubscribe Now\nSystem Setup\nInstall the latest Microsoft Agent Framework\nMAF is still updating quickly. Since APIs change a lot, this guide uses the newest version. It’s better to install the prerelease version.\npip install agent-framework --pre\nOr add the dependency in your\npyproject.toml\nfile:\n\"agent-framework-ag-ui>=1.0.0b260127\"\nInstall Microsoft Agent Framework AG-UI\nMAF works with AG-UI to support distributed agent development. You’ll need this capability today, so install the latest version of ag-ui; otherwise, APIs won’t match up.\n\"agent-framework-ag-ui>=1.0.0b260127\"\nAfter installing the needed Python packages, we can move on. First, let's get a quick background on what middleware is and what it can do.\nQuick Intro to MAF Middleware\nWhat is middleware\nAccording to the MAF documentation:\nMiddleware in the Agent Framework intercepts, changes, and enhances agent behavior at different execution points. You can use it for logging, security checks, error handling, and result transformation without changing the agent’s or function’s core logic.\nThat’s what we’ll learn today.\nHow middleware works\nAs I said before, MAF middleware uses the chain-of-responsibility pattern. Each piece of logic lives in its own node. Every node knows the next one. When a node finishes running, it passes control to the next node.\nHere’s a simple example:\nasync def logging_agent_middleware(\n    context: AgentRunContext,\n    next: Callable[[AgentRunContext], Awaitable[None]]\n) -> None:\n    print(\"[Agent] Starting execution\")\n    await next(context)\n    print(\"[Agent] Execution completed\")\nThe\nnext\nparameter points to the next node. You can run code before or after calling it.\nThe actual agent logic acts as the last node. After all middleware nodes finish, the agent runs.\nIn MAF, middleware can run in three stages:\nBefore or after\nrun\nor\nrun_stream\n.\nBefore or after a function call.\nBefore or after calling the LLM.\nThe Microsoft Agent Framework middleware works at different stages of agent execution. Image by Author\nNow let’s look at how different middleware types work.\nFunction-Based middleware\nIf your middleware is simple, like just logging agent runs, use a function-based middleware.\nYou only need a function with two parameters:\ncontext\nand\nnext\n. The\ncontext\nkeeps your runtime info, and\nnext\ncalls the next node.\nMAF uses the type annotation of\ncontext\nto tell which stage this code belongs to. For example, if it runs at the agent stage, the type should be\nAgentRunContext\n:\nasync def logging_agent_middleware(\n    context: AgentRunContext,\n    next: Callable[[AgentRunContext], Awaitable[None]]\n) -> None:\n    print(\"[Agent] Starting execution\")\n    await next(context)\n    print(\"[Agent] Execution completed\")\nFor a function call stage, use\nFunctionInvocationContext\n:\nasync def logging_function_middleware(\n    context: FunctionInvocationContext,\n    next: Callable[[FunctionInvocationContext], Awaitable[None]],\n) -> None:\n    print(f\"[Function] Calling {context.function.name}\")\n    await next(context)\n    print(f\"[Function] {context.function.name} completed\")\nAnd for the chat stage, use\nChatContext\n:\nasync def logging_chat_middleware(\n    context: ChatContext,\n    next: Callable[[ChatContext], Awaitable[None]],\n) -> None:\n    print(f\"[Chat] Sending {len(context.messages)} messages to AI.\")\n    await next(context)\n    print(f\"[Chat] AI response received.\")\nIf you dislike type annotations, you can use decorators.\n@agent_middleware\nruns at the agent stage:\n@agent_middleware    \nasync def logging_agent_middleware(context, next) -> None:\n    print(\"[Agent] Starting execution\")\n    await next(context)\n    print(\"[Agent] Execution completed\")\nThen you don’t need to add type annotations anymore.\nThere are also\n@function_middleware\nand\n@chat_middleware\nfor function calls and chat calls.\nIf your middleware needs to save state or handle more complex logic, function-based won’t be enough. Use class-based middleware.\nClass-Based middleware\nClass-based middleware organizes code with object-oriented methods. That lets middleware remember state and handle tricky logic.\nA class-based middleware must meet two rules:\nInherit from the right base class:\nAgentMiddleware\n,\nFunctionMiddleware\n, or\nChatMiddleware\n.\nHave a\nprocess\nmethod with the same parameters as the function-based ones. They use the same contexts.\nHere’s an example for a middleware class that runs at the function call stage:\nclass LoggingFunctionMiddleware(FunctionMiddleware):\n    async def process(\n        self,\n        context: FunctionInvocationContext,\n        next: Callable[[FunctionInvocationContext], Awaitable[None]]\n    ) -> None:\n        print(f\"[Function Class] Calling {context.function.name}\")\n        await next(context)\n        print(f\"[Function Class] {context.function.name} completed.\")\nJust make sure to pair the right base class with the right context type. The others follow the same rule.\nHow to use middleware\nThere are three stages for middleware and three ways to build it. Let’s put that in one grid chart to see how they connect.\nUse a grid chart to describe the implementations of different middleware. Image by Author\nThe framework now only supports passing middleware when creating the agent:\nagent = chat_client.as_agent(\n    name=\"assistant\",\n    instructions=\"You are a helpful assistant\",\n    tools=[get_weather],\n    middleware=[\n        logging_agent_middleware,\n        LoggingFunctionMiddleware(),  logging_chat_middleware,\n        blocking_middleware, logging_function_middleware,\n    ]\n)\nYou can mix all nine types freely.\nBut note that\nonly the last function middleware you add actually works right now. I’m not sure if that’s a bug, but we’ll find out later.\nProject Practice: Add Compliance Check to Your Agent\nNow let’s get hands-on. I’ll show how to use MAF middleware to add compliance checking to an agent.\nWhy add compliance checks\nEvery LLM already has basic compliance setups built in based on local laws. When companies self-host LLMs, they also add custom checks in frameworks like vLLM. But those only watch the model’s input or output.\nNow that agents are everywhere, we also need checks at the agent level: preventing prompt injection, checking MCP permissions, and so on. Middleware makes this possible.\nIn today’s demo, we’ll review every user message to make sure no one tries to make our finance assistant promise investment returns.\nIn the end, the agent will refuse to answer questions like “Will I lose money?” or “Can you guarantee profit?”\nInducing an agent will be blocked by compliance rules specific to certain business scenarios. Image by Author\nHow will you do it\nWhy use compliance checks as an example? Because in real web apps, product teams don’t manage compliance themselves. The compliance department creates the rules and sends them as microservices to each product.\nThat way, teams don’t touch those rules. They just plug them in using framework middleware. It’s common in normal web apps.\nWe’ll do the same with MAF agents, using middleware to insert compliance logic.\nTo simulate real setups, this project has two parts: one server and one client.\nThe compliance check middleware will include both server and client modules. Image by Author\nOn the compliance department side, we’ll deploy a separate agent that reviews messages. It uses an LLM to check user inputs for prompt injections or non-compliant content.\nOn the business side, we’ll have a middleware that intercepts user requests and sends them to that server. It decides whether the agent should respond.\nThe two parts communicate using the AG-UI protocol.\nServer implementation\nLet’s build the compliance-checking agent server.\nSince it only checks user requests, I’ll use the\nQwen3-30b-a3b-instruct-2507\nmodel for speed.\nagent = OpenAILikeChatClient(\n    model_id=Qwen3.Q30B_A3B\n).create_agent(\n    name=\"Assistant\",\n    instructions=dedent(\"\"\"\n    You are a compliance review officer. You will review user requests or system-generated text for compliance.\n    Your main task is to check user requests and determine whether they are trying to induce the system to produce content that guarantees investment returns or similar topics.\n    \n    You should output a JSON text, like {\"is_compliance\": 1, \"reason\": \"\"}\n    \n    Here, is_compliance being 1 means compliant, and 0 means non-compliant.\n    \n    reason should state the reason for compliance or non-compliance.\n    \n    Only output the JSON text without any markdown formatting, and do not add any introduction or explanation.\n    \"\"\"),\n)\nTo make reviews clear and fast, I ask the agent to output a JSON string.\nNote: Although I made Microsoft Agent Framework support structured output for Qwen models in a previous article:\nMake Microsoft Agent Framework’s Structured Output Work With Qwen and DeepSeek Models\nThings You Always Have to Do When Switching a Framework\nData Leads Future\nPeng Qian\nI do not know if the issue comes from AG-UI protocol or MAF.\nWhen the agent acts as an AG-UI server, structured output via\nresponse-format\nstops working. You must specify the output format in the prompt.\nAfter initializing the agent, use\nadd_agent_framework_fastapi_endpoint\nfrom\nagent_framework_ag_ui\nto bind the agent to a FastAPI\napp\ninstance.\napp = FastAPI(title=\"AG-UI Server\")\nadd_agent_framework_fastapi_endpoint(app, agent, \"/compliance\")\nFinally, run it with\nuvicorn\n:\nif __name__ == \"__main__\":\n    import uvicorn\n    uvicorn.run(app, host=\"0.0.0.0\", port=8888)\nMiddleware implementation\nThis middleware is more complex, so we’ll use class-based middleware.\nHere’s the full code:\nclass ComplianceCheckMiddleware(ChatMiddleware):\n    def __init__(self, *args, **kwargs):\n        self._init_compliant_agent()\n        super().__init__(*args, **kwargs)\n\n    async def process(\n        self,\n        context: ChatContext,\n        next: Callable[[ChatContext], Awaitable[None]],\n    ):\n        check_result: ReviewResults = await self._get_compliance_result(context)\n        if not check_result.is_compliance:\n            self._output_result(\n                context,\n                f\"😒We can’t keep providing the service because:\\n{fill(check_result.reason)}\")\n            return\n\n        await next(context)\n\n    @staticmethod\n    def _output_result(context: ChatContext, response: str) -> None:\n        if context.is_streaming: #4\n            async def output_stream() -> AsyncIterable[AgentRunResponseUpdate]:\n                yield AgentRunResponseUpdate(contents=[TextContent(text=response)])\n            context.result = output_stream()\n        else:\n            context.result = AgentRunResponse(\n                messages=[ChatMessage(role=Role.ASSISTANT, text=response)]\n            )\n\n    async def _get_compliance_result(self, context: ChatContext) -> ReviewResults:\n        messages = [message for message in context.messages if message.role.value == \"user\"][-5:]\n        response = await self.agent.run(messages) #2\n\n        check_result = ReviewResults.model_validate_json(response.text) #3\n        return check_result\n\n    def _init_compliant_agent(self) -> None:\n        client = AGUIChatClient(  #1\n            endpoint=\"http://127.0.0.1:8888/compliance\"\n        )\n        self.agent = client.as_agent(\n            name=\"compliance_agent\",\n            instructions=\"You’re a compliance officer, and you review user requests.\"\n        )\nA few details to watch:\n_init_compliant_agent\ncreates the AG-UI client but works just like a normal chat client.\nI sent recent user messages for better review accuracy.\nBut the\nAgentMiddleware\ncontext only holds the latest message. To get the message history, you must use\nChatMiddleware\n.\nSince AG-UI doesn’t support\nresponse_format\n, I parse JSON manually.\n_output_result\nsends text output if a check fails. It switches based on\ncontext.is_streaming\n.\nNow we can make a business agent. Use a bigger model and a normal system prompt; just remember to load the\nComplianceCheckMiddleware\n.\nchat_client = OpenAILikeChatClient(model_id=Qwen3.NEXT)\nagent = chat_client.as_agent(\n    name=\"chat_assistant\",\n    instructions=\"You are a helpful assistant. Answer the user's question in short and simple words.\",\n    middleware=[ComplianceCheckMiddleware()]\n)\nLet’s test it with a multi-turn chat client:\nasync def main():\n    thread = agent.get_new_thread()\n    while True:\n        user_input = input(\"\\nUser: \")\n        if user_input.startswith(\"exit\"):\n            break\n        stream = agent.run_stream(user_input, thread=thread)\n        print(\"\\nAssistant: \")\n        async for event in stream:\n            print(event.text, end=\"\", flush=True)\n        print()\nYou’ll see the agent chats normally most of the time.\nIf you ask about guaranteed returns, it refuses to answer but continues working fine afterward.\nTask done.\nConclusion\nIn this guide, we explored how middleware works in Microsoft Agent Framework.\nMiddleware lets us add new logic for logging, permissions, or compliance without touching the main agent code or prompt text.\nIn the project section, I used class-based middleware to show how to review user inputs for compliance.\nWe also took a quick look at AG-UI for building agent microservices. This helps when many teams need to make agents collaborate, and I’ll cover AG-UI and A2A in detail later.\nIf you have questions or want to learn more, leave a comment.\nDon’t forget to subscribe to my blog and share this article with your friends—maybe it’ll help someone build smarter agents 😁.\nHere is the source code of this article:\nagentic-ai-playground/11_MAF_Middleware_Basic at main · qtalen/agentic-ai-playground\nContribute to qtalen/agentic-ai-playground development by creating an account on GitHub.\nGitHub\nqtalen\nFollow Data Leads Future\nOne practical story every month, sharing my hard-learned experiences in the enterprise AI space.\nSubscribe\nEmail sent! Check your inbox to complete your signup.\nYou can unsubscribe anytime.",
  "metadata": {
    "title": "Microsoft Agent Framework (MAF) Middleware Basics: Add Compliance Fences to Your Agent",
    "description": "Learn how to use Microsoft Agent Framework middleware to add compliance checks to agents, connect AG-UI services, and build enterprise-ready AI systems.",
    "keywords": null,
    "author": null,
    "og:site_name": "Data Leads Future",
    "og:type": "article",
    "og:title": "Microsoft Agent Framework (MAF) Middleware Basics: Add Compliance Fences to Your Agent",
    "og:description": "Principles, usage, and development standards",
    "og:url": "https://www.dataleadsfuture.com/microsoft-agent-framework-maf-middleware-basics-add-compliance-fences-to-your-agent/",
    "og:image": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/size/w1200/2026/01/middleware_cover.webp",
    "og:image:width": "1200",
    "og:image:height": "686",
    "twitter:card": "summary_large_image",
    "twitter:title": "Microsoft Agent Framework (MAF) Middleware Basics: Add Compliance Fences to Your Agent",
    "twitter:description": "Principles, usage, and development standards",
    "twitter:url": "https://www.dataleadsfuture.com/microsoft-agent-framework-maf-middleware-basics-add-compliance-fences-to-your-agent/",
    "twitter:image": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/size/w1200/2026/01/middleware_cover.webp",
    "twitter:label1": "Written by",
    "twitter:data1": "Peng Qian",
    "twitter:label2": "Filed under",
    "twitter:data2": "Agentic AI, Generative AI, Microsoft Agent Framework",
    "twitter:site": "@qtalen",
    "twitter:creator": "@qtalen",
    "article:published_time": "2026-01-09T08:43:23.000Z",
    "article:modified_time": "2026-04-22T08:19:22.000Z",
    "article:tag": "Microsoft Agent Framework"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/1403947dbb28/code/body-000.txt",
      "chars": 33,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-001.txt",
      "chars": 37,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-002.txt",
      "chars": 37,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-003.txt",
      "chars": 236,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-004.txt",
      "chars": 236,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-005.txt",
      "chars": 295,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-006.txt",
      "chars": 259,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-007.txt",
      "chars": 185,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-008.txt",
      "chars": 382,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-009.txt",
      "chars": 304,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-010.txt",
      "chars": 775,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-011.txt",
      "chars": 99,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-012.txt",
      "chars": 93,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-013.txt",
      "chars": 1766,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-014.txt",
      "chars": 262,
      "language": "text"
    },
    {
      "file": "attachments/1403947dbb28/code/body-015.txt",
      "chars": 361,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/size/w1200/2026/01/middleware_cover.webp",
      "bytes": 103198,
      "reused": true,
      "local_path": "attachments/1403947dbb28/images/000.webp",
      "src": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/size/w1200/2026/01/middleware_cover.webp",
      "alt": "Microsoft Agent Framework (MAF) Middleware Basics: Add Compliance Fences to Your Agent. ",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/2026/01/image.png",
      "bytes": 177808,
      "reused": true,
      "local_path": "attachments/1403947dbb28/images/005.png",
      "src": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/2026/01/image.png",
      "alt": "Inducing an agent will be blocked by compliance rules specific to certain business scenarios.",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/2026/01/image-1.png",
      "bytes": 22088,
      "reused": true,
      "local_path": "attachments/1403947dbb28/images/007.png",
      "src": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/2026/01/image-1.png",
      "alt": "The Microsoft Agent Framework middleware works at different stages of agent execution. ",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/2026/01/image-2.png",
      "bytes": 31168,
      "reused": true,
      "local_path": "attachments/1403947dbb28/images/009.png",
      "src": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/2026/01/image-2.png",
      "alt": "Use a grid chart to describe the implementations of different middleware.",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/2026/01/image-3.png",
      "bytes": 39771,
      "reused": true,
      "local_path": "attachments/1403947dbb28/images/011.png",
      "src": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/2026/01/image-3.png",
      "alt": "Inducing an agent will be blocked by compliance rules specific to certain business scenarios.",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/2026/01/image-4.png",
      "bytes": 14146,
      "reused": true,
      "local_path": "attachments/1403947dbb28/images/013.png",
      "src": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/2026/01/image-4.png",
      "alt": "The compliance check middleware will include both server and client modules.",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/icon/color_192_192-57.png",
      "bytes": 17721,
      "reused": false,
      "local_path": "attachments/1403947dbb28/images/body-f4b9f590a741838cb0f7.png",
      "src": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/icon/color_192_192-57.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/thumbnail/Agent_Framework_cover-2.webp",
      "bytes": 133426,
      "reused": true,
      "local_path": "attachments/1403947dbb28/images/015.webp",
      "src": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/thumbnail/Agent_Framework_cover-2.webp",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/icon/pinned-octocat-093da3e6fa40-29.svg",
      "bytes": 1009,
      "reused": false,
      "local_path": "attachments/1403947dbb28/images/body-fe20f3db4cfe97e42cdf.svg",
      "src": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/icon/pinned-octocat-093da3e6fa40-29.svg",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/thumbnail/agentic-ai-playground-27",
      "bytes": 99605,
      "reused": false,
      "local_path": "attachments/1403947dbb28/images/body-68e16597bde17785fea4.img",
      "src": "https://storage.ghost.io/c/33/67/33678c00-2c15-4961-93e9-497b427e2006/content/images/thumbnail/agentic-ai-playground-27",
      "alt": "",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [],
  "links": [
    {
      "href": "https://www.dataleadsfuture.com/tag/agentic-ai/",
      "label": "Agentic AI",
      "type": "a"
    },
    {
      "href": "https://www.dataleadsfuture.com/author/peng/",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://www.dataleadsfuture.com/make-microsoft-agent-frameworks-structured-output-work-with-qwen-and-deepseek-models/",
      "label": "Make Microsoft Agent Framework’s Structured Output Work With Qwen and DeepSeek Models Things You Always Have to Do When ",
      "type": "a"
    },
    {
      "href": "https://github.com/qtalen/agentic-ai-playground/tree/main/11_MAF_Middleware_Basic",
      "label": "agentic-ai-playground/11_MAF_Middleware_Basic at main · qtalen/agentic-ai-playground Contribute to qtalen/agentic-ai-pla",
      "type": "a"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:47:47Z",
  "source_url": "https://www.dataleadsfuture.com/microsoft-agent-framework-maf-middleware-basics-add-compliance-fences-to-your-agent/",
  "papers": [],
  "actual_video_files": [],
  "body_chars": 15605,
  "expected_body_images": 10,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/1403947dbb28/pages/source.html",
  "local_html": "attachments/1403947dbb28/pages/article.html",
  "body_base_path": "attachments/1403947dbb28/pages/",
  "body_markdown_path": "attachments/1403947dbb28/pages/article.md"
}