cd /news/ai-agents/i-built-an-agent-that-reads-so-i-don… Β· home β€Ί topics β€Ί ai-agents β€Ί article
[ARTICLE Β· art-155689] src=dev.to β†— pub= topic=ai-agents verified=true sentiment=↑ positive

I Built an Agent That Reads So I Don't Have To

A developer built Overnight, a roughly 250-line Python agent that reads files, URLs, or stdin and generates two-sentence briefs per item using a local open-weight GGUF model (Qwen 2.5 1.5B Q4_K_M) via llama-cli or llama-server, writing results to a markdown file. The tool runs nightly on a free Oracle Cloud instance with no vendor SDK and no data sent to an external provider, which the developer says keeps sensitive incident notes and customer tickets on hardware they control.

by read6 min views3 publishedOct 22, 2026

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 3: Slow and Steady

Overnight is a small agent that reads the things I don't want to read, overnight,

and hands me a two-line brief per item in the morning.

You point it at a folder, a single file, a URL, or stdin. It reads every item,

runs an open-weight model on my own machine, and writes a two-sentence brief

per item to a markdown file. I wake up, open one file, I'm caught up.

The effort it saves is attention, not time. I read a lot of things that are three

paragraphs of setup for two sentences of content β€” support tickets, changelogs,

incident reports. Reading them is not hard, it's wasteful. And the timing makes it

worse: nobody wants to open forty tabs at 8am. So the fix isn't a better reader,

it's doing the reading while I'm asleep.

That's the laziness it rewards. Not "I don't want to work" β€” "this task should not

cost me attention."


_2 item(s), local mode, model `qwen2.5-1.5b-instruct-q4_k_m.gguf`_

- **a.txt** β€” The first sentence is here. The second sentence is beyond it.
- **b.txt** β€” The server is up. The team is working.

Three commands cover everything:

python3 overnight.py --watch ~/inbox --out ~/morning-brief.md
python3 overnight.py --url https://example.com/feed --out brief.md
cat notes.txt | python3 overnight.py --out brief.md

That's the whole tool. There is no cleverness in it β€” it's a watcher, a model, and

a file. Which is exactly why it fits "Slow and Steady": it runs every night

without being asked, and it produces the same correct result every time.

Live: https://92.5.41.244:8000/overnight/ β€” paste any text, click the button,

get a two-sentence brief from a local model. Nothing is sent to a provider.

Video: https://github.com/Reggiebro/overnight/releases/download/v1.0.0/demo.mp4

It runs on a free Oracle Cloud instance (8 vCPU / 24 GB) with the model on disk.

It also proves the thing works on hardware that isn't my laptop β€” I had to move it

because my old machine has a firmware thermal trip and was shutting itself down

under CPU load. The agent now lives somewhere it can't cook itself.

The summariser is a GGUF model sitting on disk β€” currently Qwen 2.5 1.5B Q4_K_M.

The harness is about 250 lines of Python with no SDK from any vendor. It talks to

llama-cli as a subprocess, or to llama-server on localhost:8080 when a server

is already running (which keeps the model resident, so a second item costs one

forward pass instead of a full reload).

That open-source core is not decorative β€” it's what makes the project work. Here's

the concrete reason a closed API would have made most of the above impossible:

--model at any GGUF and the pipeline is unchanged. Better model comes out? Drop it in. Want to fine-tune on your own vocabulary? You can, because you own the weights. The last one mattered most to me. A closed model would be a black box that can

change under me without notice. An open one is a file I can inspect.

Because the reading stays mine. That's the whole argument.

I read things that are awkward to hand to a third party: incident notes with

internal hostnames, draft docs that aren't published, tickets with customer names.

With a closed API I'd be choosing between not using the tool and shipping that

text somewhere I don't control. With an open model on disk, there's no third party

to leak to, no account to suspend, and no provider that can change its terms

under me. The tool works on a plane. It costs nothing when I run it every night.

And if the model gets worse, I swap it β€” I'm not waiting for someone else's

roadmap.

Open innovation made the project possible. Closed would have made it a trade-off.

The tool is honest about what it did, and that took more care than the summary

logic.

The output header says local mode only when the model actually produced the

brief. If no model is found, it says extractive mode and takes the first and

last sentence β€” a real compression, not an invention. And if there's genuinely

nothing to summarise, it exits non-zero rather than quietly writing an empty file.

There's a subtler version of the same problem. find_model() searches a few

directories and picks the smallest usable GGUF. If it just returned the first file

it found, a truncated download would be reported as "local mode" while every call

silently fell back to the extractive path β€” the header would be lying. So it probes

each candidate with a real load before returning it, and rejects anything that

doesn't actually load. The header can be trusted because the check is real.

A failed URL fetch is handled the same way: it becomes an item that literally says

[fetch failed: HTTP 502], so a Cloudflare error page never gets summarised into

fake news in your morning brief.

That's the standard I held it to: the tool never claims more than it did.

I'd rather say this than have you find out:

I'm listing these because the interesting part of the project isn't that it

summarises text β€” that's easy. The interesting part is that it does so with

nothing leaving the machine, no account, and no bill, and still tells you

truthfully what happened.

git clone https://github.com/Reggiebro/overnight
cd overnight
python3 -m pytest tests/ -q
python3 overnight.py --watch ~/inbox --out ~/morning-brief.md

The tests are worth a look β€” they cover the claims I made above rather than just

that functions return things. A corrupt GGUF is rejected, a failed fetch becomes

an explicit error, the extractive fallback is deterministic, and the header never

claims local mode without a model. CI runs the same suite on Python 3.10–3.12

and is green.

There's a --json flag if you want to pipe it into something else, and a cron

line in the README if you want it to actually run while you sleep.

I'm entering for Best Use of GitHub Copilot β€” the workflow automation here is

GitHub Actions: the test suite runs automatically on every push across three

Python versions, plus a no-model smoke test that verifies the tool still produces

a correct extractive brief with no model present. That's the category where this

project's automation actually shows.

I've been running it nightly. The payoff is small and specific: I stopped opening

the inbox folder in the morning. I open one file instead of forty tabs, and the

day starts without the "read forty things before coffee" tax.

The tool has no cleverness in it. It's a watcher, a model, and a file. It works

because it runs every night without being asked and produces the same correct

result. Slow and steady: run it every night, trust it in the morning.

── more in #ai-agents 4 stories Β· sorted by recency
── more on @overnight 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain β€” perfect for shipping the agent you just read about.

$git push zahid main
β†’ Live at https://your-agent.zahid.host βœ“
Get free account β†’ Pricing
from €0/mo Β· no card required
LIVE [news/i-built-an-agent-tha…] indexed:0 read:6min 2026-10-22 Β· β€”