Deploy the guardrails service¶
Composes the E1 baseline + the E2 call-an-llm module + one guardrail resource per cloud.
Verified 2026-08-08
azurerm_cognitive_account(kind = ContentSafety) — registry.terraform.io/…/azurerm/latest/docs/resources/cognitive_account- Model Armor
google-cloud-model-armor— pypi.org/project/google-cloud-model-armor aws_bedrock_guardrail— registry.terraform.io/…/aws/latest/docs/resources/bedrock_guardrail
Layout¶
examples/guardrails/
service/ # E2 chat + native-guardrail sandwich
guardrail.py # Protocol + 3 per-cloud impls + Verdict + fail-closed helper
main.py # FastAPI POST /chat -> {blocked, side, reason} | {reply}
Dockerfile
requirements.txt
chart/ # Helm chart
Chart.yaml
values.yaml
templates/{deployment,service,serviceaccount}.yaml
terraform/
azure/ (module "baseline" + "call_an_llm" + azurerm_cognitive_account kind=ContentSafety)
gcp/ (module "baseline" + "call_an_llm" + enable modelarmor.googleapis.com + writer IAM)
aws/ (module "baseline" + "call_an_llm" + aws_bedrock_guardrail resource)
Terraform¶
module "baseline" {
source = "../../../foundations/azure"
name = var.name
region = var.region
compute = var.compute
}
module "call_an_llm" {
source = "../../../call-an-llm/terraform/azure"
name = var.name
region = var.region
compute = var.compute
azure_openai_base_url = var.azure_openai_base_url
azure_openai_deployment = var.azure_openai_deployment
foundry_claude_deployment = var.foundry_claude_deployment
}
resource "azurerm_cognitive_account" "content_safety" {
name = "${var.name}-cs"
location = var.region
resource_group_name = module.baseline.resource_group_name
kind = "ContentSafety"
sku_name = "S0"
}
Feed azurerm_cognitive_account.content_safety.endpoint + primary key into the chart via env.CONTENT_SAFETY_ENDPOINT + a secret env for the key.
module "baseline" {
source = "../../../foundations/gcp"
project_id = var.project_id
name = var.name
region = var.region
compute = var.compute
}
module "call_an_llm" {
source = "../../../call-an-llm/terraform/gcp"
project_id = var.project_id
name = var.name
region = var.region
compute = var.compute
}
# Enable Model Armor on the project.
resource "google_project_service" "modelarmor" {
project = var.project_id
service = "modelarmor.googleapis.com"
disable_on_destroy = false
}
# Workload SA gets modelarmor.user so the pod can call
# sanitize_user_prompt / sanitize_model_response.
resource "google_service_account" "guardrail" {
account_id = "${var.name}-guard"
display_name = "Chiron guardrail caller"
}
resource "google_project_iam_member" "modelarmor_user" {
project = var.project_id
role = "roles/modelarmor.user"
member = "serviceAccount:${google_service_account.guardrail.email}"
}
Templates (projects/{project}/locations/{location}/templates/{id}) are created out-of-band; the wrapper reads MODEL_ARMOR_TEMPLATE_INPUT and MODEL_ARMOR_TEMPLATE_OUTPUT env vars.
module "baseline" {
source = "../../../foundations/aws"
name = var.name
region = var.region
compute = var.compute
}
module "call_an_llm" {
source = "../../../call-an-llm/terraform/aws"
name = var.name
region = var.region
compute = var.compute
eks_oidc_provider_arn = var.eks_oidc_provider_arn
}
resource "aws_bedrock_guardrail" "chiron" {
name = var.name
description = "Chiron default guardrail"
blocked_input_messaging = "Sorry, that request violates policy."
blocked_outputs_messaging = "Sorry, that response violates policy."
content_policy_config {
filters_config {
type = "HATE"
input_strength = "HIGH"
output_strength = "HIGH"
}
# ... same shape for INSULTS / SEXUAL / VIOLENCE / MISCONDUCT / PROMPT_ATTACK
}
sensitive_information_policy_config {
pii_entities_config {
type = "EMAIL"
action = "ANONYMIZE"
}
pii_entities_config {
type = "PHONE"
action = "ANONYMIZE"
}
pii_entities_config {
type = "US_SOCIAL_SECURITY_NUMBER"
action = "BLOCK"
}
}
contextual_grounding_policy_config {
filters_config {
type = "GROUNDING"
threshold = 0.75
}
filters_config {
type = "RELEVANCE"
threshold = 0.5
}
}
}
# Extend the workload role to allow apply_guardrail.
data "aws_iam_policy_document" "apply_guardrail" {
statement {
effect = "Allow"
actions = ["bedrock:ApplyGuardrail"]
resources = [aws_bedrock_guardrail.chiron.guardrail_arn]
}
}
resource "aws_iam_policy" "apply_guardrail" {
name = "${var.name}-apply-guardrail"
policy = data.aws_iam_policy_document.apply_guardrail.json
}
Verify (validate-only)¶
for p in azure gcp aws; do
( cd examples/guardrails/terraform/$p && terraform init -backend=false && terraform validate )
done
helm lint examples/guardrails/chart
helm template guardrails examples/guardrails/chart > /dev/null
python -m compileall examples/guardrails/service
Live guardrail evaluations need real credentials + the resource actually deployed — Phase 3 handles billed apply.