Skip to main content

llm-guardrails-kit

A compliance control layer that sits between your application and any LLM API — redacting PII/PCI, tracking cost, and writing privacy-safe audit logs.

PyPI Python versions License: MIT CI

Built by Gulf Business Machines (GBM) with a focus on regulated GCC sectors — finance, healthcare, and government.


Why this exists

Sending raw customer data — names, card numbers, Emirates IDs, IBANs — to a third-party LLM provider is a data-protection and compliance risk for organizations in regulated sectors. Once data leaves your perimeter you lose control of where it is stored, logged, or used for training.

llm-guardrails-kit gives you a thin, auditable control layer you own:

  • 🛡️ Redaction — detect and mask PII/PCI before the prompt leaves your network, and transparently restore the originals in the response.
  • 💰 Cost governance — meter every request and roll up spend per model.
  • 📝 Auditability — append a structured, privacy-safe JSON-Lines record for every call, proving what was sent without ever recording the raw values.

It is provider-agnostic (works with any LLM via a callable you supply) and the core install has zero third-party dependencies — easy to vet, easy to run in locked-down environments.

Data-protection regimes across the GCC (for example the UAE PDPL, DIFC and ADGM data-protection regulations, Saudi PDPL, and sector rules from regulators such as central banks and health authorities) place obligations on how personal data is processed and shared. This library is a control to help you meet those obligations — see the disclaimer.


Install

# Core — zero third-party dependencies
pip install llm-guardrails-kit

# Optional: LiteLLM integration (one client for 100+ providers)
pip install "llm-guardrails-kit[litellm]"

# Development (pytest, build, ruff)
pip install "llm-guardrails-kit[dev]"

Requires Python 3.11+.


Quickstart

Redact a prompt containing a card number, Emirates ID, and email; send it through a GuardedClient with a dummy completion function; and inspect the audit record — all without an API key.

from llm_guardrails_kit import GuardedClient, AuditLogger, CostTracker

# 1. A stand-in for your real LLM call. It receives the ALREADY-REDACTED prompt.
#    Swap this for OpenAI, Anthropic, LiteLLM, Bedrock — anything.
def my_llm(prompt: str, model: str, **kwargs) -> dict:
    # A real LLM never sees the raw PII — only placeholders like [CARD_1].
    print("LLM received:", prompt)
    return {
        "text": "Thanks! I've noted the details for [EMAIL_1].",
        "input_tokens": 42,
        "output_tokens": 12,
    }

# 2. Wire up the control layer.
audit = AuditLogger(path="audit.jsonl")
client = GuardedClient(my_llm, cost_tracker=CostTracker(), audit_logger=audit)

# 3. Call it with sensitive data.
result = client.complete(
    "Charge card 5555 5555 5555 4444 for Emirates ID 784-1984-1234567-4 "
    "and email the receipt to jane.doe@example.com",
    model="gpt-4o",
)

print("Returned to app:", result.text)
print("Redaction counts:", result.redaction_counts)
print("Cost (USD):", result.cost.total_cost)
audit.close()

Output (abridged):

LLM received: Charge card [CARD_1] for Emirates ID [EMIRATES_ID_1] and email the receipt to [EMAIL_1]
Returned to app: Thanks! I've noted the details for jane.doe@example.com.
Redaction counts: {'credit_card': 1, 'emirates_id': 1, 'email': 1}
Cost (USD): 0.000225

The audit.jsonl record — note there is no raw PII, only counts:

{"input_tokens": 42, "latency_ms": 0.05, "metadata": {}, "model": "gpt-4o", "output_tokens": 12, "redaction_counts": {"credit_card": 1, "email": 1, "emirates_id": 1}, "request_id": "d3b0...", "timestamp": "2026-07-03T09:15:22.104531Z", "total_cost": 0.000225}

Redaction on its own

from llm_guardrails_kit import Redactor

r = Redactor()
res = r.redact("Wire to AE07 0331 2345 6789 0123 456, call +971 50 123 4567")
print(res.redacted_text)  # Wire to [IBAN_1], call [PHONE_1]
print(res.counts)         # {'iban': 1, 'phone': 1}

# Fully reversible for the caller:
print(r.restore("Confirmed [IBAN_1]", res.mapping))  # Confirmed AE07 0331 2345 6789 0123 456

Partial masking (show only the last 4 of a card)

from llm_guardrails_kit import Redactor, RedactionPolicy, MaskStyle

policy = RedactionPolicy(mask_style=MaskStyle.PARTIAL)
print(Redactor(policy).redact("Card 5555 5555 5555 4444").redacted_text)
# Card **** **** **** 4444

Using it with LiteLLM (optional extra)

from llm_guardrails_kit import GuardedClient, AuditLogger

client = GuardedClient.from_litellm(audit_logger=AuditLogger(path="audit.jsonl"))
result = client.complete("Email jane.doe@example.com", model="gpt-4o")

What gets detected

