> ## Documentation Index
> Fetch the complete documentation index at: https://docs.canary.effectiveai.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Missing answers

> Why a rater answers a request that leaves inputs out, what each of its three results promises, and how one answer narrows the next question.

A quote starts with a few answers and gains the rest one at a time.
At each point, an RSL rater says what the answers so far settle and which missing answers still matter.
This page gives the reasons behind that behavior. [Rate with missing answers](https://docs.canary.effectiveai.app/rsl/how-to/rate-with-missing-answers.md) gives the steps.

## Why a rater answers a partial request

A full rating needs the whole request. `rate` refuses a request that lacks a required input, and names the input.
That refusal says what is absent. It stays silent on whether the absent input changes the premium.

The rater holds the tables, the conditions and the rules, so it knows which inputs each outcome reads.
`evaluate` uses that knowledge on the answers it has. A host that asks questions then needs only the rater's result, and the rating logic stays in one place.

The examples use the shared renters rater from the synthetic carrier Example Mutual:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc examples get renters
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
WROTE renters/rater.rsl
WROTE renters/tables/BaseRate.csv
WROTE renters/tables/BuildingFactor.csv
WROTE renters/tables/DeductibleFactor.csv
```

This request leaves out `construction`, which the rater declares as a required input:

```python theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
import json

import rslc

rater = rslc.PreparedRater("renters")
request = json.dumps({"Policy": {"insured_now": False, "contents": 30000, "territory": "rural", "has_dog": False}})

results, _, _ = rater.rate(f"[{request}]")
print(results[0]["refusal"]["violations"][0]["message"])
# missing required input construction
print(rater.evaluate(request))
# {"settled":{"ok":true,"outputs":{"Policy":{"premium":216}}}}
```

`rate` asks for the complete request. `evaluate` returns the premium, because each construction gives \$216 in the rural territory.

## The three results

| Result | The given answers | What the result promises |
| - | - | - |
| Settled | fix every outcome | The outcomes equal a full rating of each complete request that holds them |
| Refused | break a rule | A broken business rule is final. A value outside its type or range needs a correction |
| Open | leave an outcome or a business rule undecided | Each gap is a missing input that can still change the result |

The rater decides among them in a fixed order:

```mermaid theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
%%{init: {'theme': 'base', 'themeVariables': {'primaryColor': 'whitesmoke', 'primaryTextColor': 'black', 'primaryBorderColor': 'gray', 'lineColor': 'silver', 'edgeLabelBackground': 'whitesmoke', 'tertiaryColor': 'whitesmoke'}}}%%
flowchart TD
    R["A request that leaves inputs out"] --> V{"Does each given value pass its<br/>type, range and shape rules?"}
    V -- "a value fails" --> I["<b>invalid</b><br/>correct the value"]
    V -- "each passes" --> B{"Does a given answer break<br/>a business rule?"}
    B -- "yes" --> D["<b>settled</b>, ok: false<br/>a final refusal"]
    B -- "each rule holds so far" --> O{"Does a missing input still decide<br/>an outcome or a business rule?"}
    O -- "yes" --> G["<b>open</b><br/>gaps and known outcomes"]
    O -- "all decided" --> S["<b>settled</b>, ok: true<br/>final outcomes"]

    classDef box fill:whitesmoke,stroke:gray,color:black,stroke-width:1px;
    class R,V,I,B,D,O,G,S box;
    linkStyle default stroke:silver,stroke-width:1px,color:black;
```

* A refusal for a business rule arrives as `settled`, because it is as final as a premium.
* A refusal for a bad value arrives as `invalid`, and it comes before any business rule.
* An `open` result also lists each outcome that is already final, as `known`.

[Results](https://docs.canary.effectiveai.app/rsl/reference/results.md) lists each field of the three results.

## A missing answer stays unknown

The rater treats a missing input as unknown. It leaves the value open, in place of zero or a typical value.
An unknown value flows through each calculation that reads it, and the outcome stays unknown too.

A default would price a different risk. Suppose a host fills in `false` for a missing `has_dog`.
The renters rater then returns \$216 for a household whose true result is \$241, or a refusal.
The person sees a premium that the next answer withdraws.

Because the rater uses only given answers, a settled result holds for each way to complete the request.
A host shows it as final and skips the questions that remain.

One kind of input does carry a default, and the rater declares it. A choice is something the person buys, such as a deductible:

```rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
deductible: Deductible [choice, api_default: "500", ask: "Which deductible do you want?", group: "Coverage"]
```

A request that leaves `deductible` out buys the \$500 deductible, so a choice stays out of the gaps.
[Input contract](https://docs.canary.effectiveai.app/rsl/reference/input-contract.md) describes how a host reads a choice and its default.

## When a follow-up input applies

A follow-up input belongs to a request only when its condition holds:

```rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
has_dog: Bool [ask: "Do you have a dog?", group: "Household"],
dog_has_bitten: Bool when self.has_dog [ask: "Has the dog bitten anyone?", group: "Household"]
```

| `has_dog` | `dog_has_bitten` | The rater |
| - | - | - |
| `false` | is outside the request | skips the question, and ignores a given value |
| `true` | is a gap until it has a value | lists it, because a business rule reads it |
| missing | waits on its condition | lists `has_dog` as the gap |

So an input outside the request differs from an unanswered input.
The first has left the question list for good. The second stays on the list until a given answer makes it irrelevant.
A follow-up question also comes after the question that decides whether it applies.

## How one answer narrows the next question

The rater reads each rate table with the answers that it has. The building table of the renters rater files these factors:

| Territory | Frame | Masonry | Fire resistive |
| - | - | - | - |
| Metro | 1.30 | 1.15 | 1.00 |
| Suburban | 1.10 | 1.00 | 1.20, the all-other factor |
| Rural | 1.20 | 1.20 | 1.20 |

With `territory` answered, the rater looks only at that row:

| `territory` | The rows that fit | What the rater says about `construction` |
| - | - | - |
| `rural` | three rows with one factor | `construction` leaves the gaps |
| `metro` | three rows with three factors | a gap, with the three filed values as `choices` |
| `suburban` | two rows and the all-other row | a gap, with two `choices` and `more` |

The same reasoning applies to the other forms of a calculation:

* When the rows that fit agree, the lookup has its value and the missing key leaves the gaps.
* When the rows differ, their values for the missing key become its `choices`.
* An `if` with a known condition reads one branch. The inputs that only the other branch reads leave the gaps.
* A condition such as `a and b` is false as soon as one side is false.

The rater names a gap whenever it lacks a proof that the input is irrelevant.
A lookup compares at most 128 fitting rows, and a longer list of rows stays open.
So a gap sometimes changes little, and a settled result is always exact.

## What this means for a quoting conversation

* **Ask in the order of the gaps.** The rater lists first the inputs that it needs first.
* **Stop when the result is settled.** The premium equals the premium of the complete request.
* **Show a known outcome early.** A premium under `known` is final for each answer that the rules accept.
* **End on a refusal.** A broken business rule settles the request, and the remaining questions stay unasked.
* **Evaluate again after each answer.** Each call stands alone, so the same request gives the same result.

One rater gives the gaps for one program. [Plan the next question](https://docs.canary.effectiveai.app/rsl/how-to/plan-the-next-question.md) merges the gaps of several raters into one list of cards.

## Related

* [Ask the questions a rater needs](https://docs.canary.effectiveai.app/rsl/tutorial/ask-questions.md) writes a rater with questions and follow-up inputs.
* [Checks and guarantees](https://docs.canary.effectiveai.app/rsl/explanation/checks-and-guarantees.md) covers the proofs behind a complete rating.
* [Refusals](https://docs.canary.effectiveai.app/rsl/reference/refusals.md) lists the fields and codes of a refusal.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.