Azure AI Foundry Agents Integration
Swap AgentsClient for MendGuardrailsAzureFoundryClient. Everything else stays the same.
import asyncio
from azure.identity import DefaultAzureCredential
from mendguardrails import MendGuardrailsAzureFoundryClient, GuardrailEnforcementTriggered
async def main():
async with MendGuardrailsAzureFoundryClient(
endpoint="https://your-project.services.ai.azure.com/",
credential=DefaultAzureCredential(),
config="guardrails_config.json",
offline=True,
) as client:
thread = await client.threads.create()
await client.messages.create(
thread_id=thread.id,
role="user",
content="Summarise the Q2 security report.",
)
try:
run = await client.runs.create_and_process(
thread_id=thread.id,
agent_id="your-agent-id",
)
print(run.status) # real ThreadRun — type unchanged
except GuardrailEnforcementTriggered as exc:
print(f"Blocked by: {exc.guardrail_result.info['guardrail_name']}")
asyncio.run(main())
Installation
pip install "mend-guardrails[azure-foundry-agents]"
The extra pulls in azure-ai-agents. The base package does not depend on it so existing installations are unaffected.
How it works
MendGuardrailsAzureFoundryClient inherits directly from azure.ai.agents.aio.AgentsClient. All isinstance checks pass and every SDK method (threads, messages, runs.create, runs.stream, …) is available unchanged. Only runs.create_and_process and create_thread_and_process_run are intercepted to run guardrails.
The guardrail pipeline runs in three stages per request:
| Stage | When it runs | Typical use |
|---|---|---|
pre_flight |
Before the run starts, concurrently with input |
Jailbreak, PII masking |
input |
Before the run starts, concurrently with pre_flight |
Prompt injection detection, harmful-content filter |
output |
After the run completes | Prompt injection in tool output, secret-key leakage, URL filter |
pre_flight and input run concurrently. output runs after the LLM responds. The first failing guardrail raises GuardrailEnforcementTriggered and stops the pipeline immediately.
flowchart TD
A([User request]) --> B & C
B["pre_flight stage\nJailbreak · PII masking"]
C["input stage\nPrompt injection · Harmful content"]
B & C --> D{Any guardrail\nfails?}
D -- Yes --> E([GuardrailEnforcementTriggered])
D -- No --> F["Azure AI Foundry run\ncreate_and_process"]
F --> G["output stage\nPrompt injection · Secret keys · URL filter"]
G --> H{Guardrail\nfails?}
H -- Yes --> E
H -- No --> I([Response returned to caller])
Convenience method — create_thread_and_process_run
If you create the thread and run in one call, guardrails are still applied:
from azure.ai.agents.models import AgentThreadCreationOptions, ThreadMessageOptions, MessageRole
thread_options = AgentThreadCreationOptions(
messages=[
ThreadMessageOptions(
role=MessageRole.USER,
content="What is in the Q2 report?",
)
]
)
async with MendGuardrailsAzureFoundryClient(
endpoint=endpoint,
credential=DefaultAzureCredential(),
config="guardrails_config.json",
offline=True,
) as client:
try:
run = await client.create_thread_and_process_run(
agent_id="your-agent-id",
thread=thread_options,
)
print(run.status)
except GuardrailEnforcementTriggered as exc:
print(f"Blocked: {exc}")
Synchronous client
Use MendGuardrailsAzureFoundrySyncClient when you cannot use async/await:
from azure.identity import DefaultAzureCredential
from mendguardrails import MendGuardrailsAzureFoundrySyncClient, GuardrailEnforcementTriggered
with MendGuardrailsAzureFoundrySyncClient(
endpoint="https://your-project.services.ai.azure.com/",
credential=DefaultAzureCredential(),
config="guardrails_config.json",
offline=True,
) as client:
thread = client.threads.create()
client.messages.create(thread_id=thread.id, role="user", content="Hello")
try:
run = client.runs.create_and_process(thread_id=thread.id, agent_id="your-agent-id")
print(run.status)
except GuardrailEnforcementTriggered as exc:
print(f"Blocked: {exc}")
Configuration options
Both clients accept the same configuration formats as the rest of the SDK:
from pathlib import Path
from mendguardrails import MendGuardrailsAzureFoundryClient, JsonString
# File path (recommended for production)
client = MendGuardrailsAzureFoundryClient(
endpoint=endpoint,
credential=credential,
config=Path("guardrails_config.json"),
offline=True,
)
# Dictionary (for dynamic / programmatic configuration)
config_dict = {
"version": 1,
"pre_flight": {"version": 1, "guardrails": [{"type": "jailbreak"}]},
"input": {"version": 1, "guardrails": [{"type": "prompt_injection_detection"}]},
"output": {"version": 1, "guardrails": [{"type": "prompt_injection_detection"}]},
}
client = MendGuardrailsAzureFoundryClient(
endpoint=endpoint,
credential=credential,
config=config_dict,
offline=True,
)
# JSON string (with JsonString wrapper)
client = MendGuardrailsAzureFoundryClient(
endpoint=endpoint,
credential=credential,
config=JsonString('{"version": 1, ...}'),
offline=True,
)
Online mode
Omit config and offline to pull the policy from the Mend platform at runtime:
client = MendGuardrailsAzureFoundryClient(
endpoint=endpoint,
credential=credential,
mend_key="your-mend-key", # or set MEND_KEY env var
)
Audit events and callbacks
Pass on_guardrail_event to receive a callback for every guardrail result, whether it blocks or passes:
from mendguardrails.utils.events import GuardrailEvent
def handle_event(event: GuardrailEvent) -> None:
print(f"[{event.stage}] {event.guardrail_name}: {event.result}")
client = MendGuardrailsAzureFoundryClient(
endpoint=endpoint,
credential=credential,
config="guardrails_config.json",
offline=True,
on_guardrail_event=handle_event,
)
Multi-agent / A2A demo
The repository includes a full multi-agent demo that places guardrails at every A2A trust boundary:
sequenceDiagram
actor User
participant OA as OrchestratorAgent
participant RA as ResearchAgent
participant KB as Knowledge Base
User->>OA: request (A2A)
Note over OA: pre_flight — Jailbreak · PII masking
OA->>RA: delegated task (A2A)
Note over RA: input — PromptInjection · HarmfulContent
RA->>KB: fetch_document tool
KB-->>RA: document content
Note over RA: output — PromptInjection · SecretKeys
RA-->>OA: research result
Note over OA: output — PromptInjection · URL Filter
OA-->>User: final response
Requirements:
pip install "mend-guardrails[azure-foundry-agents]" "a2a-sdk" uvicorn httpx
Environment variables:
export AZURE_AI_FOUNDRY_PROJECT_ENDPOINT=https://your-project.services.ai.azure.com/
export AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME=gpt-4o
export MEND_KEY=your-mend-key
Run:
python -m examples.azure_foundry_a2a_demo
The demo exercises four security scenarios: a happy path, jailbreak detection, PII masking, and tool-output injection — all enforced automatically at the appropriate trust boundary.
Next steps
- Enforcement — blocking, logging, and custom handlers
- Error Handling — exception types and handling patterns
- OpenAI SDK integration — guardrails for OpenAI API calls