# Read first, then decide

Source: https://docs.temprl.org/guide/read-then-decide

> Use two_pass and derive so Simo reads dates and amounts first, computes exact arithmetic over them, and decides with the facts in front of it.

When a decision depends on a value in the input ("was the claim filed within 30 days?"), the most reliable approach is to **read the values first**, do any arithmetic exactly in code, and **then decide** with those facts in front of the model. Simo does this in one request with `two_pass` and `derive`.

## two_pass

With `two_pass=True`, the service answers the `Fill` and `Extract` questions first, then answers the decisions with the values read written into them. A decision then sees "amount: 89.0" instead of re-deriving it from the text.

```python
r = c.ask(ticket, {
    "amount": Fill("the amount charged, in dollars", kind="number"),
    "large":  Noul("The amount is over $500"),
}, two_pass=True)
```

Both passes run in the same request.

## derive: exact arithmetic

`derive` computes values from the reads, exactly, and shows them to the decisions. The model reads; the arithmetic never comes from the model. `derive` turns `two_pass` on automatically.

**Python**

```python
from simoai import Client, Extract, Fill, Noul, days_between

c = Client()
r = c.ask(
    {"claim": claim_text, "policy": policy_text},
    {"accident": Extract("the date of the accident, exactly as written", max_tokens=12),
     "filed":    Extract("the date the claim was filed, exactly as written", max_tokens=12),
     "amount":   Fill("the amount claimed, in dollars", kind="number"),
     "late":     Noul("The claim was filed more than 30 days after the accident")},
    derive={"days": days_between("accident", "filed", "days between the accident and the claim")})

r.values["days"]   # 34: computed exactly from the two dates read
r.values["late"]   # True, decided with "days: 34" in front of the model
r.facts            # the facts the decisions were shown
```

**JSON**

```json
{
  "model": "simo-1-pro",
  "state": {"claim": "...", "policy": "..."},
  "questions": {
    "accident": {"type": "extract", "instructions": "the date of the accident, exactly as written", "kind": "text", "many": false, "max_tokens": 12},
    "filed": {"type": "extract", "instructions": "the date the claim was filed, exactly as written", "kind": "text", "many": false, "max_tokens": 12},
    "amount": {"type": "fill", "instructions": "the amount claimed, in dollars", "kind": "number", "max_tokens": 16},
    "late": {"type": "noul", "instructions": "The claim was filed more than 30 days after the accident"}
  },
  "derive": {
    "days": {"op": "days_between", "from": "accident", "to": "filed",
             "instructions": "days between the accident and the claim"}
  }
}
```

## Helpers

| Helper | Wire format | Meaning |
|---|---|---|
| `days_between(a, b)` | `{"op": "days_between", "from": a, "to": b}` | Days from date `a` to date `b`. Dates as written: "2026-09-28", "September 28, 2026", "Sep 28" (a date without a year takes the other's) |
| `difference(a, b)` | `{"op": "difference", "from": a, "to": b}` | `b - a` |
| `sum_of(a, b, ...)` | `{"op": "sum", "of": [a, b, ...]}` | The sum |

Inputs are ids of `Fill` or `Extract` questions in the same request, and a derived name must not be a question id. Each derived value comes back as a fill answer under its name. If its inputs can't be read, it is left out of the answers.
