Skip to content

Commit 59d444f

Browse files
amitbhave10Copilot
andcommitted
Add content safety guardrail hosted-agent sample
Add a new Agent Framework / Responses hosted-agent sample that attaches a Responsible AI content safety guardrail via a definition-level policies block (type: rai_policy, rai_policy_name = full ARM resource ID). Includes a README covering prerequisites, azd and VS Code deploy paths, and runtime verification (benign prompt returns 200, a blocked prompt returns 400 content_filter). Add a learning-path entry to the hosted-agents catalog README. Verified end-to-end with azd deploy: the deployed agent reaches active with the rai_config persisted, and a harmful prompt is blocked at the input stage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 9287cf5 commit 59d444f

10 files changed

Lines changed: 226 additions & 0 deletions

File tree

samples/python/hosted-agents/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ The platform manages conversation history, streaming lifecycle, and background e
121121
9. **[Declarative Workflows](./agent-framework/responses/09-declarative-customer-support/)** — A multi-turn customer-support triage workflow defined entirely in YAML and hosted as an agent, demonstrating declarative workflow authoring with `InvokeAzureAgent` calls to specialist Foundry-hosted agents and conversation-aware routing.
122122
10. **[Downstream Azure services](./agent-framework/responses/09-downstream-azure/)** — Call Azure Blob Storage and Service Bus from the agent using its per-agent Microsoft Entra identity (no connection strings).
123123
11. **[A2A Delegation](./agent-framework/a2a/01-delegation/)** — Two-agent walkthrough: a hosted Responses **caller** delegates to a hosted Responses **executor** that is exposed as an A2A endpoint via Foundry's incoming A2A feature, wired together through a Foundry Toolbox `a2a_preview` tool over a `RemoteA2A` connection.
124+
12. **[Content safety guardrail](./agent-framework/responses/16-content-safety-guardrail/)** — Attach a Responsible AI content safety guardrail to a hosted agent so the platform screens prompts and responses against your safety policy.
124125

