Skip to main content

Microsoft 365 Agents

Integrate AgentGuard directly into Microsoft 365 Agents at the tool-call layer — no Virtue Gateway required.

Before you start

Review the AgentGuard SDK reference for client setup, result fields, and error handling.

Installation

pip install agentsuite-sdk microsoft-agents-hosting-aiohttp 'semantic-kernel[mcp]' openai

Quickstart

1. Guard client

from agentsuite import AsyncActionGuardClient, GuardError

guard = AsyncActionGuardClient(api_key=..., policy_id=...)

2. FUNCTION_INVOCATION filter

Scope the filter to your MCP plugin by checking context.function.plugin_name.

from semantic_kernel.functions import FunctionResult

_MCP_PLUGIN_NAME = "action_guard_demo"

class ActionGuardFilter:
async def __call__(self, context, next) -> None:
if context.function.plugin_name != _MCP_PLUGIN_NAME:
await next(context)
return

tool_name = context.function.name
tool_args = dict(context.arguments) if context.arguments else {}

try:
result = await guard.actions.guard_query(
query=f"Tool: {tool_name}, Args: {tool_args}",
)
if not result.allowed:
context.result = FunctionResult(
function=context.function.metadata,
value=f"[BLOCKED by Action Guard: {result.explanation or 'Policy violation'}]",
)
return
except GuardError as e:
context.result = FunctionResult(
function=context.function.metadata,
value=f"[Action Guard unavailable: {e.message}]",
)
return

await next(context)

3. Kernel, MCP plugin, and filter

from semantic_kernel import Kernel
from semantic_kernel.connectors.ai.open_ai import OpenAIChatCompletion
from semantic_kernel.connectors.mcp import MCPStreamableHttpPlugin
from semantic_kernel.filters import FilterTypes

kernel = Kernel()
kernel.add_service(OpenAIChatCompletion(ai_model_id="...", api_key=...))
kernel.add_filter(FilterTypes.FUNCTION_INVOCATION, ActionGuardFilter())

_mcp_headers = {"X-API-Key": MCP_API_KEY} if MCP_API_KEY else {}
_mcp_plugin = MCPStreamableHttpPlugin(
name=_MCP_PLUGIN_NAME,
description="...",
url=MCP_SERVER_URL,
headers=_mcp_headers,
load_prompts=False,
)

4. App startup and message handler

Wire the MCP plugin and Guard client into the app startup / shutdown hooks. See the full demo for the complete message handler and server setup.

Full runnable example: demo_action_guard_ms365.py

Demo Run

  1. Start the local MCP server in one terminal (python local_mcp_server.py from the demo repo root).
  2. Set env vars, then run:
python examples/demo_action_guard_ms365.py
  1. In another terminal, use the Teams App Test Tool (see the gateway guide for installation):
teamsapptester

Example Output

In the server terminal:

Action Guard + Microsoft 365 demo (server terminal)

In Microsoft 365 Agents Playground:

Action Guard + Microsoft 365 Agents Playground chat

Environment Variables

VariableDescription
VIRTUE_API_KEYVirtueAI API key
ACTION_GUARD_POLICY_IDPolicy set ID (agp_...)
OPENAI_API_KEYOpenAI API key
OPENAI_MODELModel name (default: gpt-4o)
MCP_SERVER_URLMCP server URL (default in demos: http://localhost:3002/mcp)
MCP_API_KEYOptional API key for the MCP server (sent as X-API-Key when set)
PORTaiohttp listen port (default: 3978)
DEBUGSet to 1 / true for verbose logging (optional)