---
title: "Domain Expert Evals: Who Decides What Good Means"
description: "Domain expert evals put the definition of correct in the hands of the qualified practitioner, not the engineer. How clinician annotations become CI gates."
author: "MDflow"
date: 2026-08-26
reading_time: "14 min"
canonical_url: https://mdflow.cz/blog/domain-expert-evals
md_url: https://mdflow.cz/blog/domain-expert-evals.md
---

# Domain Expert Evals: Who Decides What Good Means

*Published August 26, 2026 · 14 min read*


Most eval conversations are about the harness: which platform runs the scoring, how the traces are stored, whether the judge is a model or a person. Almost none are about the question underneath, which is who is actually qualified to say the output was wrong. **Domain expert evals** invert the usual order — the engineer builds the loop, but a practitioner in the field supplies the assertion.

At the [AI Engineer World's Fair](https://www.youtube.com/watch?v=O72p-rBb2bA), Akele Reed and Dave Revere of SonderMind described what that looks like when the domain is mental health care and getting it wrong has consequences that no dashboard captures. Their framing is worth borrowing even if your product never touches a clinical use case.

> **TL;DR** — In high-stakes domains the person who defines "correct" should be the licensed practitioner, not the engineer. SonderMind traces every guardrail edge case, has a clinician annotate it against a small rubric, and runs a script that turns those annotations into typed evals that gate every release — so clinical judgment lives in CI instead of in someone's memory. The hard part is not the harness, it is that the taxonomy, rubric and calibration decisions are prose that a non-engineer has to be able to write and a machine has to be able to read. [MDflow](/) holds that prose as versioned markdown both sides can reach.

## What are domain expert evals?

Domain expert evals are test cases whose **expected result was decided by a qualified practitioner**, not by the person who wrote the code. The engineer still owns the schema, the runner and the CI wiring. What changes is the source of the assertion: instead of "this looks wrong to me", the test encodes "a licensed professional reviewed this trace and said the system should have done X".

SonderMind builds Sonder, a clinically grounded AI coach for people who are not ready for therapy yet or need support between sessions. The context is not hypothetical: the American Psychological Association's [2026 Chatbots and Mental Health survey](https://www.apa.org/pubs/reports/chatbots-mental-health-2026) of more than 1,200 licensed psychologists found that **77% say their patients report using AI**, and 94% said chatbots cannot treat mental health conditions with appropriate nuance. People are already in the conversation; the question is what kind of system meets them there.

The example Reed and Revere used to make the point was not a keyword problem. A clinician gave them a real pattern from her practice: a message about packing a box, phrased so that the surface reading is someone preparing to move house and the clinical reading is someone contemplating not being here. Nothing in it matches a self-harm regex. A longer system prompt does not catch it. A general-purpose moderation API does not catch it. A clinician reads it and knows immediately.

That is the whole argument for domain expert evals in one example. The signal was the implication, not the words — and the only person who could reliably say so had a licence, not a commit history.

## Over-triggering is a failure, not a safe default

The instinct with anything sensitive is to make the guardrail eager, on the theory that a false positive costs nothing. In this domain it costs a great deal. As the SonderMind team put it, an inappropriate guardrail on someone reaching out in a vulnerable moment lands like a door slammed in their face, and it can push them further from the support they came for.

So the goal was stated as: **not more triggers, more correct triggers.** Three representative cases show what "correct" means:

1. A user describing danger in the present tense. The system surfaces local crisis resources and then **disengages** — continuing the chat is not the help that moment requires.
2. A user processing something that happened in the past, distressed but not in immediate danger. Resources are surfaced, and the conversation **continues** if the user wants it to.
3. A user working through ordinary relationship difficulty with no safety signal. The message passes straight through, and the user never learns the guardrails were there.

The same taxonomy explains something the team mentioned almost in passing during Q&A: on day one they had to **turn off the model vendors' built-in safety filters**, because those filters rejected the very clinical conversations the product exists to hold. Over-calibration is a compassionate default when a general-purpose model has no idea who is on the other end. It is a product-destroying default when you do.

Architecturally, the guardrails sit as separate LLM-as-a-judge calls that sandwich the core agent — one evaluating the incoming message, one evaluating the response and the conversation as a whole. Keeping them out of the main prompt makes them harder to talk around over a long conversation, and much easier to evaluate in isolation. It also costs latency and money on every turn, which the team judged an acceptable trade for this use case and would not necessarily be for yours.

## The loop: trace, annotate, type, gate

The mechanism that makes expert judgment durable is unglamorous, and that is the point.

**Trace the moment.** The edge case is captured in full, with enough conversation context that the decision can be re-examined later.

**Annotate it.** The clinician works an annotation queue, filling in a small rubric against the trace. The fields do more work than they look like they do:

```yaml
conversation_input: <the turns leading up to the moment>
expected_result: <what the system should have done>
expected_observation: <the assertion — the specific thing that must fire>
turn_index: <where in the conversation it should have fired>
category: <which taxonomy bucket this belongs to>
note: <context for the engineer doing the categorisation>
```

`expected_observation` is the assertion. `turn_index` is what lets the harness replay the conversation up to exactly the moment the guardrail should have fired, rather than scoring a final output and guessing. `category` is what turns one fixed sentence into a lifted category.

**Type it.** An extraction script triages the flagged traces into a report the team discusses, and normalises the same annotations into their eval schema. No one retypes a clinician's judgment into a test file by hand.

**Gate on it.** Once committed, every prompt change, model change and guardrail change is scored against what the clinician taught the system. The questions are concrete and checkable: did the expected observation fire, did the right category trigger, did it happen at the right turn, did the output evaluator catch the issue type.

The result Revere highlighted is the one that matters commercially as well as clinically: the win was not that one sentence got handled. It was that **the entire self-harm category lifted**, because the annotation carried a category and the category had a benchmark.

Two design choices hold the loop together. The clinical team owns the definition of good — vibes do not count, an accountable judgment from a licensed expert does. And the benchmarks are deliberately not pursued to perfection, because chasing a number on ambiguous edge cases drifts attention away from the humans the number exists to protect. Real failure modes from real data, scored on false positives, false negatives, category and timing.

SonderMind also open-sourced the baseline: **200 input-guardrail and 100 output-guardrail scenarios**, clinically reviewed, single- and multi-turn, calibrated against real conversation patterns. Not a replacement for your own loop — a floor, so nobody's learning curve is paid for by a person in crisis.

## Why this matters outside mental health

### For developers

The pattern generalises to any domain where **correctness is a professional judgment rather than a matching problem**: a contract clause that is unenforceable, a dosage that is contraindicated, a transaction pattern that is structuring, an accessibility failure that passes automated checks. In all of these, an engineer reading the output has no reliable way to score it, and an LLM judge inherits whatever the engineer wrote in the rubric.

Three things follow. Your eval set is bounded by how cheaply an expert can register a judgment — if annotating takes an hour and a Zoom call, you will get a handful of cases a quarter. Every annotation needs a category or you are fixing sentences instead of classes. And the extraction step has to be a script, because a manual hand-off is where expert judgment goes to die.

### For AI agents

An agent behaves according to the definition it can retrieve at run time. When the taxonomy that decides "crisis versus distress versus ordinary" lives in a slide deck, the judge prompt gets a paraphrase of it, and the paraphrase drifts from the version the human annotator is applying. Same input, two definitions, and the disagreement gets recorded as model error.

The fix is boring: keep one authoritative written definition, retrievable by both the human and the machine, with a history that answers "did the agent change or did the criteria change?"

## Which applications benefit most

1. **Health and clinical support tools** — where the standard of care is defined by licensed professionals and a false negative is a safety incident.
2. **Legal, tax and compliance assistants** — where a correct-sounding answer can be professionally negligent and only a qualified reviewer can tell.
3. **Financial advice, underwriting and fraud triage** — where regulators expect a documented, reviewable basis for automated decisions.
4. **Trust and safety classification** — where policy nuance sits with a policy team, not with the engineers shipping the classifier.
5. **Scientific and technical assistants** — where the expected answer requires domain training the build team does not have.
6. **Customer support agents in regulated industries** — where "helpful" and "permitted" are decided by different people.

## How MDflow fits

**MDflow is not an eval harness.** It does not run judges, store traces, or score anything. That belongs to your eval platform.

What it addresses is the layer this whole loop rests on: **the taxonomy, the annotation rubric, the category definitions and the calibration decisions are prose, written by people who do not have a repository account.** A clinician is not going to open a pull request to clarify what distinguishes a category-2 scenario from a category-3. If that definition lives in a repo, it gets summarised into a Google Doc; if it lives in a Google Doc, CI cannot read it.

### What already lines up today

**Markdown that a professional can edit and a script can fetch.** Documents are plain markdown, and every one has a [raw `.md` twin](/markdown-ai) an agent or a CI job can retrieve directly. The annotator edits the document; the judge prompt and the extraction script read the same bytes.

**Sharing by email, no account in your stack.** A rubric or taxonomy can be shared privately with named people by email address, or as a link, without giving anyone access to the rest of the workspace — and [collections](/use-cases/sharing) let the whole pack travel together as one reference for a reviewer or an external panel.

**Comments where the ambiguity is.** Readers can attach a comment to a selected passage of the markdown, highlighted inline. An edge case argued in the margin of the rule it concerns is recoverable; the same argument in a Slack thread is not.

**Version history answers "who moved the definition".** Every save captures the previous version across every write path — editor, HTTP API and MCP — with line-by-line diffs and non-destructive restore. When a benchmark moves between two runs, this is what tells you whether the agent changed or the criteria did. (Pro feature, private to the owner, deliberately not exposed over the API or MCP.)

**Folder descriptions make the right definition retrievable.** Every folder carries a description of what belongs in it, and [`mdflow_get_context`](/docs/mcp) ranks those descriptions above folder names and titles — so a folder described as *"clinical guardrail taxonomy and calibration decisions — authoritative, annotators and judges both read these"* is a retrieval signal you wrote rather than one a model guessed. That is [why folder descriptions beat file names](/blog/folder-descriptions-agent-context).

**One workspace, both readers.** The same documents are reachable from Claude, ChatGPT, Cursor and Codex over the [remote MCP server](/docs/mcp) with OAuth or a Personal Access Token, and from CI, cron and n8n over the [HTTP API](/docs/api).

**Encryption where the material is sensitive.** Annotated traces in these domains contain the most sensitive text a company holds. Documents can be [client-side encrypted](/blog/encrypted-notes-app), which also means they are never scanned or indexed server-side.

### Where we are headed

Direction, not a dated commitment: we are most interested in making a written definition **easier to pin to a moment in time** — referencing a specific version of a document rather than whatever is current, and richer structured retrieval over folder descriptions. For this loop, "which version of the taxonomy produced this verdict" is the question we would most like to make trivial.

## The bottom line

The interesting part of an eval system is not the runner. It is the sentence that says what should have happened, and whether the person who wrote it was qualified to. SonderMind's answer is to give that authority to clinicians, capture their judgment in a typed record with a category and a turn index, and let a script carry it into CI so it gates every future change.

That produces two artefacts. One is a test suite, which your eval platform owns. The other is prose — a taxonomy, a rubric, a set of calibration decisions — that a non-engineer has to be able to write and a machine has to be able to read, and which is worth exactly as much as your ability to tell what it said last month.

[Start free](/login) · [Connect an AI agent](/docs/mcp) · [Read the API docs](/docs/api)

## Frequently asked questions

### What are domain expert evals?

Domain expert evals are test cases whose expected result was decided by a qualified practitioner in the field rather than by the engineer building the system. The engineer still owns the harness, the schema and the CI wiring, but the assertion — what the system should have done on this specific input — comes from someone accountable for that judgment. In regulated or high-stakes domains this is the difference between a test that encodes product intuition and a test that encodes professional standard of care.

### Why is a guardrail that triggers too often a failure and not a safe default?

Because a false positive has a victim. SonderMind's team put it plainly: an inappropriate guardrail on someone reaching out in a vulnerable moment feels like a door slammed in their face, and it can push them further from the support they came for. Over-calibration is also why they had to disable the model vendors' built-in safety filters, which rejected the very clinical conversations the product exists to hold. The target is not more triggers, it is more correct triggers.

### How does a domain expert's annotation become an automated test?

Through a typed schema. SonderMind captures the conversation trace, the expert annotates it in a queue against a small rubric, and an extraction script normalises those fields into their eval format: the conversation input, the expected result, the expected observation that acts as the assertion, a turn index so the run can be replayed up to the moment the guardrail should have fired, and category metadata. Once committed, every prompt, model and guardrail change is scored against it.

### Should guardrails be separate model calls or instructions in the main prompt?

SonderMind runs them as separate LLM-as-a-judge calls that sandwich the core agent — one on the incoming message, one on the outgoing response and the conversation as a whole. Separate calls are harder to jailbreak conversationally than a safety rule buried in a long system prompt, and they are far easier to evaluate in isolation. The trade-off is real: extra latency and extra cost per turn.

### What does MDflow do for domain expert evals?

MDflow is not an eval harness and runs no scoring. It holds the written half — the taxonomy, the rubric the annotator reads, the category definitions and the calibration decisions — as plain markdown documents with version history and line-by-line diffs. A non-engineer can be given edit access by email without a repository account, and CI or a judge can fetch the same document over MCP or the HTTP API, so the expert and the machine read one definition instead of two copies that drift.

## Further reading

- [Evals-Driven Development for a Mental Health AI Coach — Akele Reed & Dave Revere, SonderMind](https://www.youtube.com/watch?v=O72p-rBb2bA) — the talk this post is based on, including the open-sourced guardrail scenarios.
- [Patients are bringing AI to therapy](https://www.apa.org/pubs/reports/chatbots-mental-health-2026) — the APA's 2026 Chatbots and Mental Health survey of more than 1,200 licensed psychologists.
- [Psychologists say patients are turning to chatbots](https://www.apa.org/news/press/releases/2026/06/patients-chatbots-mental-health) — the APA's press summary of the same findings.
- [Engineering a clinically-grounded AI mental health coach](https://www.zenml.io/llmops-database/engineering-a-clinically-grounded-ai-mental-health-coach-with-safety-first-guardrails) — a third-party write-up of SonderMind's architecture in the ZenML LLMOps database.
- [Eval rubrics for AI agents](/blog/eval-rubrics-for-ai-agents) — the companion piece on golden sets, LLM judges and rater agreement.
- [Agent observability and the self-improving loop](/blog/agent-observability-self-improving-loop) — how traces become fixes.
- [MDflow MCP docs](/docs/mcp) · [HTTP API docs](/docs/api) · [FAQ](/faq)

