Python SDK for the ELLM Guardrail — deterministic policy firewall for AI agent tool calls
Project description
ELLM Guardrail Python SDK
pip install ellm-guardrail
5-Second Start
from ellm_guardrail import GuardrailClient
# Assumes guardrail is running: docker compose up -d
guard = GuardrailClient()
result = guard.check("Bash", "rm -rf /")
print(result.verdict) # "deny"
print(result.reason) # "rm with destructive flags"
if result.is_allowed:
execute_tool()
elif result.is_denied:
print(f"BLOCKED: {result.reason}")
else:
escalate_to_human()
Integration
Any Python agent
from ellm_guardrail import GuardrailClient
guard = GuardrailClient()
def safe_execute(tool_name, target, params=None):
"""Execute a tool call, gated by the guardrail."""
result = guard.check(tool_name, target, params)
if result.is_denied:
raise PermissionError(f"Guardrail blocked {tool_name}: {result.reason}")
if result.is_escalated:
# Requires human approval
if not ask_user(f"Escalated: {result.reason}. Proceed?"):
raise PermissionError("User denied escalated action")
return actual_execute(tool_name, target, params)
Claude Code via MCP
# Start the guardrail
docker compose up -d
# Register as an MCP server
claude mcp add guardrail -- python -m ellm_guardrail.mcp_server
# Now Claude Code can call guardrail_check before every tool execution
Verdict gateway (framework-agnostic)
# Start the gateway (guardrail must be running)
python -m ellm_guardrail.proxy --port 9091
# Point any agent framework at it:
# POST tool calls to http://localhost:9091/check
# → 200 Allow / 403 Deny (JSON body carries verdict, reason, guardrail_reachable)
This is a verdict gateway, not an inline proxy: it tells the agent whether a tool call is allowed — it does not execute or forward the call itself. A true inline proxy is on the roadmap.
Context manager
with GuardrailClient() as guard:
for tool_call in agent_tool_calls:
result = guard.check(tool_call.name, tool_call.target)
if result.is_allowed:
tool_call.execute()
Configuration
| Variable | Default | Description |
|---|---|---|
GUARDRAIL_URL |
http://localhost:9090 |
Guardrail service URL |
GUARDRAIL_TIMEOUT |
2.0 |
Per-request timeout in seconds (client, MCP server, proxy) |
GUARDRAIL_FAIL_MODE |
escalate |
Fallback verdict when the guardrail is unreachable: escalate (ask a human) or deny (fail-closed). MCP server and proxy only |
GUARDRAIL_PROXY_MAX_BODY |
1048576 |
Max request body the proxy accepts (→ 413 beyond) |
guard = GuardrailClient(
base_url="http://guardrail.internal:9090",
timeout=5.0, # seconds
retries=2, # transport-error retries (default 1)
)
Failure modes
The guardrail is a security boundary, so its behavior when it fails is explicit and configurable.
Client (GuardrailClient)
timeoutdefaults toGUARDRAIL_TIMEOUT(2.0s); invalid values fall back to 2.0.- Automatic retries with exponential backoff (
0.2s, 0.4s, …) apply only to transport errors (ConnectionError,Timeout). HTTP responses — including 429 and 5xx — are never retried. - After retries are exhausted the exception propagates; wrap
check()and apply your own policy, or use the MCP server / proxy, which encode one.
MCP server (ellm_guardrail.mcp_server)
- Unreachable guardrail → tool result with
guardrail_reachable: false, anerrorstring, andisError: true(an operational failure is not a verdict). - The fallback verdict comes from
GUARDRAIL_FAIL_MODE:escalate(default — a human is asked) ordeny(fail-closed).
Proxy (ellm_guardrail.proxy)
- Unreachable guardrail →
GUARDRAIL_FAIL_MODEverdict withguardrail_reachable: falsein the body. - Body beyond
GUARDRAIL_PROXY_MAX_BODY→ 413; missing/invalidContent-Length→ 400.
Server
- Overloaded → 429 (rate limit) or 503 (connection cap); the JSON body carries
retry_after_ms.GET /healthis never rate limited. - An internal error returns 500 with a fail-safe
escalateverdict and never wedges the pipeline.
Requirements
- Python 3.10+
- Running guardrail service (
docker compose up -d) mcpextra for MCP server:pip install ellm-guardrail[mcp]
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 ellm_guardrail-0.1.0.tar.gz.
File metadata
- Download URL: ellm_guardrail-0.1.0.tar.gz
- Upload date:
- Size: 17.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03067657ac75d710830066b076b944f8ec04d02fcbf5253f84d9ef155f12c42a
|
|
| MD5 |
d52668d4ef6894c0fdc7337fd63e9113
|
|
| BLAKE2b-256 |
d9026d1fe5ee5334caafc4a3b5bf41c2576822d7b14445bb67df9de9f2e20f4c
|
File details
Details for the file ellm_guardrail-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ellm_guardrail-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.3 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 |
11bb0bbaee4b1cf26c26c037d8c0ceb02d195d0574f4b70d04f37dd4279fd8d8
|
|
| MD5 |
c43d75798e028083b75969a22328f5f1
|
|
| BLAKE2b-256 |
ae9106a04e9165cfc1f4eaf615f3a4df716dccf9cf6884e59a15a7e38a54c1ed
|