Python client for the Inhibitor policy compliance inference API
Project description
Inhibitor Python SDK
Official Python client for the Inhibitor policy compliance API. Evaluate natural-language content against your policies and get ALLOW, MODIFY, or BLOCK decisions with explanations.
Features
- Simple API — Send only
query,metadata, andadditional_metadata; no extra parameters. - Structured metadata — Use the
{"key": {"value": "val", "description": "des"}}shape for clear, documented context. - Sync and async —
InhibitorClientandAsyncInhibitorClientwith the same interface. - Typed models — Pydantic request/response models for IDE support and validation.
Installation
pip install inhibitor
Requirements: Python 3.9+, httpx, pydantic.
Quick start
from inhibitor import InhibitorClient
client = InhibitorClient(api_key="your-api-key")
response = client.inference.query(
"Can I share this document with external partners?",
metadata={
"consent": {"value": "yes", "description": "User gave consent"},
"data_type": {"value": "PHI", "description": "Contains protected health info"},
},
)
print(response) # Complete Response
print(response.final_decision) # ALLOW | MODIFY | BLOCK
print(response.explanation) # Human-readable explanation
print(response.processing_time_seconds)
client = InhibitorClient(api_key="your-api-key", base_url="https://your-custom-api.com")
API overview
What you send (request)
Only four fields are accepted:
| Field | Type | Required | Description |
|---|---|---|---|
| query | str |
Yes | Natural language content to evaluate against your policies. |
| metadata | dict |
No | Context for compliance. Shape: {"key": {"value": "val", "description": "des"}}. Used by the engine for the decision. |
| additional_metadata | dict |
No | Stores optional user information (e.g., name, email) as key-value pairs, saved along with the inference log for auditing purposes. Example: {"user_name": "John Doe", "email": "john.doe@example.com"} |
| explanation | bool |
No | If True, wait for explanation generation and include in response. Defaults to False. |
Metadata shape — Each key maps to an object with:
- value (str): The actual value (e.g.
"yes","PHI"). - description (str): Optional short description of the field.
Example:
metadata = {
"consent": {"value": "yes", "description": "User consent obtained"},
"classification": {"value": "internal", "description": "Document classification"},
}
What you get (response)
InferenceResponse includes:
| Field | Type | Description |
|---|---|---|
log_id |
str | None | ID of the inference log for fetching details later. |
query |
str | Echo of the query. |
final_decision |
str | ALLOW, MODIFY, or BLOCK. |
final_score |
float | Aggregate score (0–1). |
matched_policies |
list[str] | Policies that were evaluated. |
model_results |
list[RuleResult] | Per-rule decision, confidence, and probabilities. |
explanation |
str | None | Human-readable explanation. |
make_it_compliant |
str | None | Suggested changes to make the query compliant. |
Usage
Sync client
from inhibitor import InhibitorClient, InferenceRequest
client = InhibitorClient(api_key="your-api-key")
# Simple query
response = client.inference.query("Should I send this email to a competitor?")
# With metadata (authoritative context for the engine)
response = client.inference.query(
"Share the report with the client.",
metadata={
"consent": {"value": "yes", "description": "Client consent on file"},
"channel": {"value": "email", "description": "Delivery channel"},
},
)
# With additional_metadata (stored with log only)
response = client.inference.query(
"Upload to cloud storage.",
additional_metadata={"user_name": "John Doe", "email": "john.doe@example.com"},
)
# Using the request model
req = InferenceRequest(
query="Can I export this data?",
metadata={"data_type": {"value": "PII", "description": "Personal data"}},
)
response = client.inference.run(req)
# Fetching full inference log details
if response.log_id:
log_details = client.inference.get_log(response.log_id)
print(log_details)
Async client
from inhibitor import AsyncInhibitorClient
async with AsyncInhibitorClient(api_key="your-api-key") as client:
response = await client.inference.query_async(
"Can I share this document?",
metadata={"consent": {"value": "yes", "description": "Consent given"}},
)
print(response.final_decision)
# Or with run_async
req = InferenceRequest(query="...", metadata={...})
response = await client.inference.run_async(req)
# Fetching full inference log details (async)
if response.log_id:
log_details = await client.inference.get_log_async(response.log_id)
Configuration
| Parameter | Description |
|---|---|
api_key |
Required. Your Inhibitor API key (from the dashboard). |
base_url |
Override API base URL. Default: https://inhibitor-be.envistudios.com. |
timeout |
Request timeout in seconds (default: 60.0). |
headers |
Optional extra HTTP headers. |
The client sends the API key in the X-API-Key header. No other auth is required.
Exceptions
| Exception | When |
|---|---|
| InhibitorAuthError | Invalid or expired API key (401). |
| InhibitorValidationError | Bad request or invalid parameters (400). |
| InhibitorAPIError | Other API errors (4xx/5xx). Has status_code, detail, response_body. |
| ComplianceBlockedError | Raised by :func:check_compliance when the decision is BLOCK. Has response (full :class:InferenceResponse). |
All extend InhibitorError (with message and optional status_code).
from inhibitor import InhibitorClient
from inhibitor.exceptions import InhibitorAuthError, InhibitorAPIError
client = InhibitorClient(api_key="your-api-key")
try:
r = client.inference.query("Some query")
except InhibitorAuthError as e:
print("Auth failed:", e.message)
except InhibitorAPIError as e:
print("API error:", e.status_code, e.detail)
Integration checklist
- Get an API key from your Inhibitor dashboard.
- Install —
pip install inhibitor. - Create client —
InhibitorClient(api_key="..."). - Call —
client.inference.query(query, metadata=..., additional_metadata=...). - Handle — Use
response.final_decision,response.explanation, and catchInhibitorAuthError/InhibitorAPIErroras needed.
Decorator: check compliance before calling your function
Use :func:check_compliance to run the inference API on a chosen argument before your function runs. If the decision is BLOCK, the decorator raises :exc:ComplianceBlockedError (or returns None); otherwise it calls your function.
from inhibitor import InhibitorClient, check_compliance
client = InhibitorClient(api_key="your-api-key")
@check_compliance(client, query_arg="message")
def handle_user_message(message: str, user_id: str):
# Only runs if compliance allows (ALLOW or MODIFY)
return process(message, user_id)
# BLOCK → ComplianceBlockedError (with response.explanation, response.make_it_compliant)
# ALLOW / MODIFY → your function runs
handle_user_message("Can I share this file?", "u-123")
Options: query_arg (param name to check, default "query"), on_block ("raise" or "return_none"), metadata, pass_response (inject _inhibitor_response into kwargs). Use :class:AsyncInhibitorClient with async functions.
from inhibitor import AsyncInhibitorClient, check_compliance
client = AsyncInhibitorClient(api_key="your-api-key")
@check_compliance(client, query_arg="prompt")
async def run_llm(prompt: str):
return await model.generate(prompt)
Catch blocks with :exc:ComplianceBlockedError and use e.response.explanation or e.response.make_it_compliant to show the user why it was blocked or how to fix it.
Package structure
Each module has a single responsibility:
| Module | Purpose |
|---|---|
inhibitor.constants |
Default base URL and API path. |
inhibitor._http |
HTTP response helpers (e.g. error detail extraction). |
inhibitor.models |
Request/response Pydantic models and metadata shape. |
inhibitor.inference |
Inference API (sync/async): query, run, query_async, run_async. |
inhibitor.client |
Sync and async HTTP clients. |
inhibitor.exceptions |
Auth, validation, and API exceptions. |
Import the public API from inhibitor; use submodules only if you need constants or helpers.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file inhibitor-0.1.3.tar.gz.
File metadata
- Download URL: inhibitor-0.1.3.tar.gz
- Upload date:
- Size: 15.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d81c61ef3d8953ac86b907f0228b12c1a4b7f90736a3b0be9fe5effeaca5849b
|
|
| MD5 |
cd959fcec1077106e51ca8e272364431
|
|
| BLAKE2b-256 |
4c8ae7d5a1056636b65d3ea77b4fef42fd2eaad495f9d528348849cc487231cc
|
File details
Details for the file inhibitor-0.1.3-py3-none-any.whl.
File metadata
- Download URL: inhibitor-0.1.3-py3-none-any.whl
- Upload date:
- Size: 13.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ac3130764aea04e02353062ca36821e5fff07a5eb95b601cc4df497a177de9e1
|
|
| MD5 |
cf4fa001b17e02829a12e5700c1cddcf
|
|
| BLAKE2b-256 |
b480b0dbb0e0745237eacfe3a2e17c644e5866d676f13709456078033945a07a
|