Quick start

Jers is a hosted API at https://api.getjers.com. There is nothing to install or run. Three steps.

1. A key

Write to ceyoualigator@gmail.com with a sentence about what you want to decide; you get a key and your starting credit. Keep it in JERS_API_KEY. Keys start with jj_live_; only their hash is stored.

2. A decision

curl -s https://api.getjers.com/v1/systemone \
  -H "Authorization: Bearer $JERS_API_KEY" -H "Content-Type: application/json" \
  -d '{
    "state": {"message": "We were charged twice for September again. We just want the money back."},
    "model": "jers-latest",
    "questions": {
      "route":   {"type": "choice", "instructions": "Which team should handle this?",
                  "criteria": {"billing": "Charges and refunds", "support": "Product problems", "sales": "New licences"}},
      "refund":  {"type": "noul",   "instructions": "Is the customer asking for money back?"},
      "urgency": {"type": "score",  "instructions": "How urgent is this?",
                  "criteria": ["Can wait a week", "Should be handled today", "Blocking the customer now"]}
    }
  }'

The answer, measured on 2026-09-23 through a gateway and product started from this repository (jers-latest resolved to jers, whose router picked the English checkpoint). engine.runtime, the engine's own metadata, is left out here; the engine adds fields of its own, such as action, which Jers passes through. The warning says that route has no option for a message that fits none of the three; add "other": "None of these" and it goes away:

{
 "decision_id": "dec_02561a958a6ea3a255a69a71",
 "model": "jers",
 "engine": {
  "name": "jers",
  "checkpoint": "english"
 },
 "answers": {
  "route": {
   "type": "choice",
   "choice": "billing",
   "probabilities": {
    "billing": 0.992,
    "support": 0.005,
    "sales": 0.002
   },
   "confidence": 0.955,
   "action": {
    "act_probability": 1.0
   }
  },
  "refund": {
   "type": "noul",
   "noul": 0.897,
   "confidence": 0.897,
   "action": {
    "act_probability": 1.0
   }
  },
  "urgency": {
   "type": "score",
   "score": 1.671,
   "legend": {
    "0": "Can wait a week",
    "1": "Should be handled today",
    "2": "Blocking the customer now"
   },
   "probabilities": {
    "0": 0.008,
    "1": 0.313,
    "2": 0.679
   },
   "confidence": 0.396,
   "action": {
    "act_probability": 1.0
   }
  }
 },
 "usage": {
  "input_characters": 487,
  "questions": 3,
  "answers": 3,
  "answers_billed": 3,
  "engine_answers": 3,
  "memory_lines_used": 0,
  "memory_lines_seen": 0,
  "engine_ms": 36.0,
  "cached": false,
  "state_tokens": 20,
  "state_tokens_read": 20,
  "state_truncated": false,
  "input_tokens": 163,
  "cost": 3e-05,
  "currency": "USD",
  "balance": 4.99994,
  "gateway_ms": 37.1
 },
 "warnings": [
  {
   "code": "no_other_option",
   "question": "route",
   "message": "add an option such as other or none_of_these, so a state that fits nothing is not forced into the least bad option"
  }
 ],
 "reading": {
  "route": {
   "state_tokens": 20,
   "read": 20,
   "room": 480,
   "chars_read": 86,
   "truncated": false
  },
  "refund": {
   "state_tokens": 20,
   "read": 20,
   "room": 478,
   "chars_read": 86,
   "truncated": false
  },
  "urgency": {
   "state_tokens": 20,
   "read": 20,
   "room": 475,
   "chars_read": 86,
   "truncated": false
  }
 }
}

reading says how much of the state the engine read for each question (all of it here); decision_id is what you send back with POST /v1/feedback once you know the right answer.

3. A memory

Write what you know about the subject once, then name it in decisions:

curl -s https://api.getjers.com/v1/memory/remember -H "Authorization: Bearer $JERS_API_KEY" -H "Content-Type: application/json" \
  -d '{"subject": "acme", "text": "ACME Logistics holds an enterprise contract; refunds for ACME go to the billing team within one business day.\nACME'\''s account is handled by the enterprise desk."}'

Add "subject": "acme" and "memory": {"compare": true} to the decision request. The answer gains a memory block: the lines used (hits), how many the engine read (lines_seen), the answer without memory, and what changed.

Python

The Python SDK is not on PyPI yet; this is how it reads once it is (the requests above work today).

from jers import JersClient, Choice, Noul, Score

with JersClient() as client:
    r = client.system_one(
        state={"message": "We were charged twice for September again."},
        questions={"route": Choice("Which team should handle this?", {"billing": "Charges and refunds", "support": "Product problems"}),
                   "refund": Noul("Is the customer asking for money back?"),
                   "urgency": Score("How urgent is this?", ["Can wait a week", "Should be handled today", "Blocking the customer now"])},
        subject="acme", memory={"compare": True})
    print(r.answers["route"].choice, r.answers["route"].confidence, r.memory.lines_used, r.usage.cost)