hitl-guardrail 🛡️
A human-in-the-loop policy guardrail for LLM / AI-agent actions.
When an AI agent can take consequential actions — send money, email a customer, delete a record, post publicly — you don't want a language model to be the last thing standing between intent and impact. hitl-guardrail wraps any such action in a small, deterministic policy layer that decides:
✅ approve automatically · 🧑⚖️ escalate to a human · ⛔ reject — each with an auditable reason and a 0–100 risk score.
- 🔒 The model advises; policy decides. Rules live in tested code, not prompts, so behaviour is reproducible and can't drift with a model update.
- 🧩 Framework-agnostic. Works with CrewAI, LangGraph, the OpenAI Agents SDK, or plain Python.
- 🪶 Zero dependencies, fully typed, tiny.
Install
pip install hitl-guardrail
Quickstart
from hitl_guardrail import Guardrail, Rule, Decision
guard = Guardrail(
rules=[
Rule("amount_cap", lambda a: a["amount"] <= 2000,
weight=40, message="amount over $2,000 needs a human"),
Rule("receipt", lambda a: a.get("has_receipt", False),
when=lambda a: a["amount"] > 50, # only checked over $50
message="receipt required for amounts over $50"),
Rule("no_fraud", lambda a: not a.get("flagged_fraud", False),
on_fail=Decision.REJECTED, weight=100, message="flagged as fraud"),
],
auto_approve=lambda a: a["amount"] <= 200, # small + compliant → auto
)
result = guard.evaluate({"amount": 2500, "has_receipt": True})
print(result.decision) # Decision.NEEDS_HUMAN_REVIEW
print(result.risk_score) # 40
print(result.reasons) # ['amount over $2,000 needs a human']
Gate an action with the @protect decorator
The function runs only if the action is approved; otherwise your review/reject handlers take over.
review_queue = []
@guard.protect(on_review=lambda action, res: review_queue.append((action, res)))
def pay_expense(action):
return charge_card(action) # only runs when APPROVED
pay_expense({"amount": 5000}) # -> escalated, not charged
Without an on_reject handler a rejected action raises GuardrailError; without an
on_review handler a review returns the GuardrailResult so you can route it yourself.
How the decision is made
- Every applicable rule runs. A rule returns
Truewhen the action complies. - A failing rule adds its
weightto the risk score and records a reason. - Precedence: any
on_fail=REJECTEDfailure → REJECTED. Otherwise any failed review rule, orrisk_score >= risk_threshold(default 60) → NEEDS_HUMAN_REVIEW. Otherwiseauto_approve(action)decides (defaults to approve). - A rule that raises is treated as a failure and fails safe to human review.
Use with an agent framework
# CrewAI / LangGraph / OpenAI Agents SDK — same idea: guard the *tool*, not the prompt.
@guard.protect(on_review=queue_for_human, on_reject=notify_and_drop)
def transfer_funds(action: dict):
banking_api.transfer(**action)
Why this exists
Extracted from a production multi-agent finance system (agentic-finance-crew), where the same principle applies: an LLM can propose, but a deterministic guardrail authorizes.
Development
pip install -e ".[dev]"
pytest -q
python examples/expense_approval.py # decision routing
python examples/approval_workflow.py # human-in-the-loop review queue (approve/reject)
See examples/approval_workflow.py for a complete
human-approval workflow — auto-approve, park-for-review, and reject — built entirely
from the public API.
License
MIT © Furqan Ali
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 hitl_guardrail-0.1.0.tar.gz.
File metadata
- Download URL: hitl_guardrail-0.1.0.tar.gz
- Upload date:
- Size: 10.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2091a1a7e88248bd4db80c8f01d450a7f51ae30c3bfa1f11858c70ca0fe1bcb5
|
|
| MD5 |
a128ad895aff7ad077824aad65b34fe1
|
|
| BLAKE2b-256 |
ac5b734c16f2441ebeaf94d0cde38fff4ebc55787296aea0ada683b42b1704a0
|
File details
Details for the file hitl_guardrail-0.1.0-py3-none-any.whl.
File metadata
- Download URL: hitl_guardrail-0.1.0-py3-none-any.whl
- Upload date:
- Size: 8.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
acf50806b71842a8988d82ecfac019f7836aa3ad135205f869ecc4929dc80ec6
|
|
| MD5 |
7bf9719aa68118e3071c15d9d1cf273e
|
|
| BLAKE2b-256 |
299d2d8f0db365d16f5c1ccc081acf6a59601ed9e9559efe758b6429ade4133f
|