Policies
A policy is one rule a Guard applies, such as "hide email
addresses" or "block prompt injection". A guard is a list of them.
Its job
A policy decides one thing about one piece of text: let it through, flag it, block it, or rewrite part of it. It says which checks it runs at, and it has a name that shows up in findings.
A policy doesn't decide the final outcome. The guard runs every policy that applies, and the check blocks if any of them blocks.
Mental model
There are three kinds. They differ in where the decision is made.
| Kind | Where it runs | What it does | Examples |
|---|---|---|---|
| Transform | Your machine | Rewrites or inspects text with code: patterns, word lists, size caps. | invisible_text, regex, substrings, allowed_tools, token_limit |
| Sensitive-data policy | Your machine | Finds values that must not leave, and jes replaces them. | pii, secrets, canary |
| Judgment | The decision model | Asks the model a typed question and compares its answer with your threshold. | injection, hazards, toxicity, topics, tool_safety, judge(...) |
A check runs in two steps. First the local policies run, in order, and sensitive values are replaced. Then the judgments see the cleaned text and are sent to the model together.
So a judgment never sees a value that pii or secrets found.
Using it
You don't build policy objects by hand. You call a factory function, and it returns a ready policy:
from jes import Guard, YesNo
from jes.policies import injection, judge, pii, secrets
guard = Guard(
[
pii(["EMAIL_ADDRESS", "PHONE_NUMBER"]), # sensitive data, local
secrets(), # sensitive data, needs jes[secrets]
injection(threshold=0.8), # judgment
judge( # your own judgment
"refund_promise",
YesNo("Does the reply promise a refund?"),
threshold=0.7,
stages=("output",),
),
],
model="jev-latest",
)
To ask the model your own question, use judge(). You write the question
with a question type, and the decision model answers it. To
match text with code, write a Transform class. It needs a name, stages,
a phase, and an apply(text, context) method that returns edits and
findings. jes applies the edits. See
Write your own policy.
Good to know
- Every judgment needs a threshold. jes ships no default. A threshold belongs to one model and one question. See Questions and thresholds.
- Each policy runs only at its stages.
piiruns at every check.injectionruns on input, untrusted text, and tool calls.canaryruns on replies and tool calls. Overridestages=on the factory when you need to. - Names must be unique in a guard. A finding's
policyis the name, so you can tell tworegexpolicies apart. - You can't write your own sensitive-data policy.
pii,secrets, andcanaryare built in, because jes owns how their values are replaced and restored. A customTransformcan still rewrite text. - Some policies need an extra.
secrets()needsjes[secrets].piineeds nothing for emails, phone numbers, and cards, which are patterns. Names (PERSON, on inpii()by default) needjes[pii]and a spaCy model, and raisePolicyErrorwithout them. See Installation. - Recipes are policies too.
jes.recipesholds more judgments and transforms, such aslanguage,json_check, andmalicious_urls. See Built-in policies.
Next
- Built-in policies, with every policy and its stages.
- Write your own policy.
- Reference: Policies, for every factory argument.