Detector Placeholder Validation
Email [EMAIL_n] RFC-ish pattern
Phone (intl + UAE/GCC) [PHONE_n] E.164 digit-count (7–15)
Credit card [CARD_n] Luhn checksum + length 13–19
Generic PCI [PCI_n] 4×4 card-shaped grouping (defensive)
IBAN [IBAN_n] ISO 13616 mod-97 + per-country length
Emirates ID [EMIRATES_ID_n] 784-YYYY-NNNNNNN-C format + Luhn
IPv4 address [IP_n] Octet range 0–255
Custom [NAME_n] Your regex

Every numeric detector uses real structural validation, not just a regex, so 1234 5678 9012 3456 is not mistaken for a valid card, and a corrupted IBAN is rejected by its checksum.


API overview

Symbol Purpose
Redactor(policy=None) .redact(text) -> RedactionResult; .restore(text, mapping) -> str
RedactionPolicy Toggle detectors, add custom_patterns, pick mask_style
RedactionResult .redacted_text, .mapping, .counts, .total_redactions
MaskStyle PLACEHOLDER (default, reversible), PARTIAL (last 4), FULL
CostTracker(prices=None, default_price=None) .record(model, in, out), .total(), .reset(), .set_price()
CostTracker.from_litellm_prices() Build a tracker from LiteLLM's live price data
DEFAULT_PRICES / load_litellm_prices() Built-in snapshot / live price loader
AuditLogger(path=None, sink=None) .log(...) -> AuditRecord; JSON-Lines, never logs raw PII
GuardedClient(completion_fn, ...) .complete(prompt, model); .from_litellm(...) optional helper
luhn_valid, iban_valid, emirates_id_valid Standalone validators

Cost prices — three ways, from convenient to real

Model prices change, so pick the source that matches how much accuracy you need.

1. Built-in snapshot (default). DEFAULT_PRICES in cost.py is a small, hand-maintained table of per-1M-token prices for common OpenAI/Anthropic models. Convenient, but it drifts — treat it as a fallback, not gospel.

2. Live prices (recommended for production). Load the continuously-updated price table used by LiteLLM (hundreds of models across providers). It uses the installed litellm package if present, otherwise fetches the public price JSON with the standard library — no third-party dependency required:

from llm_guardrails_kit import CostTracker

tracker = CostTracker.from_litellm_prices()   # self-updating, ~2400+ models

The network fetch needs valid CA certificates. On a fresh python.org install on macOS, run the bundled "Install Certificates.command" once, or install the [litellm] extra so prices are read locally with no network call. If loading fails (e.g. offline), it falls back to DEFAULT_PRICES automatically.

3. Your own contracted rates (most accurate). If GBM has committed-use or negotiated pricing, that contract is the real price — feed it in directly:

from llm_guardrails_kit import CostTracker, ModelPrice

tracker = CostTracker(prices=my_rate_table)          # whole table
tracker.set_price("gpt-4o", ModelPrice(2.3, 9.0))    # or one model

Development

pip install -e ".[dev]"
ruff check .
pytest
python -m build

Disclaimer

llm-guardrails-kit is a helper control layer, not a guarantee of regulatory compliance. It reduces the risk of leaking sensitive data to third-party LLMs, but:

  • No automated redactor detects 100% of sensitive data in free-form text.
  • It does not claim any specific certification or regulatory approval.
  • You remain responsible for validating it against your own legal, regulatory, and contractual obligations before relying on it in production.

Test it thoroughly with your own data and threat model. Use of this software is subject to the MIT License and provided "as is", without warranty.


Built by Gulf Business Machines (GBM). Maintainer: Hasan Odeh.

Metadata

Release files for llm-guardrails-kit 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for llm-guardrails-kit 0.2.0
File Size Uploaded Provenance
llm_guardrails_kit-0.2.0.tar.gz 23.0 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for llm-guardrails-kit 0.2.0
File Interpreter ABI Platform
llm_guardrails_kit-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 43.0 kB

Release files / llm_guardrails_kit-0.2.0.tar.gz

Download URL llm_guardrails_kit-0.2.0.tar.gz
Size 23.0 kB
Tags Source
SHA-256 checksum
How to use checksums
b4ce0b7a94b53091c8391d8a9bf7c81dafaec7e6a8ce81395760cf26f23e7db7
BLAKE2b-256 checksum
How to use checksums
1e3a2e733f9736b9b7bfb4f9450512625e00ebc50f739877b45324204065306a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 2, 2026.

Transparency log

Release files / llm_guardrails_kit-0.2.0-py3-none-any.whl

Download URL llm_guardrails_kit-0.2.0-py3-none-any.whl
Size 20.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bb8b5801eb889445d30f41b868ca0615fe63ffdae76add331144574a27a6510a
BLAKE2b-256 checksum
How to use checksums
5de8d851cacf8730b3273a224b34d7ecc9712b577ac38e184f0e904ef2625323
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 2, 2026.

Transparency log

Security for llm-guardrails-kit 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for llm_guardrails_kit-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 2, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page