# Notice Sloth: an open-weight model reads my university notices so I don't have to

> Source: <https://dev.to/shotaro_takakura/notice-sloth-an-open-weight-model-reads-my-university-notices-so-i-dont-have-to-529a>
> Published: 2026-10-24 11:31:26+00:00

*This is a submission for the [Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady](https://dev.to/challenges/hacktoberfest-week3-2026-10-19)*

Every week my university portal posts a stream of notices: registration windows, cancelled classes, scholarship paperwork, library maintenance, career events. Most of them are not for me. A few of them are, and missing one of those can cost a semester. The only safe strategy is to read everything, which is exactly what a sloth would refuse to do.

This is not a made-up annoyance. My university portal posts about 35 notices a week, and almost every one of them carries a label like 【重要】 (important), 【必読】 (must read) or 【緊急】 (urgent). When everything is marked important, the notices that really are, like a course-registration window or a classroom change, get buried. Earlier this year I had a personal dashboard, KAsmappyⅡ, built on top of the portal partly for this reason. It sorts notices into categories, but categories still don't tell me whether a notice is *for me*. Notice Sloth is a new, separate project that tries to answer that question.

**Notice Sloth** reads them for me. I paste a week of notices (they are in Japanese) and write one short profile of myself, once: year, faculty, which courses I take, that I'm not in the teacher-training course, that I don't have a scholarship. For every notice, Gemma tells me what it is about in one English line and one Japanese line, whether it is actually addressed to me, and what I have to do, by when, and where. Then plain code sorts everything into three piles:

The deadlines in "Do this" become a calendar file with a reminder the day before. Six notices in, one thing to do out.

**Live:** [https://notice-sloth.shotaro-takakura.workers.dev](https://notice-sloth.shotaro-takakura.workers.dev)

Press **Load sample notices (fictional)**, then **Read them for me**.

The sample is six made-up notices written in the style of a Japanese university portal: a course-registration correction window, a teacher-training guidance session for third-years, library maintenance, a scholarship renewal, a cancelled German class and an optional career workshop. With the sample profile (second-year, not in teacher training, no scholarship), a real run took 6.8 seconds and came back like this:

| Notice | Pile | Why | 
|---|---|---|
| Course registration corrections, due Oct 31 17:00 | **Do this** | addressed to all undergraduates, action required | 
| Career workshop, apply by Nov 7 | Good to know | for everyone, but opt-in | 
| Library maintenance, Nov 2 | Good to know | nothing to do | 
| German II cancelled, Oct 27 | Good to know | I take the class, nothing to do | 
| Teacher-training guidance | Not for you | for third-years in teacher training | 
| Scholarship renewal | Not for you | profile says no scholarship | 

The calendar file has exactly one event: "Correct course registrations", Oct 31, with a reminder on Oct 30.

Reads your university notices so you don't have to.

Paste a week of notices from your university portal (Japanese or English). Gemma, Google's open-weight model, reads each one and tells you:

Then plain code sorts everything into **Do this / Good to know / Not for you** and gives you a calendar file (.ics) with a reminder the day before each deadline.

**Live demo:** [https://notice-sloth.shotaro-takakura.workers.dev](https://notice-sloth.shotaro-takakura.workers.dev) — press "Load sample notices (fictional)", then "Read them for me".

Built for the [DEV Hacktoberfest Open-Source AI Challenge, Week 3: Slow and Steady](https://dev.to/challenges/hacktoberfest-week3-2026-10-19).

```
notices ──► split on "---" ──► Gemma (one call per notice, JSON schema) ──► normalise + validate
                                                                                   │
                         .ics
```

…
**The model: Gemma 4.** The hosted demo runs `@cf/google/gemma-4-26b-a4b-it` on Cloudflare Workers AI. The offline CLI runs `gemma4:e2b` on Ollama, which is small enough for an 8 GB laptop. Both go through the same file, `src/core.js`, so there is one prompt, one schema and one set of rules.

**One notice, one call, one JSON schema.** The app splits the paste on `---` lines and sends each notice separately with a short JSON schema: title, English and Japanese summary, the audience as written, `applies_to_me` (`yes` / `no` / `unclear`) with a one-line reason, `action_required`, `action_optional`, and a list of tasks with date, time and place. Short schemas matter with open models: the fewer fields, the fewer ways to drift.

**The model reads; code decides.** Gemma never chooses the pile. It reports what the notice says and who it is for, and a four-line function decides:

```
export function bucketOf(n) {
  if (n.applies_to_me === "no") return "skip";
  if (n.action_required && !n.action_optional && n.tasks.length > 0) return "do";
  return "fyi";
}
```

That made the first mistake easy to fix. In the first version the career workshop landed in "Do this", because applying for it is technically an action. The fix was one boolean in the schema, `action_optional`, and one condition in that function. No prompt tuning.

**Dates are validated, never guessed.** The prompt gives Gemma today's date so it can turn "10月31日（金）17:00" into `2026-10-31` and `17:00`. Code then checks every date and time; February 30th or 25:00 becomes `null` instead of a wrong calendar entry. The .ics writer converts from the browser's time zone to UTC and adds a one-day reminder.

**The bug that ate the tokens.** The first deploy returned nothing for all six notices. The raw response showed why: Gemma 4 thinks before it answers, and on this task it spent the entire 1,200-token budget reasoning and left `content` empty. Extraction doesn't need deliberation, so the Worker now sends `chat_template_kwargs: { enable_thinking: false }` (and the CLI sends `think: false` to Ollama). A short notice now uses about 500 tokens in total, about 8 Workers AI neurons, and the six-notice sample takes 6 to 11 seconds because the notices run in parallel.

**Stack:** a Cloudflare Worker (about 60 lines) and one static HTML page with no framework, so the moving parts are the model and `core.js`. Seven `node --test` tests cover splitting, JSON recovery, date validation, the pile rule and the calendar output.

A note on how this was made: the problem comes from my own university portal, and Claude Code designed, wrote and tested the implementation. Gemma is the only model inside the app itself.

University notices are not public documents. Some name students, some are about scholarships and money, and all of them sit behind a login. With a closed API, the only way to automate reading them is to send all of that to someone else's server.

Because Gemma's weights are open, there is a second option. The CLI runs the same pipeline against Ollama on a local machine, and nothing leaves it. The hosted demo exists so judges can try it in one click; the offline path is the one I would actually point at my real inbox.

I've tried running open models locally on Windows before, but I haven't benchmarked Notice Sloth's offline path yet, so there is no number for it here.

Open weights also mean the model size can be swapped without rewriting anything: the 26B mixture-of-experts version on Workers AI for the demo, the 2B-effective version for an 8 GB laptop. The prompt, the schema and the rules stay the same.

Cost matters too. A sloth doesn't want a monthly bill for being lazy. Running locally is free after the download, and the hosted version is cheap enough to leave online.

On the sample week, there is one card to read instead of six notices. Everything that isn't for me is folded away, and the one deadline goes into the calendar with a reminder.

**Best Use of Gemma**: Gemma 4 is the only model in the project. It runs hosted on Workers AI (`gemma-4-26b-a4b-it`) and locally on Ollama (` gemma4:e2b`) from the same code, and it handles Japanese notices with bilingual summaries.
