jamjet-guardrails-validators
Guardrails AI validators backed by jamjet-guardrails, a zero-dependency library of deterministic content checks with published precision and recall.
Installed from PyPI, not from the Guardrails Hub, which is closed. Every validator here is an ordinary pip install.
Install
pip install jamjet-guardrails-validators
Requires Python 3.10 to 3.13, the range guardrails-ai itself supports.
Use the composite
from guardrails import Guard
from jamjet_guardrails_validators import JamJetChain
guard = Guard().use(JamJetChain(checks=["pii", "secrets"], on_fail="fix"))
outcome = guard.validate("SLACK_BOT_TOKEN=xoxb-0000000000-2000000000008-EXAMPLEONLYnotarealtoken")
outcome.validated_output
# 'SLACK_BOT_TOKEN=[REDACTED:CREDIT_CARD+SLACK_TOKEN]'
Why one validator and not two
Stacking jamjet/pii and jamjet/secrets as two validators is not the same
thing, and the difference is a leak rather than a preference. Measured on
guardrails-ai 0.11.0, which has two validator services and picks between them
without asking.
The sequential service (GUARDRAILS_RUN_SYNC=true) hands each validator the
previous validator's fix_value. Over the token above, with jamjet/pii first,
the guard reports validation_passed=True and returns:
SLACK_BOT_TOKEN=[REDACTED:SLACK_TOKEN][REDACTED:CREDIT_CARD]-EXAMPLEONLYnotarealtoken
The 13-digit middle segment is Luhn-valid and begins with a 2, so the PII check reads it as a payment card and redacts it first. That placeholder splits the token in half. The secrets check then matches only the 16-character prefix, and the 24-character secret tail survives into a value the guard calls valid.
The default async service runs every validator over the original value and
combines the fixes with a three-way merge. That closes the stump above and opens
something worse: a FailResult with no fix_value, which is what a deny is, is
outvoted by one that carries a fix. Stacking jamjet/injection-structural with
jamjet/pii under on_fail="fix", over a string carrying both an address and a
tag-character injection payload, returns validation_passed=False in one order
and validation_passed=True with the payload intact in the other.
JamJetChain has neither failure because it does not compose fixes at all. It
runs one chain, which hands every check the same original string, merges every
redaction in a single pass over that string, and combines decisions restrictively
so a later check cannot talk an earlier deny back down to a pass. The host gets
one FailResult with one fix_value, and the placeholder names every check that
claimed the region: [REDACTED:CREDIT_CARD+SLACK_TOKEN] rather than one of the
two.
The per-check validators exist for a caller composing a single check. If you want two, use the composite.
Which checks you can name
checks takes any check the installed jamjet-guardrails registers. That list
grows with the core library, so read it from the library rather than from this
page:
from jamjet_guardrails_validators import VALIDATORS
sorted(VALIDATORS)
VALIDATORS is generated from jamjet_guardrails.detectors.AVAILABLE at import,
so a check added to the core is a validator here with no edit. A single check:
from jamjet_guardrails_validators import validator_for
guard = Guard().use(validator_for("pii")(on_fail="fix"))
A check that takes options is configured through options, keyed by check name:
JamJetChain(checks=["secrets"], options={"secrets": {"on_match": "deny"}}, on_fail="exception")
Choosing on_fail
| Chain decision | FailResult carries |
on_fail="fix" |
on_fail="exception" |
|---|---|---|---|
allow |
nothing, it passes | value unchanged | value unchanged |
redact |
fix_value and the spans |
the redacted value | raises |
deny |
the spans, no fix_value |
validation_passed is False and validated_output is None |
raises |
Measured on guardrails-ai 0.11.0: on_fail="fix" over a FailResult with no
fix_value does not raise and does not pass the original through. It sets
validation_passed to False and validated_output to None. That is the right
answer and a quiet one, so put deny-class checks under
on_fail="exception". There is no fix for a deny, and a caller that reads
validated_output without reading validation_passed gets None rather than a
signal.
The chain's own content on a deny is never offered as a fix_value.
GuardrailChain's docstring is explicit that on a deny that string exists for
the audit record and is not safe to send.
What the failure carries
error_message names the validator, the decision and the finding types, for
example:
jamjet/chain[pii,secrets]: redact (pii:CREDIT_CARD, secrets:SLACK_TOKEN)
error_spans carries one ErrorSpan per located finding, with start and end
indexing the value that was validated and reason naming the detector and the
finding type.
Neither ever quotes the content. If a check itself fails, the message carries the exception's type name and the SHA-256 of what was inspected, and not the exception's message: an exception message routinely quotes the value that caused it, and that value is the content.
Direction and origin
Every validator takes direction ("input" or "output", default "output")
and origin (default "model"). They reach the check as its Context, they are
recorded on every verdict, and some checks decide differently per direction.
Validating a user's message rather than a model's reply means
JamJetChain(checks=[...], direction="input", origin="user").
Any metadata a Guard passes is forwarded to the check as Context.metadata.
Licence
Apache-2.0.
The framework this adapter installs makes network calls
jamjet-guardrails says on its own front page: no dependencies, no network
calls, no model downloads. That is true of the core and it stops being true of
your environment the moment you install this adapter, so it is said here rather
than left for you to find.
Measured on guardrails-ai 0.11.0: it posts usage metrics unless
settings.rc.enable_metrics is false, and it builds an OpenTelemetry batch span
exporter AT IMPORT whose flush happens at interpreter exit. On a machine with no
route to the endpoint, that flush is several seconds of OTLP retries at the end
of every process; on a machine with one, it is a report.
Both are yours to turn off, and the ORDER matters, because the exporter is built during import:
import os
os.environ["OTEL_SDK_DISABLED"] = "true" # before importing guardrails
from guardrails import settings
settings.rc.enable_metrics = False
settings.disable_tracing = True
tests/conftest.py in this package does exactly that, for the same reason.
Nothing in this adapter sends anything anywhere. The spans and messages it returns go back to the host in-process.
Metadata
Release files for jamjet-guardrails-validators 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| jamjet_guardrails_validators-0.1.0.tar.gz | 21.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| jamjet_guardrails_validators-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 38.7 kB
Release files / jamjet_guardrails_validators-0.1.0.tar.gz
| Download URL | jamjet_guardrails_validators-0.1.0.tar.gz |
|---|---|
| Size | 21.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7d0ea8733ad152bce1aa065790e5c50c2b5a49ed7c480622f1651433d0af8dfb
|
|
BLAKE2b-256 checksum How to use checksums |
23e1d054f128a3e1fe69f221b002c4d91397babd841f5794a0993385ae848348
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 5, 2026.
Transparency logRelease files / jamjet_guardrails_validators-0.1.0-py3-none-any.whl
| Download URL | jamjet_guardrails_validators-0.1.0-py3-none-any.whl |
|---|---|
| Size | 16.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ea472927514dcae6e81a25b05fae2dd4bd756723f23cad160afdca3f9bd2d2f6
|
|
BLAKE2b-256 checksum How to use checksums |
b3b87abe452ad383486c31dabcd852ab0c499316135ae7c2ffdfd41bb925d86a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Sep 5, 2026.
Transparency log