A local-first gate for LLM apps: define a check — keyword, regex, URL, length, JSON-schema — attach it to a stage (input, tool call, tool output, output). Deterministic, microsecond, $0, and every decision is audit-grade evidence.
Project description
cendor-guardrails
A local-first gate for LLM apps: define a check — keyword, regex, URL, length, JSON-schema —
attach it to a stage (input, tool_call, tool_output, output), and block, redact, or flag
before the model or a tool ever runs. No server, no account, no model call.
Deterministic checks in microseconds for $0 — and every decision lands in a tamper-evident audit chain.
·
pip install cendor-guardrails
from cendor.core import instrument
from cendor.guardrails import install, rules
client = instrument(OpenAI())
install([ # one interceptor gates every call
rules.keyword_deny(["ignore previous instructions"], action="block"),
rules.regex_rule(r"\bsk-[A-Za-z0-9]{20,}\b", action="redact", stage="input"),
rules.url_allowlist(["docs.cendor.ai"], stage="input"),
])
client.chat.completions.create(model="gpt-4o", messages=msgs)
# blocked prompt -> raises GuardrailTripped BEFORE the request is sent ($0 spent)
# a leaked key -> the provider receives "[redacted]" instead
Highlights
- Four intervention points — gate the user turn (
input), the model's request to call a tool (tool_call), the tool's result (tool_output), and the model's final answer (output). Matches Azure Foundry's intervention points and OpenAI's four decorator types. - Deterministic built-ins, no heavy deps —
keyword_deny,regex_rule,url_allowlist/url_deny,length_bounds(char + exact token bounds viacendor.core.tokens),json_schema, andcustom. Regex/arithmetic only — offline, deterministic, $0. - Evidence, not just enforcement — every trip or flag emits a
GuardrailDecisionon thecendor.corebus, socendor-acttracechains it as a tamper-evidentguardrail_decisionentry with no import between the two. "We blocked it" is in the hash chain, not a log line. - Three ways to use it — pure
apply()/evaluate(); framework-independentinstall()on the core seam (orscoped()for per-request gating on a concurrent server); andAgent(guardrails=[…])incendor-sdk(all four in-loop stages + per-run override). - Bring-your-own model judge —
rules.llm_judgefor open-ended risk, with per-guardrailtimeout+on_error(fail-closed by default) andcendor.guardrails.judgehelpers (verdict prompt + strict-JSON parsing). The judge rides an instrumented client, so its own spend is budgeted + audited. - Detection tiers you opt into — a local classifier contract (
rules.classifier,rules.prompt_guardbehind the[promptguard]extra),rules.language, and hosted rails (rules.bedrock_guardrail/azure_content_safety/model_armor— duck-typed clients, metered by the vendor). Every hosted verdict still emits a localguardrail_decision: cloud check, local evidence. No jailbreak/PII-catch-rate claim ships without a reproduced, published benchmark. - Config as data + grounding —
load_policy("guardrails.yaml")builds deterministic rules from a versioned file and stamps itspolicy_hash/policy_versiononto every decision (the audit chain proves which policy was live);rules.groundedness/rules.denied_topicsgate on bring-your-own-embedding cosine similarity (RAG hallucination / off-topic), no bundled model. - Red-team it —
run_redteam(guardrails, load_corpus("attacks.jsonl"))reports the trip rate + false-positive rate against a labeled corpus you supply (cendor vends no attack data). A measurement, not a claim: publish a rate only with the corpus named.
from cendor.guardrails import apply, guardrail, Verdict, GuardrailTripped
@guardrail(stage="output")
def must_be_json(payload, ctx):
if not payload.strip().startswith("{"):
return Verdict("block", reason="expected a JSON object")
try:
apply([must_be_json], "output", model_text) # raises GuardrailTripped on a block
except GuardrailTripped as e:
print(e.decisions) # the recorded decisions, block last
How it plugs into your agent
guardrails is the Gate in the pipeline — contextkit → squeeze → tokenguard → guardrails → cassette → acttrace. It imports only cendor-core: checks ride the same instrument() seam
and event bus every other library uses, so the same guardrail works under cendor-sdk, a bare
instrumented client, or beneath another framework — in Python and TypeScript alike.
Honest limits: the built-ins are deterministic, so they do not stop a novel adversarial
attack — a jailbreak they were never told about will pass. Pair them with a bring-your-own model
judge (rules.llm_judge, an adapter contract — you supply the call, and the extra latency/cost is
real) and treat the deterministic rules as the fast, free floor, not a ceiling. PII/secret
detection lives in cendor-acttrace (guard(Policy…)), not here.
Part of the Cendor stack — github.com/cendorhq/cendor-libs. Powered by PowerAI Labs.
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 cendor_guardrails-1.2.0.tar.gz.
File metadata
- Download URL: cendor_guardrails-1.2.0.tar.gz
- Upload date:
- Size: 51.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
79dea09de9c0d89791db776b0a67a1070bc4786c57bcf4b685a1add212b2f3f3
|
|
| MD5 |
95bd36ab0f0050f98187ae4a42c77e99
|
|
| BLAKE2b-256 |
35eba86758b8fdecc4e3ede6702f59f0aca311ccd8a373307284b492373d4c27
|
Provenance
The following attestation bundles were made for cendor_guardrails-1.2.0.tar.gz:
Publisher:
release.yml on cendorhq/cendor-libs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cendor_guardrails-1.2.0.tar.gz -
Subject digest:
79dea09de9c0d89791db776b0a67a1070bc4786c57bcf4b685a1add212b2f3f3 - Sigstore transparency entry: 2128310437
- Sigstore integration time:
-
Permalink:
cendorhq/cendor-libs@21c728d034a317fcda6c73e23968e38015f00cc5 -
Branch / Tag:
refs/tags/guardrails-v1.2.0 - Owner: https://github.com/cendorhq
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@21c728d034a317fcda6c73e23968e38015f00cc5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cendor_guardrails-1.2.0-py3-none-any.whl.
File metadata
- Download URL: cendor_guardrails-1.2.0-py3-none-any.whl
- Upload date:
- Size: 42.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e2e04f5f10aacbf6dcd111edee462f9207bc17119205ac3f75b161b60dfb0f81
|
|
| MD5 |
5ec7ad540bbce71a965bfca653ac96df
|
|
| BLAKE2b-256 |
92e9b70f6ddb0d1496bf14e25ad8995d4389b4deb1b09142e770b530fa8bdda5
|
Provenance
The following attestation bundles were made for cendor_guardrails-1.2.0-py3-none-any.whl:
Publisher:
release.yml on cendorhq/cendor-libs
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cendor_guardrails-1.2.0-py3-none-any.whl -
Subject digest:
e2e04f5f10aacbf6dcd111edee462f9207bc17119205ac3f75b161b60dfb0f81 - Sigstore transparency entry: 2128310492
- Sigstore integration time:
-
Permalink:
cendorhq/cendor-libs@21c728d034a317fcda6c73e23968e38015f00cc5 -
Branch / Tag:
refs/tags/guardrails-v1.2.0 - Owner: https://github.com/cendorhq
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@21c728d034a317fcda6c73e23968e38015f00cc5 -
Trigger Event:
push
-
Statement type: