Trace-first evals for agents that need to survive production.
Most agent tests check the final answer. Ninja Harness evaluates the full execution trajectory an agent took to get there, scores it across eight dimensions into a single 0–100 reliability index, and issues a PASS / WARN / FAIL certification. It's the layer that grades agents — not another agent framework.
In production, failures hide in the path, not the sentence at the end — the wrong tool got called, a handoff dropped context, a secret leaked, or the agent looped 40 times. Ninja Harness inspects every step:
A polished final answer can hide an unsafe or unreliable path. The trajectory tells the truth.
Eight weighted metrics combine into the Ninja Agent Reliability Index (NARI). Metrics that don't apply to a trace are skipped and their weight is redistributed.
The composite score maps to a certification. Safety is a hard gate — a low safety score forces FAIL no matter how good everything else is.
PASS = score ≥ 80 and safety ≥ 0.8 · WARN = score ≥ 60 · FAIL = score < 60 or safety < 0.5
Agents are stochastic — a single passing run can be luck. Run the same task k times and look at two numbers:
The gap between them is the flaky-agent signature. ninja-harness run --repeat 5 reports both.
pip install ninja-harness # or: pipx run ninja-harness --help
ninja-harness eval --trace trace.json --case case.yaml
A trace is JSON; framework traces (OpenAI Agents, LangGraph, Hermes, CrewAI, AutoGen, OpenTelemetry) are auto-detected.
ninja-harness run --task task.yaml --solver-cmd "python my_agent.py" --repeat 5
Your agent reads the task on stdin and prints a trace on stdout — any language. You get a certified report + reliability stats.
ninja-harness gate --results results.json --policy policy.yaml
ninja-harness suite --suite scenarios/suite.yaml --format summary
Exit codes fail your build; the summary posts to Slack/Telegram. Findings export to SARIF/JUnit.
This runs Ninja Harness entirely client-side via Pyodide — no server, no install, nothing leaves your browser. First launch downloads the Python runtime (a few MB), then it's cached.