# RevoPSy: guide for scripts and AI agents

You can plan a peptide synthesis on a RevoPSy instrument over HTTP. You can look at the catalog, ask which residues of a sequence are
difficult, preview and compare plans, and store the plan you choose. You **cannot start a run**: a person loads the syringes and reagents
the loading sheet asks for, and presses Start. That is deliberate.

The machine-readable description is `GET /openapi.json`. This text is `GET /agent-guide.md`.

## 1. Access

* The **base URL** is shown in the UI where the token is made (*Account > API access*). Behind the HTTPS proxy it ends in `/api`
  (for example `https://revopsy.example/api`), on the instrument itself it is `http://<host>:8000`.
* Send `Authorization: Bearer rps_...` on every call. A token is made by a person in the UI, has a **scope** and **expires** (1 to 90 days):
  * `read`: catalog, methods, runs, library (all `GET`);
  * `plan`: also `POST /plans/difficulty`, `POST /plans/preview`, `POST /plans`.
* Anything else (starting a run, changing methods or the library, users, instrument commands) answers `403` for a token.
* First call: `GET /auth/me`. `401` = wrong or expired token; `403` = the token's scope is too small for that call.

## 2. The order of calls to plan well

1. `GET /materials`: find the **resin id** (name contains the resin, for example *Rink Amide*) and look at the amino acids.
2. `GET /methods`: choose a method (`is_default` marks the instrument default). Read its `json.blockInputs` if you want to know the
   deprotection time, the coupling reagents and the equivalents it uses.
3. `GET /library/profile-sets` and `GET /library/strategies`: optional. A profile set says what is different for an amino acid
   (longer time, more equivalents, another reagent). A strategy is a method plus a profile set under one name.
4. `POST /plans/difficulty` with `{ "sequences": ["..."], "method_id": "<id>" }`: for each sequence you get an `overall` verdict (how many
   residues are difficult, mean and maximum score), the `regions` that are hard, **risks** (aspartimide, diketopiperazine and others, with remedies) and **suggestions**. A suggestion names a
   `position`, a `slot` (Coupling, Deprotect, Capping) and an `override` (for example a double coupling, a longer time, more equivalents).
   Sources are in `references`.
5. `POST /plans/preview` with the run and `"accept_suggestions": true`: the plan with all suggestions applied. Compare variants by calling
   it again with another `method_id`, `profile_set_id`, `strategy_id`, `align`, or with a list in `accept_suggestions`
   (`[{ "vial": 1, "position": 7 }]`). Look at `summary.seconds_total` (time), `warnings`, `applied` (which residues were changed and why)
   and `materials` (what has to be loaded).
6. `POST /plans` with the request you chose. The answer has the `id` of the production. It appears in the list of runs as *not prepared*.
7. Tell the person what to do: the id, the warnings, the loading sheet (`materials`), and that they must load and start it in the UI.

## 3. The request

```json
{
  "method_id": "3",
  "run": {
    "sequence": ["AAAVVVAAAVVV"],
    "productName": ["AV test"],
    "resin": [{ "id": "4.6", "mass": 100 }]
  },
  "profile_set_id": null,
  "accept_suggestions": true
}
```

* **Notation.** One-letter codes written from the **N-terminus on the left to the C-terminus on the right**. The synthesis runs the other
  way: it starts at the C-terminus (the resin, the right end), and **position 1 is the C-terminal residue**, the first one coupled. A `2`
  after a letter marks a double coupling of that residue (`AAAVV2V...`).
* At most **6 sequences** (vials) per production; `run.resin` has one entry per sequence, `mass` is mg of dry resin.
* `profile_set_id`: leave it out for the instrument default, `null` for none.
* Do not combine `strategy_id` with another method or set: the plan is refused with `strategy_mismatch`.

## 4. Errors

Every error has `error` (the reason, in words) and often `code`:

| status | meaning |
|---|---|
| 400 | the request is wrong; the text says which field. Planner codes: `unknown_reagent`, `unknown_solution`, `rule_conflict`, `invalid_profile_set`, `strategy_mismatch`, `no_concentration`, `invalid_unit` |
| 401 | no token, wrong token, expired or revoked |
| 403 | the token's scope or the user's role does not allow this |
| 404 | no such method, set, strategy or run (or it is private to somebody else) |
| 409 | a strategy that the user cannot use; a stale draft |
| 429 | too many attempts; wait for `Retry-After` |

## 5. Example: AAAVVVAAAVVV on 100 mg Rink Amide

```sh
BASE=https://revopsy.example/api ; AUTH="Authorization: Bearer $REVOPSY_TOKEN"
curl -s -H "$AUTH" $BASE/materials | jq '.resins[] | select(.name|test("Rink";"i")) | {id,name,capacity}'
curl -s -H "$AUTH" $BASE/methods | jq '.methods[] | {id,name,is_default}'
curl -s -H "$AUTH" -H 'content-type: application/json' $BASE/plans/difficulty \
  -d '{"sequences":["AAAVVVAAAVVV"],"method_id":"3"}' | jq '.vials[0] | {overall,regions,suggestions,risks}'
curl -s -H "$AUTH" -H 'content-type: application/json' $BASE/plans/preview \
  -d '{"method_id":"3","run":{"sequence":["AAAVVVAAAVVV"],"resin":[{"id":"4.6","mass":100}]},"accept_suggestions":true}' | jq '{summary,warnings,applied}'
```

## 6. Rules for an agent

* **Never invent ids.** Take resin, method, set and strategy ids from the lists above.
* **Say what you changed and why.** Report `applied` and the `references` of the suggestions you accepted to the person.
* **Do not store a plan with warnings you do not understand.** Show them and ask.
* **A plan is not a run.** Hand over the production id; do not try to start it, and do not ask the person for their password.
* Tokens are secret. Do not print them or write them into files that are shared.
