Skip to content

Microsoft Agent Framework

pip install "mimir-decisions[local,agent-framework]"

mimir.integrations.agent_framework.as_function_tool converts a decision tool into a FunctionTool that returns the typed result as JSON.

ToolCallCheckMiddleware is function middleware that intercepts each tool call before it runs. Only calls that receive a certified ALLOW are forwarded to the tool. A certified DENY and an uncertified ESCALATE both block the call, and the model receives the check's reason instead.

Tested from agent-framework-core 1.19.

Native tools

"""A Microsoft Agent Framework agent that routes support tickets with a MIMIR decision tool.

Install `mimir-decisions[local,agent-framework]` and `agent-framework-openai`, set `OPENAI_API_KEY`,
then run `make example NAME=agent_framework/agent`.
"""

import asyncio
from typing import Any, Final

from agent_framework import Agent, BaseChatClient

from mimir import Choice, Decider, Mimir
from mimir.integrations.agent_framework import as_function_tool

MODEL: Final = "gpt-5.5"
TEAMS: Final = {
    "billing": "Billing: payments, refunds and invoices",
    "security": "Security: account access, passwords and fraud",
    "shipping": "Shipping: deliveries, tracking and returns",
}
INSTRUCTIONS: Final = (
    "Route the customer's ticket with route_ticket, then tell the customer which team will "
    "answer. If the decision is deferred, say that a person will review the ticket."
)


def build_agent(decider: Decider, client: BaseChatClient[Any]) -> Agent:
    """The support agent, answering with `decider`."""
    route_ticket = decider.tool(
        "route_ticket",
        Choice("Which team should handle this ticket?", TEAMS),
        description="Route a customer support ticket to the team that owns it.",
    )
    return Agent(client=client, instructions=INSTRUCTIONS, tools=[as_function_tool(route_ticket)])


async def main() -> None:
    from agent_framework.openai import OpenAIChatClient

    agent = build_agent(Mimir.from_pretrained("Mythologic/MIMIR-1"), OpenAIChatClient(model=MODEL))
    print((await agent.run("I was charged twice for order 4412.")).text)


if __name__ == "__main__":
    asyncio.run(main())

Tool-call check

"""A Microsoft Agent Framework agent whose refunds MIMIR checks against the refund rules
first.

A certified yes runs the refund; otherwise the refund does not run and the model reads the
check's reason. Install `mimir-decisions[local,agent-framework]` and `agent-framework-openai`, set
`OPENAI_API_KEY`, then run `make example NAME=agent_framework/guarded_agent`.
"""

import asyncio
from typing import Any, Final

from agent_framework import Agent, BaseChatClient, FunctionTool

from mimir import Decider, Mimir
from mimir.integrations.agent_framework import ToolCallCheckMiddleware

MODEL: Final = "gpt-5.5"
RULES: Final = (
    "A refund is at most the amount the customer paid for the order.",
    "Refunds above 500 dollars need a manager's approval.",
)
INSTRUCTIONS: Final = "Issue the refunds customers ask for with issue_refund."


def issue_refund(order: str, amount: float) -> str:
    """Refund `amount` dollars on `order`."""
    return f"Refunded {amount:.2f} dollars on order {order}."


def build_agent(
    decider: Decider, client: BaseChatClient[Any], refund: FunctionTool | None = None
) -> Agent:
    """The refunds agent, its refund tool checked by `decider` against `RULES`."""
    tool = refund or FunctionTool(
        name="issue_refund", description="Refund the customer.", func=issue_refund
    )
    check = decider.tool_call_check(RULES, tools=[tool.name])
    return Agent(
        client=client,
        instructions=INSTRUCTIONS,
        tools=[tool],
        middleware=[ToolCallCheckMiddleware(check)],
    )


async def main() -> None:
    from agent_framework.openai import OpenAIChatClient

    agent = build_agent(Mimir.from_pretrained("Mythologic/MIMIR-1"), OpenAIChatClient(model=MODEL))
    print((await agent.run("Refund 900 dollars on order 4412.")).text)


if __name__ == "__main__":
    asyncio.run(main())

Over MCP

"""A Microsoft Agent Framework agent using MIMIR's MCP server over stdio, through
`MCPStdioTool`.

The server runs `examples/tools.yaml`, so the agent sees `route_ticket` and passes only the
ticket. Agent Framework's MCP client needs the MCP SDK 1, so the server runs in its own
environment through `uvx`. Install `agent-framework`, `mcp<2` and `uv`, set
`OPENAI_API_KEY`, then run `make example NAME=agent_framework/mcp_agent`.
"""

import asyncio
from collections.abc import Sequence
from pathlib import Path
from typing import Any, Final

from agent_framework import Agent, BaseChatClient, MCPStdioTool

MODEL: Final = "gpt-5.5"
TOOLS: Final = Path(__file__).parents[1] / "tools.yaml"
SERVER: Final = (
    "uvx",
    ("--from", "mimir-decisions[local,mcp]", "mimir-decisions", "mcp", "--tools", str(TOOLS)),
)
INSTRUCTIONS: Final = (
    "Route the customer's ticket with route_ticket, then tell the customer which team will "
    "answer. If the decision is deferred, say that a person will review the ticket."
)


def mimir_server(command: str, arguments: Sequence[str]) -> MCPStdioTool:
    """MIMIR's MCP server, started as `command` with `arguments`."""
    return MCPStdioTool(name="mimir", command=command, args=list(arguments))


def build_agent(server: MCPStdioTool, client: BaseChatClient[Any]) -> Agent:
    """The support agent, with the tools of `server`."""
    return Agent(client=client, instructions=INSTRUCTIONS, tools=[server])


async def main() -> None:
    from agent_framework.openai import OpenAIChatClient

    async with mimir_server(*SERVER) as server:
        agent = build_agent(server, OpenAIChatClient(model=MODEL))
        print((await agent.run("I was charged twice for order 4412.")).text)


if __name__ == "__main__":
    asyncio.run(main())