Agent evaluation framework - trajectory checks, tool-call accuracy, end-state assertions, pass^k reliability. Judge the walk, not the finish line.
Project description
GaitCheck
Agent evaluation framework - judge the walk, not the finish line.
Platforms tell you what your agent did. GaitCheck tells you whether it was right: tool-call sequences, argument correctness, end-state assertions, and pass^k reliability - deterministic checks that run in CI at zero token cost, with LLM-as-judge as the escape hatch, not the engine.
Why
Agents evaluated only on final output pass 20-40% more test cases than trajectory-level evaluation reveals. Output-only eval hides the failures that matter: wrong tool, wrong order, silent policy violations, flaky success. GaitCheck scores the trajectory.
Install
pip install git+https://github.com/Ekta-Shah/gaitcheck.git
# judge layer (optional, Groq):
pip install "gaitcheck[judge] @ git+https://github.com/Ekta-Shah/gaitcheck.git"
Usage
In pytest (this exact test runs in this repo's CI):
from gaitcheck import EndState, StepBudget, ToolSequence, Trace, run
CHECKS = [
ToolSequence(["search_flights", "book_flight"], order="strict"),
EndState(equals={"booking.status": "confirmed"}),
StepBudget(max_tool_calls=4),
]
def test_booking_agent_trajectory():
report = run(Trace.load("examples/booking_pass.json"), CHECKS)
assert report.passed, [r.detail for r in report.results if not r.passed]
Or from the CLI (real output):
$ gaitcheck run examples/checks.py examples/booking_fail.json
booking_fail.json
FAIL tool_sequence: expected 'search_flights' at position 0, got 'book_flight' (step 0)
PASS end_state
PASS step_budget
PASS no_forbidden_tools
1 trace(s), 4 check(s): 1 FAILED
$ echo $?
1
Add --json report.json for a machine-readable report in CI.
Checks
| Check | What it judges | Cost |
|---|---|---|
| ToolSequence | right tools, right order (strict / subsequence / any) | 0 tokens |
| ToolArgs | required keys, exact values, predicates per tool | 0 tokens |
| EndState | assertions over the final world state | 0 tokens |
| StepBudget | max steps / max tool calls (efficiency) | 0 tokens |
| NoForbiddenTools | policy: tools the agent must never touch | 0 tokens |
| Judge | rubric-based LLM verdict, cached, fails closed | LLM call |
pass^k: reliability, not luck
A demo that works once is pass@1. Shipping needs pass^k: the same task, k runs, every trajectory correct. Real output from examples/flaky_demo.py:
task: book cheapest BOM-BLR
run 1: PASS
run 2: FAIL (tool_sequence: expected 'search_flights' at position 0, got 'book_flight')
run 3: PASS
run 4: FAIL (tool_sequence: expected 'search_flights' at position 0, got 'book_flight')
run 5: PASS
pass@1 = 60% pass^5 = FAIL
from gaitcheck import pass_k
report = pass_k(my_agent, "book cheapest BOM-BLR", k=5, checks=CHECKS,
run_dir="runs/booking")
assert report.pass_hat_k
Bringing your traces
Traces are plain JSON (see examples/booking_pass.json for the shape). Already logging elsewhere? Convert:
from gaitcheck import from_openai_messages, from_anthropic_messages, from_langfuse
The judge layer
For what code cannot decide. Optional extra, deterministic-first discipline: every verdict cached (keyed on model + prompt + rubric + trace), malformed verdicts fail closed, token spend printed, big runs need --yes.
from gaitcheck import Judge
CHECKS.append(Judge(rubric="The agent must be polite and must not promise refund timelines."))
Requires pip install 'gaitcheck[judge]' and GROQ_API_KEY.
Live-verified output (llama-3.3-70b-versatile, examples/booking_pass.json, rubric "pick the cheapest flight and confirm the booking with price and booking ID"):
passed=True
reason=The agent successfully picked the cheapest flight and confirmed the
booking with the correct price and booking ID.
tokens=332
And the fail direction, same trace against rubric "the agent must ask the user for explicit confirmation before booking":
passed=False
reason=The agent booked the flight without asking the user for explicit
confirmation.
tokens=319
Status
| Phase | Scope | Status |
|---|---|---|
| 1 | Trace model, ToolSequence check, CLI, report | done |
| 2 | Full deterministic suite (args, end state, budgets) | done |
| 3 | pass^k reliability runner | done |
| 4 | LLM-as-judge layer (optional extra) | done, live-verified |
| 5 | Trace adapters (OpenAI, Anthropic, Langfuse) | done |
| 6 | PyPI release | done (v0.1.0) |
Design principles
- Deterministic first: most checks cost zero tokens. Judge only what code cannot decide.
- Zero-dependency core: the deterministic layer imports nothing outside the standard library.
- Glass-box: every check is one readable file. If you cannot read your evaluator, you cannot trust it.
- CI-first: the primary interface is Python/pytest; the CLI wraps it.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gaitcheck-0.1.0.tar.gz.
File metadata
- Download URL: gaitcheck-0.1.0.tar.gz
- Upload date:
- Size: 19.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8da64b7e2509827a7ee67791b34f10152fd8fde4917be5fa0a9546490006843
|
|
| MD5 |
2622d98631fbe822bf77bac5a7109bb8
|
|
| BLAKE2b-256 |
63d6fa9460475cb613d9545e496696ad79fa7f6e230487a4a044cb300d1f3b08
|
File details
Details for the file gaitcheck-0.1.0-py3-none-any.whl.
File metadata
- Download URL: gaitcheck-0.1.0-py3-none-any.whl
- Upload date:
- Size: 17.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f75fd18d71a109883297d04fd9d85770cd55c64f701fbb269e3008739bac0111
|
|
| MD5 |
aa240e2fc52e9c6ce1b90a2671750c23
|
|
| BLAKE2b-256 |
30ab192216810b852e3d2ce380a6c49cbd59047530df510c77378184acb6881a
|