Skip to content

Add offline and online guardrails and scored evals - #10

Merged
Doringber merged 1 commit into
mainfrom
cursor/guardrails-and-evals-cce1
Nov 2, 2026
Merged

Doringber merged 1 commit into
mainfrom
cursor/guardrails-and-evals-cce1

Conversation

@Doringber

Copy link
Copy Markdown
Owner

Summary

Guardrails and evals follow the same pytest style as the existing assertions and scorers. One guardrail definition runs offline against a recorded trace and online against a live stream. Evals are named scores with a pass threshold. Both show up in the HTML report.

Guardrails

  • Guardrail is a small base class. @guardrail turns a function into one. Hooks are on_message, on_tool_call, and on_trace.
  • Offline: check_guardrails(result, ...), result.assert_guardrails(...), or the agent_guardrails.check fixture.
  • Online: GuardrailMonitor.handle / on_message / on_tool_call as events arrive. Trace rules run in finish(). fail_fast=True raises GuardrailViolationError. The agent_guardrails.monitor fixture records the outcome, including when the stream aborts.
  • Built-ins: NoProfanityGuardrail (profanity or any disallowed language) and RequiredFinalToolGuardrail, plus must_open_pull_request() for "this flow must open a PR at the end".

Evals

  • Eval plus @eval_case registers a scorer. Pass means score >= threshold.
  • Run with run_evals, result.assert_evals, or the agent_eval fixture. @pytest.mark.agent_eval("name") selects registered evals.
  • Built-ins: RequiredTermsEval and RequiredToolsEval.

Report

Scenario cards gain Guardrails and Evals sections, using the same details/table layout as assertions. The sections are omitted when a scenario has neither.

Tests

pytest -m "not agent_e2e and not agent_write_action" — 310 passed, coverage 88.88% (threshold 85%). Each built-in guardrail and eval has a known-good trace that passes and a known-bad trace that fails, in both offline and online modes for guardrails. python examples/guardrails_and_evals.py runs the three README examples.

Also: scenario reports now keep expected_mcp_servers (the writer already passed it), and the HTML tool-flow pytester fixture lives in the test module so it still overrides agent_client on pytest 9.

Open in Web Open in Cursor 

The same guardrail definition checks recorded traces and live message
or tool-call streams. Evals register with a decorator and run from
pytest, and both results appear in the HTML report.

Co-authored-by: Dor Ingber  <Doringber@users.noreply.github.com>
@Doringber
Doringber merged commit f4cad74 into main Nov 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants