> The full index of these docs is at [llms.txt](https://u22a8.ai/llms.txt).

# Send abstentions to a person

Automate the verdicts A8 answers at your minimum accuracy, and queue each abstention for a person with the check its evidence failed.

The verdict tells you what to do; the abstention tells you who decides. Act on every verdict A8 returns at your minimum accuracy, and send every abstention to a person.

## 1 Motivation

A queue of decisions splits into cases the evidence carries and cases it leaves open. A8 draws that line on every request at the [minimum accuracy](https://u22a8.ai/docs/a8-abstention.md) you set: an answered verdict holds its promise, and a case below it comes back as an abstention. Routing on that line automates the first set and gives people the second, so a person’s time goes to the cases that need judgment.

Every abstention also names the check its evidence failed, in `abstention.kind`, so the review queue sorts itself: a case too close to call goes to a reviewer, and an untaught criterion goes to whoever teaches A8.

## 2 Example

A support desk routes tickets to billing, shipping or account. A misrouted refund request costs a customer a day, so the desk automates routing at a minimum accuracy of 95 and has a support agent route the rest.

### 2.1 Step 1: judge at your minimum accuracy

Send each ticket with the criterion, the queue schema and the minimum accuracy:

```python
import json
import os

from openai import OpenAI

client = OpenAI(
    base_url="https://api.u22a8.ai/eval/v1", api_key=os.environ["U22A8_API_KEY"]
)

route = {
    "type": "json_schema",
    "json_schema": {
        "name": "route",
        "schema": {
            "properties": {
                "queue": {"enum": ["billing", "shipping", "account"]}
            }
        },
    },
}


def judge(ticket: str):
    return client.chat.completions.create(
        model="a8:95",  # minimum accuracy 95
        messages=[
            {
                "role": "system",
                "content": "Which queue does the ticket belong in?",
            },
            {"role": "user", "content": ticket},
        ],
        response_format=route,
    )
```

### 2.2 Step 2: act on a verdict, queue an abstention

An abstention arrives as a refusal, with its kind and levels in `abstention`:

```python
def handle(ticket: str):
    resp = judge(ticket)
    message = resp.choices[0].message
    if message.refusal is None:
        queue = json.loads(message.content)["queue"]
        assign(ticket, queue)  # automated at 95
        return
    abstention = resp.model_extra["abstention"]
    review(
        ticket,
        kind=abstention["kind"],  # the check the evidence failed
        answerable_at=abstention["answerable_at"],
    )
```

`assign` and `review` are your own functions. The abstention for a close call:

```json
{
  "kind": "too_close",
  "asked": 95,
  "answerable_at": 80,
  "earned": 97,
  "missing": null
}
```

Recorded from `a8-1-1@20260715t140322z` on 2026-10-22.

### 2.3 Step 3: sort the review queue by kind

| `kind`               | Send it to                                            |
| -------------------- | ----------------------------------------------------- |
| `too_close`          | A reviewer: the case sits near the line               |
| `unfamiliar_subject` | A reviewer, and the person who teaches A8             |
| `level_not_earned`   | The person who teaches A8                             |
| `no_evidence`        | The person who teaches A8, with `missing` attached    |
| `no_question`        | The system that sent it: the request held no question |

*Table 1.* Where each kind of abstention goes. The kinds and what clears each are on [Accuracy and abstention](https://u22a8.ai/docs/a8-abstention.md).

When a reviewer decides a case, their decision is a teach: tell your assistant the ticket belonged in billing, and A8 learns it. See [Teaching](https://u22a8.ai/docs/a8-teaching.md).

## 3 How the minimum accuracy was chosen

The minimum accuracy sets the trade between the two queues. A higher value sends more cases to people and makes the automated ones right more often.

1. **Start from the cost of a wrong automated decision.** A misrouted refund costs more than an agent’s minute, so the desk asks for 95: at least 95% of automated routes are correct.
2. **Measure coverage at that level on your own tickets.** Run a [test](https://u22a8.ai/docs/a8-testing.md) on tickets with known queues, and read the share answered. That share is the automated volume, and the rest is the review queue’s size.
3. **Teach the abstentions down.** `level_not_earned` and `no_evidence` shrink as you teach. `too_close` persists at some rate at every level above `0`, and those are the cases for a person.

## Next steps

- [Accuracy and abstention](https://u22a8.ai/docs/a8-abstention.md): How a request sets the minimum accuracy a verdict must meet, what that level promises and the five kinds of abstention.
- [Testing A8](https://u22a8.ai/docs/a8-testing.md): Test what A8 learned the way you would test a student, with new questions, known answers, accuracy and coverage, on a pinned version.
- [Teaching](https://u22a8.ai/docs/a8-teaching.md): How to teach and retract through MCP, when a teach lands in your organization’s model and what it changes.
