Deploy the Guardrail Adapter
This guide walks you through deploying the guardrail adapter and connecting it to a gateway so that MCP tool-call traffic is inspected by a guardrail provider.
Prerequisites
-
A Kubernetes cluster with
kubectlconfigured, or Docker for standalone Envoy usage. -
Go 1.24+ (if building from source) or a pre-built container image (
ghcr.io/agentic-layer/guardrail-adapter). -
A Presidio Analyzer service reachable from the cluster (for the
presidio-apiprovider).
Primary path: managed deployment via tool-gateway-agentgateway
The recommended way to run the adapter is to let the tool-gateway-agentgateway operator manage it automatically.
When you attach a Guard to a ToolGateway, the operator creates a dedicated adapter Deployment, ConfigMap, and Service, and wires the AgentgatewayPolicy extProc.backendRef at it — no manual adapter deployment required.
Step 1: Install the operator
Follow Install the Tool Gateway agentgateway Operator.
Pass the --guardrail-adapter-image flag (already set in the shipped install.yaml):
args:
- --guardrail-adapter-image=ghcr.io/agentic-layer/guardrail-adapter:latest
Step 2: Create a GuardrailProvider and Guard
apiVersion: runtime.agentic-layer.ai/v1alpha1
kind: GuardrailProvider
metadata:
name: presidio
namespace: guardrail-providers
spec:
type: presidio-api
presidio:
baseUrl: http://presidio.guardrail-providers:80
---
apiVersion: runtime.agentic-layer.ai/v1alpha1
kind: Guard
metadata:
name: pii-guard
namespace: guards
spec:
mode:
- pre_call
- post_call
providerRef:
name: presidio
namespace: guardrail-providers
presidio:
language: en
scoreThresholds:
ALL: "0.5"
entityActions:
EMAIL_ADDRESS: MASK
PHONE_NUMBER: MASK
Step 3: Attach the Guard to a ToolGateway
apiVersion: runtime.agentic-layer.ai/v1alpha1
kind: ToolGateway
metadata:
name: tool-gateway
namespace: tool-gateway
spec:
toolGatewayClassName: agentgateway
guardrails:
- name: pii-guard
namespace: guards
kubectl apply -f guardrailprovider.yaml
kubectl apply -f guard.yaml
kubectl apply -f toolggateway.yaml
The operator creates the adapter pod in the Guard’s namespace and updates the gateway configuration automatically. See Create and Use Guardrails in Gateways for a full cross-gateway walkthrough.
Standalone deployment with Kubernetes manifests
Use this path when you want to deploy the adapter independently of the operator — for example when wiring it into a vanilla Envoy proxy or when testing a custom guardrail provider.
Deploy the adapter
The manifests under deploy/local/ in the repository ship two variants:
-
deploy/local/dynamic/— adapter reads guardrail config from Envoy dynamic metadata andx-guardrail-*headers at runtime. -
deploy/local/static/— adapter reads config once from aConfigMap-mounted YAML file at startup.
Apply the static variant (recommended for Kubernetes deployments where one pod serves one guardrail configuration):
kubectl apply -k deploy/local/static/
This creates:
-
A
ConfigMapnamedguardrail-adapter-configin theguardrails-staticnamespace containing aconfig.yamlthat references your Presidio endpoint. -
A
DeploymentandServicefor the adapter (port9001for gRPC ext_proc, port8080for HTTP health).
Edit the ConfigMap before applying to point at your Presidio service:
data:
config.yaml: |
provider: presidio-api
modes:
- pre_call
- post_call
presidio:
endpoint: http://presidio.my-namespace:80
language: en
score_thresholds:
ALL: "0.5"
entity_actions:
EMAIL_ADDRESS: MASK
See Static configuration file for the full schema.
Wire the adapter into a vanilla Envoy proxy
Configure Envoy’s EnvoyExtensionPolicy (when using Envoy Gateway) or an ext_proc HTTP filter (when using raw Envoy) to point at the adapter’s gRPC service.
Envoy Gateway: EnvoyExtensionPolicy
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyExtensionPolicy
metadata:
name: guardrail-extproc
namespace: my-namespace
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: HTTPRoute
name: my-mcp-route
extProc:
- backendRefs:
- group: ""
kind: Service
name: guardrail-adapter
port: 9001
processingMode:
request:
body: FullDuplexStreamed
response:
body: FullDuplexStreamed
messageTimeout: 5s
failOpen: false
Configure a provider
When using the dynamic configuration path, inject x-guardrail-* headers from a Lua filter or route metadata:
| Header | Purpose |
|---|---|
|
Provider name. Currently |
|
Comma-separated inspection modes: |
|
Base URL of the Presidio Analyzer service. |
|
ISO language code for text analysis (e.g. |
|
JSON object mapping entity types to minimum confidence scores. |
|
JSON object mapping entity types to |
For the static configuration path, set GUARDRAIL_CONFIG_FILE to a mounted YAML file instead (see Guardrail Adapter Reference).
Verify
# HTTP health check
curl http://localhost:8080/health
# Expected: OK
# Check adapter logs
kubectl logs -l app=guardrail-adapter -n guardrails-static
# Confirm the gRPC server is up (requires grpcurl)
grpcurl -plaintext localhost:9001 list
Send a test MCP tools/call request through the gateway containing PII.
The adapter logs a line such as masked request body replacements=1 and the response body arrives with sensitive spans replaced (e.g. <EMAIL_ADDRESS>).