This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady
Hi! I'm Chamod, a third-year IT student in Sri Lanka, and I need money for my studies.
The money is out there. There are scholarships, research grants, paid remote internships, and hackathons with real cash prizes. The problem is finding it. Every search turns into twenty tabs, and half of them say "US residents only", or closed last month, or turn out to be a "Top 50 Hackathons of 2026" list that links to another list.
So I did the laziest thing I could think of. I built an agent that hunts for money while I sleep.
What I Built
Lazy Scholar wakes up every night, searches the web for opportunities, and reads every result the way I would. It asks: can I actually apply to this? Is it still open? Is there real money in it?
By morning there's a short digest waiting for me at lazyscholar.tech:
Each match comes with the deadline, the prize or pay, a score out of 100 for how well it fits me, and the reasons behind that score. There's also an application email already drafted for the best match, so the hardest part of applying (starting) is done.
It's built for me, but anyone can fork it, write their own profile, and get their own nightly digest.
Demo
Live: lazyscholar.tech (rebuilt every night)
Code
Lazy Scholar
An agent that hunts for money for my studies while I sleep.
Every night, Lazy Scholar searches the web for scholarships, grants, paid internships and hackathons with prizes. An open-weight Gemma model reads each result against my profile and decides whether I can actually apply. Each morning it publishes a short digest with a drafted application email for the best match.
Live digest: https://lazyscholar.tech
Built for the DEV Hacktoberfest Open-Source AI Challenge, Week 3 "Slow and Steady".
How it works
GitHub Actions, every night (02:00 Sri Lanka time)
β
ββ 1. Search SerpApi runs 6 Google queries search.py
ββ 2. Remember SQLite skips links already judged db.py
ββ 3. Judge Gemma scores each new link β JSON judge.py, llm.py
ββ 4. Digest HTML page + email draft for top match digest.py
ββ 5. Publish GitHub Pages at lazyscholar.tech .github/workflows/nightly.yml
-
Search. SerpApi runs a few Google queries tunedβ¦
How I Built It
Every night at 2 AM Sri Lanka time, GitHub Actions runs five small steps.
1. Search. SerpApi runs six Google searches tuned to me, such as remote AI internships, online hackathons with cash prizes, and scholarships open to Sri Lankan students. I exclude the big job boards, because a page with 50 jobs on it can't be judged as one opportunity.
2. Remember. Every link goes into a small SQLite database with its verdict. If the agent has seen a link before, it skips it. GitHub Actions starts from a clean machine every run, so the database lives on a separate data branch of the repo between nights.
3. Judge. This is where Gemma comes in. For each new link, Gemma 4 (gemma-4-26b-a4b-it) gets my profile, today's date and the search result, and has to answer in JSON:
{"eligible": true, "category": "hackathon", "score": 85,
"deadline": "2026-11-30", "amount": "...", "reasons": ["..."]}
It's stricter than I expected. It turned down an in-person hackathon in the UK because I can't travel, a hackathon whose deadline had passed eleven days earlier, and every "best hackathons" list page.
4. Digest. A plain HTML page with one card per match, sorted by deadline. Gemma also writes the email draft, using placeholders like [your CGPA] instead of my real details, because the page is public.
5. Publish. GitHub Pages, on a free .tech domain.
Not everything worked the first time:
- The first run took 22 minutes. Each Gemma call takes about 17 seconds, and I was judging 49 links one at a time. Now it judges three at once, and since it never judges the same link twice, a normal night takes about three minutes.
- Gemma gave everything a 95. Five matches, five identical scores, which made ranking useless. I added clear score bands to the prompt (90+ only if the fit, the prize and the deadline are all clear), and the next match came back as an 85.
-
"New" matches weren't new. GitHub's servers run on UTC, so at 5 AM in Colombo it was still "yesterday", and old matches kept showing up as new. One line in the workflow,
TZ: Asia/Colombo, fixed it.
I built this with help from Claude Code, an AI coding assistant. It wrote much of the code, and it helped me write this post. I made the decisions, tested every step against real searches, and reviewed each commit before it went in.
Why Does Open Innovation Matter?
My laptop is an M2 MacBook with 8 GB of RAM. It isn't running a 26-billion-parameter model any time soon. So right now Gemma runs on Google AI Studio's free tier.
The important part is that I'm not stuck there. Gemma's weights are open, so the exact same model can run somewhere else, and in Lazy Scholar that's one setting:
MODEL_PROVIDER=google # or: openrouter, ollama
If the free tier changes, I can switch to OpenRouter. If my university gives me access to a GPU, or I get a better laptop one day, I can run the model locally and my profile never leaves my own machine. With a closed model, the API is the product, and if it changes, the project breaks.
For a student with no budget, that's the difference between a project that lasts and one that dies when a free trial ends.
The Lazy Payoff
In its first day, Lazy Scholar read 76 different links and found 7 open opportunities that actually fit me. One is an online AI hackathon whose listing shows a β¬50,000 prize pool, closing November 8.
The whole thing runs on free tiers: six searches a night out of SerpApi's 250 a month, and a few Gemma calls.
Prize Categories
- Gemma: Gemma 4 judges every opportunity and drafts the emails
- SerpApi: powers the nightly search
- .tech domain: lazyscholar.tech
-
GitHub Copilot: the whole agent is automated with GitHub Actions (nightly cron, a
databranch for memory, Pages deploy)
Somewhere out there is a scholarship with my name on it. Lazy Scholar will find it. I'll be asleep.


Top comments (0)