| If the message is about | It goes to |
|---|---|
| a quiz, assignment, task, test or in-class activity: deadline, points, marks, what to submit, notes, how to do one | the TS-03 Academic Tracker (the snapshot of your tracker sheet) |
| NLU, NLP, FoVL or Computer Vision: lectures, class days, holidays, exam dates, slides, recordings, who teaches | the professors' course sheet kept by Prof. Sidharth Ranjan and Prof. Deeksha (read through the schedule cache, Guide 16) |
| learning or preparing a concept | /prep study help |
| who teaches a subject outside that course sheet | the subject list |
| unsure | the bot asks which one you mean |
It is off by default. Commands (/week, /nlp, /add and the rest), the owner's write commands and every answer path stay exactly as they are. If Jev is down, slow or unsure, the existing rules decide.
Related: Guide 14 (routing), Guide 15 (running everything), Guide 16 (the course sheet). Every guide and diagram by name: docs index.
1. What Jev is
Jev is a commercial "System One" model from TypeSafe AI. It generates no text. Given a message and a few typed questions, it returns a choice from fixed options, a score on a rubric, or the probability that a statement is true. Early access opened on 15 September 2026. Cloudflare's open decision model, Clef, takes the same request, so it works as a stand-in. Accuracy and speed figures come from the vendor and from other people's tasks, so this guide has you measure it on your own messages before it acts (section 4, steps 6 and 7).
2. How a decision is made
Jev decision flow
Green is where the message ends up. Yellow is the safe fallback or a question back to the person.
The decision styles:
| Style | When | Rule |
|---|---|---|
| Rule A: tracker first | the message has a quiz, assignment, task, test, due, notes or how-do-I word | it stays with the tracker if Jev gives the tracker at least tracker_priority (0.40), even when it also names NLP. "NLP lecture or assignment due?" goes to the tracker |
| Decisive | Jev's top route is at least need (0.75) and ahead of the next by lead (0.25) |
go there |
| Course check | the winner is the professors' sheet | needs course_min (0.50) that a course is named. "Is there class on 9 October?" names none, so the bot asks which subject |
| Rules break the tie | Jev is not decisive but the rules have a signal | use the rules' route |
| Ask | not decisive and no rule signal | one line asking tracker or course sheet, no answer call spent |
| Rules only | slash commands, owner write commands, anything Jev cannot reach | Jev is never consulted |
A Jev-routed question
Jev only chooses the route. The answer is still written by the same zero-tool sandbox as before, from the tracker snapshot, the schedule cache or the study material.
3. What Jev is asked
One request with two typed questions about the message text. The course names come from ~/.config/ts03-schedules.json.
{"state": "is there NLP class on 9 October?",
"questions": {
"route": {"type": "choice", "instructions": "Where should this classmate message go? Choose the single best destination.",
"criteria": {"tracker": "A quiz, assignment, task, test or in-class activity: ...",
"professors_sheet": "The course sheet kept by the professors (NLP, NLU, CV, ...): lectures, class days, ...",
"study": "A request to explain, learn or prepare a concept or topic",
"people": "Who teaches ... for a subject outside that course sheet",
"other": "A greeting, thanks, chit-chat, or anything that is not coursework"}},
"course": {"type": "noul", "instructions": "Is this message about one of these courses: ...?",
"criteria": {"true": "It names or clearly concerns one of those courses", "false": "It does not"}}}}
It returns a probability for each route and one for the course question. The decision is plain Python in router_choose(), so the arithmetic stays in code.
4. Setup, step by step
1. Get access. Pick one:
- TypeSafe directly: join the early-access waitlist at typesafe.ai and get an API key. Use backend chat with the base URL they give you (an OpenAI-compatible endpoint).
- Cloudflare Workers AI: create an API token from the Workers AI template (Workers AI - Read and Edit) and note your account id. Use backend cloudflare, model typesafe/jev.
- No Jev access yet: Cloudflare's open Clef model takes the same request. Use backend cloudflare, style path, model @cf/cloudflare/clef-flash.
2. Put the key in the bot's env file (it is already chmod 600). Never in the repo:
echo 'TS03_ROUTER_KEY=<your key>' >> ~/.config/ts03-bot.env
3. Create the config. It starts off:
cp templates/ts03-router.json.example ~/.config/ts03-router.json
nano ~/.config/ts03-router.json # set backend, model, account_id or base_url. Leave "mode": "off"
4. Selftest. One live call with two probe messages. It tries the request styles and tells you which one works:
scripts/ts03-bot router-selftest
You want OK: the cloudflare backend answered with style 'body' and the tracker probe landing on tracker, the lecture probe on professors_sheet. If it prints Set "style": "path", put that in the config. If no style works, paste the lines it printed.
5. Deploy the bot and check it:
./scripts/install-bot.sh whatsapp
scripts/ts03-bot selftest
6. Replay your own history, read-only on the bot. This runs your real logged messages through Jev and compares with where the rules sent them:
scripts/ts03-bot router-eval --limit 40
same means Jev agrees with the bot. DIFF means it would choose differently. ASK means it would ask. A difference is not an error: read each one and decide which route you would have wanted.
7. Shadow mode. Jev is asked and logged but never acted on:
sed -i '' 's/"mode": "off"/"mode": "shadow"/' ~/.config/ts03-router.json
launchctl kickstart -k gui/$(id -u)/com.ts03.bot.whatsapp
After a few days:
scripts/ts03-bot router-status
It shows how many decisions were logged, how many matched the rules, how many Jev would change, how many it would ask, and the most recent differences.
8. Turn it on only when the differences look right:
sed -i '' 's/"mode": "shadow"/"mode": "on"/' ~/.config/ts03-router.json
The bot reads the config on every message, so this takes effect at once. The key is read at start, so restart the bot only if you changed TS03_ROUTER_KEY.
9. Roll back any time: set "mode": "off". No restart.
5. Commands and test messages
| Command | What it does |
|---|---|
scripts/ts03-bot router-status |
config, key present, decisions logged, agreement with the rules, recent differences |
scripts/ts03-bot router-selftest |
one live call, finds the working request style |
scripts/ts03-bot router-ask <message> |
probabilities, the rules' view and the decision for one message, as if the mode were on |
scripts/ts03-bot router-eval [--limit N] |
replay logged messages and compare |
~/.local/bin/ts03-bot works the same over SSH. Test messages for your DM once it is on:
| Send | Goes to |
|---|---|
@bot NLU/NLP InClassActivity2 kaise karna hai? |
the tracker |
@bot NLP lecture or assignment due? |
the tracker (Rule A) |
@bot when is the next NLU lecture? |
the professors' sheet |
@bot who teaches CV? |
the professors' sheet |
@bot is there class on 9 October? |
the bot asks which subject |
@bot explain the concept of perplexity |
/prep study help |
@bot who is the professor for GPU programming? |
the subject list |
@bot tell me about nlp |
the bot asks tracker or course sheet |
@bot thanks |
the old behaviour (tracker fallback) |
Each decision is logged in ~/Library/Logs/ts03-bot.log as router[on]: rules=… jev=…(0.91) next=…(0.05) course=0.97 -> route:… (why) 'message'.
6. Tuning
| Setting | Default | Raise it to | Lower it to |
|---|---|---|---|
need |
0.75 | act less often and ask more | act more often |
lead |
0.25 | require a clearer winner | accept close calls |
tracker_priority |
0.40 | let more mixed messages go to the course sheet | send more mixed messages to the tracker |
course_min |
0.50 | ask for the subject more often | assume the course sooner |
timeout_s |
3.0 | wait longer for Jev | give up sooner and use the rules |
per_minute, per_day |
20, 400 | allow more calls | cap spending |
If your provider offers a pinned model version, put it in model, so an alias upgrade cannot change behaviour under you.
7. Privacy and cost
- What leaves your Mac: only the scrubbed message text, at most 500 characters.
@ids are removed, and no sender, chat or group id is sent. The questions are fixed text. - It is a third party. Today only the Claude sandbox sees classmates' messages. With the router on, TypeSafe or Cloudflare sees them too. Tell the group before you turn it on.
- Cost: about 450 input tokens per message. At the published input price of $0.042 per million tokens that is roughly two cents per thousand messages, and output is free. One guide reports no free tier, so the key needs a funded account. The daily cap bounds the spend.
- The key lives in
~/.config/ts03-bot.env, not in the repo or the router config.
8. Troubleshooting
| Symptom | Fix |
|---|---|
router-selftest: TS03_ROUTER_KEY is not set |
add it to ~/.config/ts03-bot.env. The command line reads that file too |
HTTP 401 |
wrong or unfunded key |
HTTP 404 |
wrong account_id, base_url or model name |
No style worked |
paste the lines above it. The response shape may differ from the documented ones |
log lines router: FAILED, rules used |
Jev errored or timed out. Nothing is shown to the group and the rules answered |
| every message asks "which subject" | course_min too high, or the course names in ts03-schedules.json do not match how people write |
| Jev disagrees with a rule you trust | read router-eval, then raise need or lead, or leave it in shadow |
| the router seems ignored | "mode" is off, or the message started with / |
9. Limits
- Never tested against live Jev by me. The request and response shapes come from the providers' public examples, and the code accepts four response shapes and fails open.
router-selftestis the first real check. - It routes free text only. It never decides commands, owner actions or anything that writes to a sheet.
- A wrong confident answer from Jev is still possible. The tracker-first rule, the course check and shadow mode exist to limit that.
- It does not check for graded-question requests. That stays with the prompt rule and the sandbox's
CLAUDE.md. - Instructors and course names come from the schedule config. Keep it in step with the sheet.
Questions or corrections: [email protected]