đŻ Writing Useful Evals
Welcome to the heart of skill-eval! If youâre new to writing evals (short for evaluations), think of them as friendly grading rubrics for your AI. Instead of traditional unit tests that just check if code compiles, an eval checks if the AI made the right kinds of decisions when following your skillâs instructions.
A well-written eval doesnât just check that an agent can do a task â it checks whether your skill makes the agent better at it.
This guide is your trusty companion to writing evals that produce trustworthy, actionable numbers. Letâs dive in.
The Golden Rule
A good eval is one where the baseline run fails more often than the with-skill run.
If both the baseline (the AI working all alone) and the skill (the AI armed with your awesome instructions) sail through every assertion, you canât tell if the skill is actually helping. The eval might be a little too easy, or your assertions might just be checking generic correctness instead of the specific superpower your skill provides.
What if the baseline gets 100%?
When the baseline gets a perfect score, it usually means one of two things:
- Your evals are too easy! The task doesnât need the skillâs guidance. Time to crank up the difficulty or make the assertions more specific.
- Your skill isnât needed for this task. The base model already knows how to do it without you. Thatâs super useful information. You can now focus your skill on a narrower or trickier problem.
The benchmark numbers alone canât tell you which one is true. You have to peek at the actual outputs and judge whether your skill is producing noticeably better work.
Start with the Skillâs Promise
Before you write a single assertion, try finishing this sentence:
âMy skill helps the agent do ______ better than it would on its own.â
Every eval should target that exact gap. If your skill teaches a migration from Mocha to Jest, donât just ask âdo the tests pass?â â ask âdid the agent replace sinon.stub() with jest.spyOn() exactly how the skill describes?â
Anatomy of a Strong Eval
A strong eval has three key ingredients:
- A focused prompt that gives just enough context (donât overwhelm the AI).
- Input files that exercise a real, meaty corner case.
- Assertions that check the skill-specific behavior, not just basic success.
Letâs look at an example prompt:
{
"prompt": "Migrate evals/fixtures/sinon-sandbox.spec.js from Sinon to Jest. Write the migrated file to outputs/sinon-sandbox.spec.js. Do not run the tests."
}
Great assertions for this prompt might be:
file_exists:sinon-sandbox.spec.js(Did it even make the file?)contains_text:sinon-sandbox.spec.js:jest.spyOn((Did it use the right tool?)contains_text:sinon-sandbox.spec.js:jest.restoreAllMocks()(Did it clean up after itself?)The output file does not import sinon or call require('sinon')(Did it leave the old stuff behind?)jest.spyOn calls appear inside beforeEach, not at module scope(Did it understand the nuance?)
Notice how those last few assertions verify the shape of the migration â the exact behavior your skill is trying to teach.
Assertion Types & When to Use Them
skill-eval gives you four built-in assertion styles. Letâs mix them wisely.
1. Deterministic Matchers
Use these whenever you can. Theyâre blazingly fast, cheap, and never vary between runs.
file_exists:<name>â Checks that an output file was actually produced.contains_text:<file>:<text>â A simple, reliable substring check.matches_text:<file>:<regex>â When you need some regex pattern matching magic.
These are your bread and butter for structural checks: imports, function names, config keys, and exact strings.
2. LLM Judge Assertions
Use these for subjective or semantic checks that a regex just canât catch.
Examples:
"The explanation is clear and actionable.""The refactor preserves the original behavior.""The output follows the repository's existing friendly style."
LLM assertions are super powerful but a bit slower and more expensive. Keep them focused â 1 to 2 per eval is usually perfect. Always pair them with at least one deterministic assertion so a totally empty output doesnât pass by accident.
3. Negative Assertions
Donât just assert what should be there â assert what shouldnât.
"The output does not import sinon.""No placeholder text like 'TODO' or 'Lorem ipsum' appears."
Negative assertions catch lazy outputs that technically pass a positive check but totally miss the point.
Common Eval-Writing Traps
Watch out for these pesky pitfalls.
1. The âAny Correct Answerâ Trap
đŤ Oops: "The output is a valid JSON file."
â
Nailed it: "The JSON contains a 'users' key with at least three entries, each with an 'id' and 'email'."
2. The âCheck the Wrong Thingâ Trap
đŤ Oops: For a code-migration skill, only checking that the tests pass.
â Nailed it: Checking that the old pattern is gone and the new pattern is present in the right place.
3. The âSingle Golden Pathâ Trap
If every eval uses the exact same simple input, the model will just coast on prior knowledge. Spice it up!
- Include a tricky edge case.
- Include a deliberately messy file.
- Include a case where the naive answer is subtly wrong.
4. The âForty Assertionsâ Trap
More assertions donât always mean better signal. A smaller set of sharp, focused assertions beats a giant wall of fuzzy ones. Aim for a sweet spot of 3â7 assertions per eval.
Make Your Evals Fail First
We know this sounds backwards, but itâs the absolute fastest way to know theyâre working.
- Write your evals and assertions.
- Run the baseline (no skill) and watch them fail beautifully.
# The run command will execute your evals skill-eval run --baseline previous # The grade command evaluates the outputs against your assertions skill-eval grade - Run the with-skill version and watch more of them turn green!
# Alternatively, use loop to run, grade, and benchmark all at once! skill-eval loop
If your baseline already passes, tighten up those assertions until it doesnât. If you just canât get it to fail, the task might not be a great target for your skill.
Prompt-Writing Tips for Eval Authors
- Be explicit about output location. Tell the agent exactly where to save its work.
- Forbid sneaky shortcuts. Add phrases like âDo not ask questionsâ or âDo not run the testsâ if those would derail your eval.
- Keep files bite-sized. Huge inputs blow up tokens and obscure your signal.
- Use realistic fixtures. The closer the input looks to real user data, the more useful your results will be.
Iterate on Your Evals Like You Iterate on Your Skill
Evals arenât set-and-forget. As your skill levels up, your evals should too:
- Remove assertions the skill now passes in its sleep.
- Add new ones that stretch the skill even further.
- Delete evals that no longer measure anything meaningful.
A healthy eval suite actually gets harder over time. Thatâs how you know your skill is genuinely improving.
Quick Checklist
Before you run the full skill-eval loop command, ask yourself:
- Can I explain exactly what gap this eval is measuring?
- Will the baseline run plausibly fail at least one assertion?
- Do my assertions check the skill-specific behavior, not just generic correctness?
- Are at least some assertions deterministic?
- Did I include a negative assertion to catch lazy outputs?
- Is the prompt super clear about where outputs should go?
If you can check all six boxes, youâre in fantastic shape. Happy evaluating!