Message and History
History is the earlier conversation you pass to a check, oldest first. Each
entry is a Result from an earlier check, or a Message you
build yourself.
from jes import Message
from jes.guard import History # Result | Message
Its job
Some attacks only show across turns. A request can look harmless on its own and dangerous after the three messages before it. History gives the judgments that look at context the conversation so far.
History is context, not the text under check. It never changes the check's
onward, and it doesn't make a turn's own findings go away.
Mental model
History is what the judge reads before it reads the new turn:
Before any of it reaches the model, jes cleans it the same way it cleans the checked text. Emails and secrets in earlier turns are replaced too.
- A
Resultfrom the same conversation (sameRedactionsstore) is already clean, so jes reuses itssanitizedtext. - A
Message, or aResultfrom another store, is cleaned again from its text. - A
Messagehas arole:"user","assistant", or"tool". AResultgets its role from its stage. An input result is the user, a tool result is the tool, and anything else is the assistant.
Using it
Most apps keep the Results they already have:
history = []
incoming = guard.check_input(user_text, redactions=store, history=history)
reply = call_model(incoming.onward)
outgoing = guard.check_output(
reply, prompt=incoming, redactions=store, history=history
)
history += [incoming, outgoing]
When the earlier turns come from somewhere else, such as a database or a
chat framework, build Messages:
from jes import Message
history = [
Message("user", "Which pills are in the cabinet?"),
Message("assistant", "Ibuprofen and acetaminophen."),
]
guard.check_input("How many would be too many?", history=history)
Good to know
- Only judgments that ask for context see it.
hazards,indirect_injection,tool_safety, and ajudge(..., context="optional")read the history.injection,toxicity, andtopicsjudge the new text alone. - The newest turns win. When the history doesn't fit in one request, jes
drops the oldest turns and adds a
history_truncatedflag. The check still runs. A prompt that doesn't fit is dropped with acontext_droppedflag. - A blocked turn poisons the rest. A
Resultin history from the same store that was notokblocks the check withcontext_not_ok. Add a turn to history only when it went through. - Pass
sanitized, notonward, to your own model. An earlier reply'sonwardhas placeholders restored, so it carries the real values. - History has a cap. One check takes up to 1,024 context entries, and their
total size is bounded by
Limitsmax_context_bytes.
Next
- Multi-turn conversations, the full turn loop.
Redactions, the store that keeps a conversation's placeholders consistent.- Reference: context rules.