Repository navigation
feat(examples): add TypeSafe Jev evaluator example - #279
Merged
Merged
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
SAO-17570. Adds a worked example of integrating a third-party evaluation API
as an Agent Control evaluator, with an agent that is guarded by it.
The evaluator lives in the example, following examples/deepeval, and is
registered through an entry point in the example's own pyproject:
[project.entry-points."agent_control.evaluators"]
"typesafe.jev" = "jev:TypeSafeJevEvaluator"
Installing the example into the environment that runs agent-control-server is
the whole integration. Agent Control needs no change, and the demo clients
never mention TypeSafe: they talk to the server, and the server decides.
TypeSafe Jev answers typed questions about a payload and returns calibrated
values, so the evaluator's job is to turn a vector of answers into the one
boolean a control needs. Each question carries an operator and a threshold,
and decide.combine resolves them with any or all in a single request, which is
what keeps the batching Jev is built for. A question without a threshold is
recorded but does not decide, which is how you collect a score before acting
on it. jev/config.py is the contract in both directions: it validates stored
controls and generates the UI's schema.
The demo is a support assistant for a fictional bank with a synthetic customer
table and one real tool. Controls screen three different things, and each
fails differently:
- the user's message, so a jailbreak is stopped before the model is called
- the tool call the model chose, so a broad query for identifying fields is
stopped before it reaches the data
- the model's reply, so one that reads an SSN back is withheld
Asking for your own SSN exercises two of them at once: the lookup is
legitimate and allowed, and the reply is not and is withheld. A fourth control
steers rather than blocks, routing a request for personal financial advice to
a licensed advisor.
The chat page streams each step with its own timing, because the guardrail
calls take a few hundred milliseconds and the model takes seconds. It also
shows the raw answer, the threshold and the outcome for every control that
ran, so a decision can be read rather than trusted. The demo runs with no
model credentials at all, falling back to a scripted stand-in.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
mikebranc-cisco
force-pushed
the
feat/typesafe-jev-evaluator
branch
from
October 2, 2026 14:29
739f19d to
848518e
Compare
namrataghadi-galileo
approved these changes
Oct 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Requested by the Agent Control team (Namrata) and tracked as SAO-17570.
Summary
Adds a worked example of integrating a third-party evaluation API as an Agent Control evaluator, plus an agent guarded by it.
TypeSafe Jev is a System One model: it does not generate text, it answers typed questions about some state and returns calibrated values. Every question in a request is answered in one pass over the state, so the evaluator's job is to turn a vector of answers into the single boolean a control needs.
decide.combineresolves them withanyorallwithout giving up that batching.The demo is a support assistant for a fictional bank with a synthetic customer table and one real tool. Controls screen three different things, and each fails differently:
Asking for your own SSN exercises two at once: the lookup is legitimate and allowed, the reply is not and is withheld. A fourth control steers rather than blocks, routing a request for personal financial advice to a licensed advisor.
Scope
User-facing/API changes: none. No core change, no new dependency for existing users. The evaluator registers through an entry point in the example's own
pyproject.toml:Internal changes: one row added to
examples/README.md. Nothing else outsideexamples/typesafe_jev/.Out of scope:
CONTRIBUTING.mdpoints new evaluators atevaluators/contrib/template/. This one lives in the example instead, per Namrata's call, so it can be promoted to a contrib package later without blocking the example now. It followsexamples/deepeval, which already ships an evaluator this way.Risk and Rollout
Risk level: low. Additive only — 19 files, all new except one line in the examples index. Nothing imports it, nothing runs it unless you install it. The evaluator is inert until a control names
typesafe.jev.Rollback plan: revert the commit. There is no migration, no config change, and no effect on an existing deployment.
Testing
make check(or explained why not) — ruff and mypy clean on the example;pytestgreen. The example is outside theuvworkspace by design (evaluators/contrib/*is excluded the same way), so its tests run from its own directoryVerified from an empty database and a fresh virtualenv, following the README as a new user:
json, list, regex, sqlpip install -e .in the example+ typesafe.jevsetup_controls.pyagainst an empty DBdemo_agent.pychat_app.pywith no model credentialschat_app.pywith a real modelThe no-credentials path matters most: a fresh clone runs the whole guardrail flow with no API keys for the model, which is what the README promises.
Checklist
Follow-ups, not blocking:
jev/toevaluators/contrib/typesafe/when the team wants it released as a distribution. It was built that way first; moving it back is mostly a directory move plus asemantic_releaseentry.https://typesafe.ai. Worth deep-linking their System One docs once we settle which URLs to cite.🤖 Generated with Claude Code