Jers: decisions with memory
Typed questions in, typed answers with probabilities out, one call, no text generation. The same request and answer shape as TypeSafe's /v1/systemone, plus a per-subject memory that lives in RAM on this machine: a subject is whatever you decide about, a customer, a user, a player, a device, a case. Input is free; you pay per answer. Start with getting started and the examples; all pages at /docs, for agents /llms.txt. Try it in the playground.
Getting a key
python3 decision_api_server.py keys add --tenant acme --credit 5.00 # prints the key once
A decision
export JERS_API_KEY=jj_live_...
export JERS_BASE_URL=http://127.0.0.1:8797 # or this gateway's address
curl -s $JERS_BASE_URL/v1/systemone \
-H "Authorization: Bearer $JERS_API_KEY" -H "Content-Type: application/json" \
-d '{"state": {"message": "We were charged twice for September again."}, "model": "jers-english", "subject": "acme-ops",
"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"]}}}'
Leave out subject and the call is stateless. With it, the answer carries a memory block: the lines used, and with "memory": {"compare": true} the answer without memory and what changed.
Memory
POST /v1/memory/remember {"subject": "acme-ops", "text": "ACME holds an enterprise contract; refunds go to billing within one business day."}
POST /v1/memory/forget {"subject": "acme-ops", "concept": "enterprise contract"} removal verified against recall
POST /v1/memory/delete {"subject": "acme-ops"}
GET /v1/memory?subject=acme-ops&lines=true
POST /v1/memory/rules {"subject": "acme-ops", "when": "open_tickets >= 3", "text": "Escalate ACME to a person."} checked in code on the request's values
GET /v1/memory/rules?subject=acme-ops
POST /v1/memory/rules/delete {"subject": "acme-ops", "rule_id": "r_..."}
Models
jers | Jers; its language router picks the checkpoint |
jers-english | Jers, English checkpoint (ModernBERT-large) |
jers-multilingual | Jers, multilingual checkpoint (mmBERT-base) |
jers-typed-decisions | Jers, checkpoint fine-tuned on typed-decision workflows |
GET /v1/models says which ones answer right now and what is pinned, and lists the jers-ft- models fine-tuned for your tenant.
Prices
| per request | 0.00000 USD |
| per million input characters | 0.00000 USD |
| per answer | 0.00001 USD |
| per memory line written | 0.00001 USD |
| bill engine answers | no |
placeholder prices written by the code, not by the owner; input is free, each answer and each memory line written is priced; edit this file and restart. Input, the state and the questions, is free and counted in characters; each question answered is one answer, times the option orders (robust), windows and placebo pass you ask for, and usage.answers_billed shows it; tokens are reported only when the engine counted them. GET /v1/usage shows credit, spending and the last requests; every priced request is one line in the tenant's ledger.
Errors
400 bad Content-Length · 401 no or bad key · 402 no credit left · 403 sign-up off or invite needed · 404 not found · 409 a limit, such as 5,000 golden cases, 10,000 memory lines or 100 rules · 413 body over 1 MB (16 MB for /v1/batches and /v1/golden) · 415 not JSON · 422 bad request, with the reason · 429 over the key's requests per minute, with Retry-After · 500 gateway error, not charged · 502 engine or product down, not charged.
Rules that work in memory
A one-pass engine does not compare numbers and does not read negation. Put conditions in code: a memory rule with when (POST /v1/memory/rules) or derive in the request, checked on values and the state's fields. Leave options that must never be chosen out of criteria, and keep memories short.