Apply guardrails with the Python client
Use the Deeploy Python client to discover Workspace guardrails, check payloads manually, and enforce guardrails automatically on requests made through OpenAI-compatible clients and supported AI libraries.
Install the guardrails package
Install the guardrails extra when you install the Deeploy Python package. The extra includes the dependencies required for guardrail evaluation and request interception.
pip install "deeploy[guardrails]"
If you already installed deeploy, install or upgrade the extra with the same command.
Configure authentication
You need the following values to connect to a Workspace:
- Your Deeploy host URL.
- Your Workspace ID.
- Either access and secret keys or OAuth client credentials.
- An OpenAI-compatible provider URL, API key, and model when you send requests to a provider.
Store these values in environment variables rather than placing credentials directly in your notebook or application. The following example loads them from a local env_guardrail file. If you only use guard.check() or local regex guardrails, you don't need to configure a provider.
import os
from pathlib import Path
from dotenv import load_dotenv
ENV_FILE = Path.cwd() / "env_guardrail"
if not ENV_FILE.is_file():
raise FileNotFoundError(
f"Create {ENV_FILE} from env_guardrail.example and fill in the values."
)
load_dotenv(ENV_FILE)
DEEPLOY_BASE_URL = os.environ["DEEPLOY_BASE_URL"]
WORKSPACE_ID = os.environ["DEEPLOY_WORKSPACE_ID"]
DEEPLOY_CLIENT_ID = os.environ["DEEPLOY_CLIENT_ID"]
DEEPLOY_CLIENT_SECRET = os.environ["DEEPLOY_CLIENT_SECRET"]
PROVIDER_BASE_URL = os.environ["OPENAI_BASE_URL"]
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
MODEL = os.environ["OPENAI_MODEL"]
For access-key authentication, initialize the client with access_key and secret_key instead of OAuth client credentials. See Authentication for the available Deeploy authentication methods.
Connect to the GuardrailService
Create a Deeploy Client and retrieve its GuardrailService. The service uses your Workspace credentials to list and evaluate the guardrails configured in that Workspace.
The service supports two failure modes for deployment-backed guardrails:
fail_mode="open"(default): if a guardrail deployment cannot be reached, rejects authentication, or another interception error occurs, the provider request or response is forwarded and the failure is logged.fail_mode="closed": the guardrail failure is raised and the unguarded provider request or response is not allowed to continue.
Use fail_mode="closed" when guardrail enforcement is mandatory:
from deeploy.guardrails import GuardrailService
guard = GuardrailService(
host=DEEPLOY_BASE_URL,
workspace_id=WORKSPACE_ID,
client_id=DEEPLOY_CLIENT_ID,
client_secret=DEEPLOY_CLIENT_SECRET,
fail_mode="closed",
)
Use fail_mode="open" when guardrails should be best-effort and provider availability should take priority.
from deeploy.client import Client
client = Client(
host=DEEPLOY_BASE_URL,
workspace_id=WORKSPACE_ID,
oauth_client_id=DEEPLOY_CLIENT_ID,
oauth_client_secret=DEEPLOY_CLIENT_SECRET,
)
guard = client.get_guardrail_service()
You can also initialize GuardrailService directly when you don't need the rest of the client:
from deeploy.guardrails import GuardrailService
guard = GuardrailService(
host=DEEPLOY_BASE_URL,
workspace_id=WORKSPACE_ID,
client_id=DEEPLOY_CLIENT_ID,
client_secret=DEEPLOY_CLIENT_SECRET,
)
Discover Workspace guardrails
Call get_guardrails() to retrieve the guardrails configured in the Workspace. Each returned guardrail includes its name, type, action, direction, and deployment details when applicable.
guardrails = guard.get_guardrails()
print(f"Discovered {len(guardrails)} guardrail(s):")
for guardrail in guardrails:
print(
f"- {guardrail.name} ({guardrail.id}): "
f"type={guardrail.guardrail_type.value}, "
f"action={guardrail.action.value}, "
f"input={guardrail.apply_to_input}, "
f"output={guardrail.apply_to_output}"
)
if not guardrails:
raise RuntimeError("No guardrails were returned for this Workspace.")
You can pass the complete list to the service or select a subset for a specific request.
Evaluate a payload manually
Use guard.check() when you want to evaluate a payload without making a provider request. The method returns the processed payload when the check succeeds. A masking guardrail can return a modified payload, while a blocking guardrail raises GuardrailBlocked.
from deeploy.guardrails import GuardrailBlocked
input_payload = {
"model": MODEL,
"messages": [
{"role": "user", "content": "Give me a sample email address?"}
],
}
try:
checked_payload = guard.check(input_payload, guardrails)
print("Manual check passed:", checked_payload)
except GuardrailBlocked as exc:
print("Manual check blocked the payload:", exc.reason)
Use manual checks for validation, tests, or workflows where you build the provider request yourself.
Enforce guardrails on provider requests
Use guard.install() as a context manager to intercept matching HTTP requests. The guardrails apply for the duration of the context and are removed when the context exits.
The following example protects an OpenAI-compatible chat completion request:
from openai import OpenAI
client = OpenAI(api_key=OPENAI_API_KEY, base_url=PROVIDER_BASE_URL)
with guard.install(guardrails):
response = client.chat.completions.create(
model=MODEL,
messages=input_payload["messages"],
stream=False,
)
print(response.choices[0].message.content)
To intercept a provider endpoint that is not covered by the default patterns, provide url_pattern as a regular expression matching the full request URL.
with guard.install(guardrails, url_pattern=r"/chat/completions"):
response = client.chat.completions.create(
model=MODEL,
messages=input_payload["messages"],
stream=False,
)
url_pattern is a regular expression searched against the full request URL. It adds a custom match to the built-in patterns; it does not replace or restrict them. For example, the following also matches /chat/completions, even though the custom pattern itself targets /my-provider/guarded:
with guard.install(guardrails, url_pattern=r"/my-provider/guarded"):
response = client.post(
"https://provider.example.com/my-provider/guarded",
json=input_payload,
)
Omit url_pattern to use only the built-in provider endpoint patterns. Because it is a regular expression, escape special characters and anchor the expression when a precise URL match is required.
By default, interception covers these endpoint patterns:
/chat/completions/completions/v1/messages/v1/responses
A guardrail can flag, mask, or block content depending on its configured action. Catch GuardrailBlocked around manual checks when you need to handle a blocked request explicitly. For intercepted requests, the service returns the guardrail response or refusal according to the configured action.
Add local regex guardrails
Regex guardrails configured in your Workspace are synchronized to the Python client and executed locally. You can also add local regex guardrails with ManualGuardrail.make_regex() when you need an additional application-specific rule that isn't configured in the Workspace.
The following example creates additional flag, mask, and block rules:
from deeploy.enums import GuardrailAction
from deeploy.guardrails import GuardrailBlocked, ManualGuardrail
regex_flag = ManualGuardrail.make_regex(
regex=r"\b\d{16}\b",
action=GuardrailAction.FLAG,
name="manual-card-flag",
)
regex_mask = ManualGuardrail.make_regex(
regex=r"abc@\w+\.com",
action=GuardrailAction.MASK_CONTENT,
replacement="[EMAIL REDACTED]",
name="manual-email-mask",
)
regex_block = ManualGuardrail.make_regex(
regex=r"\b\d{3}-\d{2}-\d{4}\b",
action=GuardrailAction.BLOCK,
name="manual-ssn-block",
)
print(guard.check("My card is 4111111111111111", regex_flag))
print(guard.check("reach me at [email protected] please", regex_mask))
try:
guard.check("My SSN is 123-45-6789.", regex_block)
except GuardrailBlocked as exc:
print("Blocked:", exc.reason)
You can use the same guardrail with a provider client:
with guard.install([regex_mask]):
response = client.chat.completions.create(
model=MODEL,
messages=[
{
"role": "user",
"content": "My support email is [email protected]. Please say it back verbatim.",
}
],
stream=False,
)
print(response.choices[0].message.content)
Use a Deployment as a guardrail
A Deployment-backed guardrail sends the request to a dedicated guardrail Deployment. The Deployment must return a JSON object containing a Boolean guardrail_triggered property. For masking behavior, it can also return the transformed request body. See Using a deployment as a guardrail for the response schema and masking examples.
Use ManualGuardrail.make_deployment_guardrail() when you want to configure one Deployment-backed guardrail directly instead of discovering it from the Workspace.
from deeploy.enums import GuardrailAction, GuardrailEndpointType
from deeploy.guardrails import ManualGuardrail
manual_guardrail = ManualGuardrail.make_deployment_guardrail(
deployment_id="r715707e-5d1f-4caa-8180-0958c240c1f3",
deployment_token=os.environ.get("DEEPLOY_DEPLOYMENT_TOKEN", ""),
endpoint_type=GuardrailEndpointType.PREDICT,
action=GuardrailAction.BLOCK,
apply_to_input=True,
apply_to_output=False,
name="deployment-guardrail",
)
with guard.install([manual_guardrail]):
response = client.chat.completions.create(
model=MODEL,
messages=input_payload["messages"],
stream=False,
)
An empty deployment_token makes the service use the Workspace authentication configured on GuardrailService. Provide a deployment token when the application should authenticate specifically to that Deployment.
The Deployment response must include a Boolean guardrail_triggered value. If it is missing or is not a Boolean, the SDK logs a warning and treats the deployment guardrail as not triggered. It does not raise a schema-validation error for this response shape.
Integrate with AI libraries
Install the library you want to use, then wrap the model call with guard.install().
LangChain
The following example uses ChatOpenAI with an OpenAI-compatible provider:
from langchain_openai import ChatOpenAI
langchain_model = ChatOpenAI(
model=MODEL,
api_key=OPENAI_API_KEY,
base_url=PROVIDER_BASE_URL,
)
with guard.install(guardrails):
response = langchain_model.invoke(input_text)
print(response.content)
LangGraph
Create the graph normally and install guardrails around the graph invocation:
with guard.install(guardrails):
graph_result = graph.invoke(
{"messages": [{"role": "user", "content": input_text}]}
)
print(graph_result["messages"][-1].content)
smolagents
Pass a list of messages to OpenAIModel.generate() and scope the request with url_pattern:
from smolagents import OpenAIModel
smol_model = OpenAIModel(
model_id=MODEL,
api_base=PROVIDER_BASE_URL,
api_key=OPENAI_API_KEY,
)
with guard.install(guardrails):
response = smol_model.generate(
[{"role": "user", "content": input_text}]
)
print(response.content)
Nest temporary guardrail scopes
Guardrail installations can be nested. A temporary inner scope replaces the active rules while it runs, then restores the outer rules when it exits. This lets you define process-wide rules and apply additional rules for a specific operation.
from deeploy.enums import GuardrailAction
from deeploy.guardrails import ManualGuardrail
rule_a = ManualGuardrail.make_regex(
regex=r"alpha",
action=GuardrailAction.BLOCK,
name="scope-a-alpha",
)
rule_b = ManualGuardrail.make_regex(
regex=r"beta",
action=GuardrailAction.BLOCK,
name="scope-b-beta",
)
try:
guard.install([rule_a])
with guard.install([rule_b]):
# Requests in this scope use rule_b.
pass
# Requests here use rule_a again.
finally:
guard.uninstall()
Call uninstall() when you install a process-wide guardrail scope without a with statement. Prefer the context-manager form for temporary scopes so cleanup happens automatically.