Results
from jes import Result, Finding, Span, ScoreResult, Usage, Message, Stage
All result types are frozen dataclasses. Result lives in jes.result. The
rest live in jes.types. jes re-exports the ones above.
Result
Every check returns one: check_input, check_untrusted, check_tool_call,
check_tool_result, and check_output.
| Field | Type | Meaning |
|---|---|---|
stage | Stage | The stage checked |
decision | "allow" | "block" | "block" if any finding blocks |
complete | bool | Every transform and judgment finished |
original | str | The checked text, as you passed it |
sanitized | str | What the judges saw: the text with redactions applied and placeholders unrestored. Send this to your model. |
findings | tuple[Finding, ...] | Flags, redactions, and blocks only. A passing check adds none. |
scores | Mapping[str, ScoreResult] | One entry per question asked, keyed "<policy>.<question>", including passes |
usage | tuple[Usage, ...] | One entry per backend request |
duration_ms | float | How long the check took |
redactions | Redactions | The conversation's store. A new one if you passed none. |
| Property | Meaning |
|---|---|
allowed | decision == "allow" |
ok | allowed and complete. Branch on this. |
onward | The one string to pass to the next hop (see below) |
onward
| Result | onward |
|---|---|
ok on output | The reply, with this store's placeholders restored |
ok on tool_call | The original arguments. Tool call arguments are never rewritten. |
ok on any other stage | sanitized |
Not ok on tool_call | "Tool call blocked." |
Not ok on tool_result | "Tool result blocked." |
Not ok otherwise | "Blocked: <names>.", where each name is a blocking finding's label, or its policy name for a judgment's violation finding. "Blocked." if there are no findings. |
A refusal never contains the checked text. An output result's onward is for
the user. When you send an earlier reply back to the model, use its
sanitized text or pass the result as history.
The repr of a result shows lengths, not text, so it is safe to log.
refusal and finding_name
from jes.result import refusal, finding_name
refusal(stage: Stage, findings: Iterable[Finding]) -> str
finding_name(finding: Finding) -> str
refusal builds the text that onward returns for a result that isn't
ok. finding_name is how a refusal names one finding: the policy name for
a one-question judgment, and the label otherwise.
Finding
Finding(policy: str, label: str, action: Action, score: float | None = None,
spans: tuple[Span, ...] = (), target: Target = "text",
index: int | None = None)
| Field | Meaning |
|---|---|
policy | Policy name, or "jes" for a finding the engine adds, such as input_too_long |
label | For a judgment, the question id, for example "violation" or "S9". For a transform, what it found, for example "EMAIL_ADDRESS". |
action | "flag", "redact", or "block" |
score | The violation score behind a judgment finding. The full scores are in result.scores. |
spans | Where it was found, as offsets only |
target | Which text the spans index into (see below) |
index | Which source or history entry, when target is "source" or "history" |
Spans index into the original string that target and index name:
target | Text |
|---|---|
"text" | The checked text |
"prompt" | The prompt= context |
"question" | The question= context |
"source" | sources[index] |
"history" | history[index] |
A finding carries no text.
Span
Span(start: int, end: int)
A half-open [start, end) range of Python string indices. It raises
ValueError unless 0 <= start <= end.
ScoreResult
ScoreResult(value: float, model: str, confidence: float | None = None)
One question's violation score: the value its policy compared with the
threshold. model is the backend's model, for example "jev-latest".
confidence is set when the backend reports one, which TypeSafe does for
Choice and Score questions. When a check asks a question more than once,
for example once per chunk or item, scores keeps the highest value.
Usage
Usage(model: str, input_tokens: int | None = None, output_tokens: int | None = None)
The tokens one backend request used, when the backend reports them.
Message and State
Message(role: Role, text: str)
State(stage: Stage, text: str, prompt: str | None = None, question: str | None = None,
sources: tuple[str, ...] = (), history: tuple[Message, ...] = (),
tool: str | None = None)
Message is how you pass raw earlier turns in history. role must be
"user", "assistant", or "tool", or it raises ValueError. A "tool"
message is treated as a tool result.
State is what a backend judges: the sanitized text, the context fields its
policies asked for, and the tool name on the tool stages. A custom backend
receives it as Request.state.
History, the type of history=, is Result | Message. It lives in
jes.guard. See Context rules.
Both reprs show lengths, not text.
Type aliases
| Name | Values |
|---|---|
Stage | "input", "untrusted", "tool_call", "tool_result", "output" |
Action | "flag", "redact", "block" |
Decision | "allow", "block" |
Role | "user", "assistant", "tool" |
Target | "text", "prompt", "question", "source", "history" |
STAGES and ROLES are tuples of every Stage and Role, in the order
above.