Python
The official openai Python SDK talks to the firewall exactly as it talks to
OpenAI. You change base_url and api_key; your model strings, messages, tools,
and response parsing all stay as they are. The gateway holds your provider key
server-side and injects it upstream, so this process never carries one.
Install
pip install openai
Configure
Have the CLI print the snippet, with your organisation UUID already filled in:
vulnetix ai-firewall snippet --lang python --sdk openai --provider openai
Or write it by hand — two settings, and only two:
import os
from openai import OpenAI
client = OpenAI(
base_url=f"https://guardrails.vulnetix.com/openai/{os.environ['VULNETIX_ORG_UUID']}/v1",
api_key=os.environ["VULNETIX_API_KEY"], # your Vulnetix key, not an OpenAI key
)
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
)
print(response.choices[0].message.content)
Swap openai in the path for any other provider slug — groq, mistral,
deepseek, openrouter — and change the model string to whatever that provider
calls its model. The gateway forwards model verbatim.
Streaming
Unchanged. The gateway relays the provider’s SSE stream.
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Hello"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)
Handling a guardrail block
A request your policy refuses never reaches the provider. It comes back as an
OpenAI-shaped 403, which the SDK raises as openai.PermissionDeniedError.
This is the one thing worth adding to your code.
import openai
try:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
)
except openai.PermissionDeniedError as e: # HTTP 403
err = e.response.json().get("error", {})
code = err.get("code") # request_blocked, model_denied, ...
rule = err.get("blocked_by") # the rule that stopped it
if code == "request_blocked":
raise RuntimeError(f"AI firewall blocked this request: rule {rule!r}") from e
raise
Read code to tell your organisation refused this apart from the provider
refused this:
code | Meaning |
|---|---|
request_blocked | A content guardrail matched. blocked_by names the rule; violations lists every rule that matched. |
provider_denied | Your organisation’s policy does not allow this provider. |
model_denied / model_not_allowed | Your organisation’s policy does not allow this model. |
provider_key_missing | No provider key is stored in the vault for this provider. |
pii_redact rule rewrites the
matched spans in your prompt to the literal [REDACTED] and lets the request
proceed. Your code sees no exception and no warning; it simply gets a completion
about redacted text. If a model seems to be answering a question you did not quite
ask, check your redaction rules before you check the model.Tool / function calling
Tools pass through untouched — tools, tool_choice, and the tool_calls you get
back are all the provider’s own. Guardrails inspect the request you send, which
includes the tool messages you send back with results. A tool that returns a
secret and hands it to the next turn is a request the firewall will see, and can
block or redact.
Gotchas
api_keyis your Vulnetix key. Passing an OpenAI key here is the most common401. The provider key belongs in the vault, not in this process.- The SDK reads
OPENAI_BASE_URLandOPENAI_API_KEYfrom the environment if you omit the arguments — sovulnetix ai-firewall install shellalone can route an existing script through the gateway with no code change at all. Passingbase_urlexplicitly is the version that survives a shell that was never re-sourced. - Use
openai.APIStatusErrorif you want one handler for every HTTP failure;PermissionDeniedErroris the 403 subclass of it.