Skip to main content

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)

  • timeout defaults to GUARDRAIL_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, an error string, and isError: true (an operational failure is not a verdict).
  • The fallback verdict comes from GUARDRAIL_FAIL_MODE: escalate (default — a human is asked) or deny (fail-closed).

Proxy (ellm_guardrail.proxy)

  • Unreachable guardrail → GUARDRAIL_FAIL_MODE verdict with guardrail_reachable: false in the body.
  • Body beyond GUARDRAIL_PROXY_MAX_BODY → 413; missing/invalid Content-Length → 400.

Server

  • Overloaded → 429 (rate limit) or 503 (connection cap); the JSON body carries retry_after_ms. GET /health is never rate limited.
  • An internal error returns 500 with a fail-safe escalate verdict and never wedges the pipeline.

Requirements

  • Python 3.10+
  • Running guardrail service (docker compose up -d)
  • mcp extra for MCP server: pip install ellm-guardrail[mcp]

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ellm_guardrail-0.1.0.tar.gz (17.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ellm_guardrail-0.1.0-py3-none-any.whl (11.3 kB view details)

Uploaded Python 3

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

Hashes for ellm_guardrail-0.1.0.tar.gz
Algorithm Hash digest
SHA256 03067657ac75d710830066b076b944f8ec04d02fcbf5253f84d9ef155f12c42a
MD5 d52668d4ef6894c0fdc7337fd63e9113
BLAKE2b-256 d9026d1fe5ee5334caafc4a3b5bf41c2576822d7b14445bb67df9de9f2e20f4c

See more details on using hashes here.

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

Hashes for ellm_guardrail-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 11bb0bbaee4b1cf26c26c037d8c0ceb02d195d0574f4b70d04f37dd4279fd8d8
MD5 c43d75798e028083b75969a22328f5f1
BLAKE2b-256 ae9106a04e9165cfc1f4eaf615f3a4df716dccf9cf6884e59a15a7e38a54c1ed

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page