125126
### Invocations protocol
126127

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
agent.manifest.yaml
2+
agent.yaml
3+
.env.example
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.venv
2+
__pycache__
3+
*.pyc
4+
*.pyo
5+
*.pyd
6+
.Python
7+
.env
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
FOUNDRY_PROJECT_ENDPOINT="..."
2+
AZURE_AI_MODEL_DEPLOYMENT_NAME="..."
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
FROM python:3.12-slim
2+
3+
WORKDIR /app
4+
5+
COPY . user_agent/
6+
WORKDIR /app/user_agent
7+
8+
RUN if [ -f requirements.txt ]; then \
9+
pip install -r requirements.txt; \
10+
else \
11+
echo "No requirements.txt found"; \
12+
fi
13+
14+
EXPOSE 8088
15+
16+
CMD ["python", "main.py"]
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Content safety guardrail (Responses protocol)
2+
3+
An [Agent Framework](https://github.com/microsoft/agent-framework) agent hosted on Microsoft Foundry using the **Responses protocol**, with a Responsible AI (RAI) **content safety guardrail** attached. The guardrail screens the prompts the agent receives and the responses it returns against an RAI policy, so harmful content is filtered according to your safety configuration.
4+
5+
## How it works
6+
7+
The agent itself is the basic `FoundryChatClient` agent served via `ResponsesHostServer` — see [main.py](main.py). The guardrail is **not** code; it's a definition-level setting. The agent declares a `policies` list with a `rai_policy` entry that points to an RAI policy by its full Azure Resource Manager (ARM) resource ID:
8+
9+
```yaml
10+
policies:
11+
- type: rai_policy
12+
rai_policy_name: /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/<account>/raiPolicies/<policy-name>
13+
```
14+
15+
The platform applies that policy to the agent at runtime. When you omit the `policies` block, the platform applies the default policy, `Microsoft.DefaultV2`. For a conceptual overview, see [Add a content safety guardrail to a hosted agent](https://learn.microsoft.com/en-us/azure/foundry/agents/how-to/add-hosted-agent-guardrails).
16+
17+
## Prerequisites
18+
19+
1. An RAI policy created on your Foundry resource, and its full ARM resource ID. To create one, see [Configure guardrails and controls](https://learn.microsoft.com/en-us/azure/foundry/guardrails/how-to-create-guardrails). The ARM resource ID has this form:
20+
21+
```text
22+
/subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/<account>/raiPolicies/<policy-name>
23+
```
24+
25+
1. **Azure Developer CLI (`azd`)** — [Install azd](https://learn.microsoft.com/en-us/azure/developer/azure-developer-cli/install-azd), then install the AI agent extension and authenticate:
26+
27+
```bash
28+
azd ext install azure.ai.agents
29+
azd auth login
30+
```
31+
32+
## Configure the guardrail
33+
34+
Set `rai_policy_name` to your RAI policy's full ARM resource ID in both [agent.yaml](agent.yaml) and [agent.manifest.yaml](agent.manifest.yaml). Use the full ARM resource ID, not the bare policy name.
35+
36+
## Option 1: Azure Developer CLI (`azd`)
37+
38+
### Initialize the agent project
39+
40+
No cloning required. Create a new folder and initialize from the manifest:
41+
42+
```bash
43+
mkdir my-guardrail-agent && cd my-guardrail-agent
44+
45+
azd ai agent init -m https://github.com/microsoft-foundry/foundry-samples/blob/main/samples/python/hosted-agents/agent-framework/responses/16-content-safety-guardrail/agent.manifest.yaml
46+
```
47+
48+
Follow the prompts to configure your Foundry project and model deployment. If you don't have an existing Foundry project, `azd ai agent init` guides you through creating one.
49+
50+
> [!NOTE]
51+
> After init, confirm that `rai_policy_name` in the generated `agent.yaml` holds your policy's full ARM resource ID.
52+
53+
### Provision Azure resources (if needed)
54+
55+
If you don't already have a Foundry project and model deployment:
56+
57+
```bash
58+
azd provision
59+
```
60+
61+
> [!IMPORTANT]
62+
> If you provisioned a new Foundry project, it doesn't have your RAI policy yet. Before you deploy, [create an RAI policy](https://learn.microsoft.com/en-us/azure/foundry/guardrails/how-to-create-guardrails) on the provisioned account, then set `rai_policy_name` in the generated `agent.yaml` to that policy's full ARM resource ID. Deploying with a placeholder or nonexistent policy ID fails.
63+
64+
### Deploy to Foundry
65+
66+
```bash
67+
azd deploy
68+
```
69+
70+
The platform applies the guardrail when it creates the agent version. For the full deployment guide, see [Deploy a hosted agent](https://learn.microsoft.com/en-us/azure/foundry/agents/how-to/deploy-hosted-agent).
71+
72+
### Invoke the deployed agent
73+
74+
```bash
75+
azd ai agent invoke "Write a short friendly hello message."
76+
```
77+
78+
## Option 2: VS Code (Foundry Toolkit)
79+
80+
1. Install the **[Foundry Toolkit](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.azure-ai-foundry)** extension and sign in to Azure.
81+
1. Open the Command Palette (`Ctrl+Shift+P`) and run **Foundry Toolkit: Create Hosted Agent**, then select this sample from the gallery. The extension scaffolds the project and generates `agent.yaml`.
82+
1. Set `rai_policy_name` in the generated `agent.yaml` to your policy's full ARM resource ID.
83+
1. Run **Foundry Toolkit: Deploy Hosted Agent** and follow the wizard to deploy.
84+
85+
## Verify the guardrail
86+
87+
After deployment, confirm the guardrail filters content by sending a benign prompt and a prompt that violates your policy to the agent's Responses endpoint. The platform screens prompts at the input stage and rejects a violating prompt before the agent runs.
88+
89+
A prompt that passes the policy returns `HTTP 200` with the agent's response. A blocked prompt returns `HTTP 400` with a `content_filter` error:
90+
91+
```json
92+
{
93+
"error": {
94+
"code": "content_filter",
95+
"message": "The request was blocked due to content safety policy violation at input stage.",
96+
"type": "content_safety_error"
97+
}
98+
}
99+
```
100+
101+
If a violating prompt isn't blocked, confirm that the policy referenced by `rai_policy_name` is configured to filter the relevant content category and severity.
102+
103+
## Next steps
104+
105+
- [Add a content safety guardrail to a hosted agent](https://learn.microsoft.com/en-us/azure/foundry/agents/how-to/add-hosted-agent-guardrails) — set a guardrail with `azd`, the Python SDK, or REST
106+
- [Guardrails and controls overview](https://learn.microsoft.com/en-us/azure/foundry/guardrails/guardrails-overview) — what guardrails are and the risks they detect
107+
- [Basic hosted agent](../01-basic/) — the agent this sample builds on
108+
- [Manage hosted agents](https://learn.microsoft.com/en-us/azure/foundry/agents/how-to/manage-hosted-agent) — monitor and manage deployed agents
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: agent-framework-content-safety-guardrail
2+
displayName: "Content safety guardrail (Agent Framework, Responses)"
3+
description: >
4+
An Agent Framework agent hosted by Foundry with a Responsible AI content
5+
safety guardrail. The guardrail screens prompts and responses against an RAI
6+
policy, so harmful content is filtered according to your safety configuration.
7+
metadata:
8+
tags:
9+
- Agent Framework
10+
- AI Agent Hosting
11+
- Azure AI AgentServer
12+
- Responses Protocol
13+
- Content Safety
14+
- Guardrails
15+
template:
16+
name: agent-framework-content-safety-guardrail
17+
kind: hosted
18+
protocols:
19+
- protocol: responses
20+
version: 1.0.0
21+
# Content safety guardrail. Replace rai_policy_name with the full ARM resource
22+
# ID of an RAI policy on your Foundry resource. See README.md for how to create
23+
# one. Omit the policies block to use the default policy (Microsoft.DefaultV2).
24+
policies:
25+
- type: rai_policy
26+
rai_policy_name: /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/<account>/raiPolicies/<policy-name>
27+
environment_variables:
28+
- name: AZURE_AI_MODEL_DEPLOYMENT_NAME
29+
value: "{{AZURE_AI_MODEL_DEPLOYMENT_NAME}}"
30+
resources:
31+
- kind: model
32+
id: gpt-4.1-mini
33+
name: AZURE_AI_MODEL_DEPLOYMENT_NAME
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# yaml-language-server: $schema=https://raw.githubusercontent.com/microsoft/AgentSchema/refs/heads/main/schemas/v1.0/ContainerAgent.yaml
2+
kind: hosted
3+
name: agent-framework-content-safety-guardrail
4+
protocols:
5+
- protocol: responses
6+
version: 1.0.0
7+
# Content safety guardrail. Replace rai_policy_name with the full ARM resource
8+
# ID of an RAI policy on your Foundry resource. See README.md for how to create
9+
# one. Omit the policies block to use the default policy (Microsoft.DefaultV2).
10+
policies:
11+
- type: rai_policy
12+
rai_policy_name: /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.CognitiveServices/accounts/<account>/raiPolicies/<policy-name>
13+
resources:
14+
cpu: '0.25'
15+
memory: '0.5Gi'
16+
environment_variables:
17+
- name: AZURE_AI_MODEL_DEPLOYMENT_NAME
18+
value: ${AZURE_AI_MODEL_DEPLOYMENT_NAME}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright (c) Microsoft. All rights reserved.
2+
3+
import os
4+
5+
from agent_framework import Agent
6+
from agent_framework.foundry import FoundryChatClient
7+
from agent_framework_foundry_hosting import ResponsesHostServer
8+
from azure.identity import DefaultAzureCredential
9+
from dotenv import load_dotenv
10+
11+
# Load environment variables from .env file
12+
load_dotenv()
13+
14+
15+
def main():
16+
client = FoundryChatClient(
17+
project_endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"],
18+
model=os.environ["AZURE_AI_MODEL_DEPLOYMENT_NAME"],
19+
credential=DefaultAzureCredential(),
20+
)
21+
22+
agent = Agent(
23+
client=client,
24+
instructions="You are a friendly assistant. Keep your answers brief.",
25+
# History will be managed by the hosting infrastructure, thus there
26+
# is no need to store history by the service. Learn more at:
27+
# https://developers.openai.com/api/reference/resources/responses/methods/create
28+
default_options={"store": False},
29+
)
30+
31+
server = ResponsesHostServer(agent)
32+
server.run()
33+
34+
35+
if __name__ == "__main__":
36+
main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
agent-framework>=1.2.2
2+
agent-framework-foundry-hosting

0 commit comments

Comments
 (0)