# fixragent-triage

One maintenance photo in, one fixed JSON out: what it is, how urgent, which trade to call, what to say. This is the Python client for the fixRAgent triage API — `POST https://fixragent.com/api/triage` — in one file, standard library only. Python 3.9 or newer.

## Install

The file is the install. Download it and import it:

```sh
curl -fsSL https://fixragent.com/sdk/python/fixragent_triage/__init__.py -o fixragent_triage.py
```

The same file is the `fixragent-triage` package; the `pip install fixragent-triage` line lands here with the first publish, and the import below stays the same.

## Triage a photo

```python
import os
from fixragent_triage import triage, FixragentError

with open("photo.jpg", "rb") as f:
    reply = triage(
        f.read(),
        key=os.environ["TRIAGE_DEMO_KEY"],   # sent as x-triage-key
        config="fast",                       # "fast" reads the photo three times, "deep" five
        problem_text="Water on the floor under the heater.",
    )

core = reply["core"]
print(core["tier"], core["trade_required"], core["resident_explanation"])
# e.g. TODAY Plumber There is water on the floor under the heater …
print(reply["agreement"])       # {'mode': 'fast', 'n': 3, 'k': 3, 'decided': True, …}
print(reply["diagnosis_id"])    # keep it: the Triage Profile is https://fixragent.com/c/<diagnosis_id>
```

`photo` is `bytes`, a base64 string or a `data:image/…;base64,` URL (JPEG, PNG or WebP, 1 KB to 3 MB decoded). The reply is the API's own JSON as a `dict` — `core` carries the twenty fixed fields, `agreement` says how many independent reads agreed, `callback_url` is where the outcome goes. Every field is typed in `types.py` (`TypedDict`s generated from the published OpenAPI document).

Read three fields first: `core["tier"]` (one of `EMERGENCY`, `TODAY`, `THIS WEEK`, `WHENEVER`, assigned in code from fixed rules), `core["trade_required"]`, and `core["resident_explanation"]`.

### Spanish

```python
reply = triage(photo, key=key, lang="es")
```

`lang="es"` answers with the prose fields — `fault_summary`, `photo_subject`, `asset_type`, `trade_required`, `resident_explanation` — in Spanish. `hazard_detail` stays in English, on purpose: the hazard line is never machine-translated. `reply["language"]` says what was served.

### Arguments

| argument | values | default |
|---|---|---|
| `key` | your demo key | `None` (required on production) |
| `config` | `"fast"` (three reads) · `"deep"` (five reads) | `"fast"` |
| `extended` | `True` adds the `extended` block | `False` |
| `mime_type` | `"image/jpeg"` · `"image/png"` · `"image/webp"` | `"image/jpeg"`, or the type in a data URL |
| `problem_text` | the reporter's own words, up to 1,200 characters | `None` |
| `reporter` | `"resident"` · `"assessor"` · `"technician"` | `None` |
| `lang` | `"en"` · `"es"` | `None` |
| `variant` | up to 40 characters, stored on the row | `"source:sdk-python"` |
| `base_url` | the API base | `https://fixragent.com` |
| `opener` | an injected `callable(Request)` | `urllib.request.urlopen` |
| `timeout` | seconds | `90` |

## Report what happened

```python
from fixragent_triage import report_outcome

report_outcome("fixed", callback_url=reply["callback_url"], fixed_by="pro", trade="plumber")
```

`outcome` is `"fixed"`, `"not_fixed"` or `"partial"`. Photo, triage, what actually happened — that loop is the point.

## Errors

A reply the API refused raises `FixragentError`:

```python
try:
    triage(photo, key=key)
except FixragentError as e:
    print(e.status, e.code, e.message, e.retry_after)
    # 429 rate_limited "…" 1800   — the guard that stopped you, in a sentence, with the seconds to wait
```

`code` is the API's own `error` value (`demo_key_required`, `rate_limited`, `demo_key_quota`, `budget_exhausted`, `image_too_large`, …), `message` its plain-words sentence, `retry_after` the `Retry-After` header in seconds when one was set.

## Try it without a key

Point `base_url` at the mock, which replays captured replies and runs no engine:

```python
reply = triage(photo, base_url="https://b1442b0b-4a7a-4135-ab4d-9c4b9c1ab0d2.mock.pstmn.io")
```

The mock takes a request body of up to 1 MB, so send it a small copy of the photo. Details: https://fixragent.com/docs#mock.

## The key

Ask at https://fixragent.com/docs#key, or email legal@fixragent.com with one line on what you are building, and a person replies with your key. A demo key carries 60 requests a day; one address gets 20 an hour.

## The rest

- The reference, field by field: https://fixragent.com/docs
- OpenAPI: https://fixragent.com/openapi.json · Postman: https://fixragent.com/docs/fixragent-triage-api.postman_collection.json
- The JavaScript client: https://fixragent.com/sdk/js/index.mjs · The MCP tool: https://fixragent.com/mcp/README.md
- Terms for the API: https://fixragent.com/api-terms — the reply is an educational triage for routing; gas, water near electrics and exposed wiring go straight to a licensed trade.
