Human-in-the-Loop, Not Hands-Off

I automated job-search triage without automating the decision that carries my name.

Human-in-the-Loop, Not Hands-Off

Applying for jobs at scale is a throughput problem wearing a motivation problem's clothes. There are hundreds of relevant listings on any given week. Each one costs you a few minutes just to read the description, decide whether you're a fit, pick the right résumé variant, and paste the same three answers into yet another screening form. Do it honestly, by hand, and you top out around twenty a day — exhausted, and still missing the good roles buried on page six.

So the temptation is obvious: automate it. And the internet is full of tools that do — one click, hundreds of applications, fully hands-off. I understand the appeal. I also think it's the wrong design, and I want to make the case for the boring middle path I actually built.

The problem isn't judgment. It's triage.

When I looked closely at where my time actually went, almost none of it was judgment. Judgment — "is this role worth my name on it?" — takes seconds once you have the facts. What ate the hours was triage: opening the post, reading past the boilerplate, extracting the salary and location and stack, comparing it to my profile, choosing backend vs. fullstack résumé. Mechanical work. Repetitive. Exactly the kind of thing software is good at.

So I built wb-jobs: a command-line assistant that harvests LinkedIn and Indeed, reads each posting with an AI, scores it 0–100 against my full master résumé, picks the tailored résumé variant, and pre-fills the application. And crucially, if a job scores below my custom threshold (say, an 85/100), the gatekeeper drops it entirely — it doesn't even enter my local database. It turns twenty-a-day of grind into a perfectly curated queue I can review in minutes.

A real wb-jobs harvesting and AI scoring run

Then it stops.

Here's the line I drew, and the whole argument of this piece: wb-jobs fills the application, and then it stops and waits for me. It does not submit. I see what it wrote — the answers, the cover letter, the résumé it chose — and I click the button, or I don't.

That single design decision is the difference between a tool and a nuisance. Mass-blasting applications isn't clever automation; it's spam with a personal brand attached. It's bad for you — recruiters recognize the pattern and discount it — and it's bad for the humans on the other side, who now have three hundred more low-signal applications to wade through. A hands-off bot optimizes a metric (applications sent) that nobody should actually want to maximize.

The human checkpoint keeps the metric honest. What you want isn't more applications; it's more good applications, sent with attention. Automating the triage raises your throughput on the part that doesn't need you. Keeping the submit gate protects the part that does.

The engineering, briefly

Three choices shaped the build, and each one is really an ethics choice in disguise.

Resilience over a single provider. The AI scoring runs as a four-provider waterfall — Groq, then OpenRouter, then Cohere, then Gemini. When one key hits its free-tier ceiling, the next takes over automatically, each call wrapped in a timeout so a hung API can never stall the queue. The practical effect: the tool keeps working on free infrastructure, so it stays accessible, not paywalled.

Local over cloud. Everything runs on your machine. Your job history is a plain SQLite file on disk; your API keys, session cookies, and résumés are git-ignored and never packaged. There is no account, no server, no telemetry. Your job search is nobody's dataset but yours.

The local wb-jobs SQLite metadata

Readable over magic. It's a few hundred lines of TypeScript you can read in an afternoon, with a test suite over the AI response schema and the résumé selector. Nothing about how it scores you is hidden; the prompts are text files you edit.

The same principle I keep arriving at

I've written before about wb-flow, the workflow engine I use to run my open-source monorepo — and the argument there was identical in shape: AI should run at machine speed, but a human has to stay the owner. In wb-flow that means "done" and "valid" are two different checkboxes, flipped by two different steps, because an agent saying it finished is an opinion, not a verdict. In wb-jobs it means the bot prepares, but a person submits.

Different domain, same conviction: the point of automation is to remove toil, not to remove the human from the decisions that carry their name. "Hands-off" sounds like the goal. It isn't. Hands-on-the-decisions, hands-off-the-drudgery — that's the goal.

Use it responsibly

I'll say the honest part plainly, because the tool does. Automating interactions with platforms like LinkedIn and Indeed can conflict with their Terms of Service. wb-jobs is a personal, educational project, built for your own human-in-the-loop search — not for mass, unattended, or commercial use — and it ships with a disclaimer that says exactly that. It isn't affiliated with any platform. You're responsible for how you use it. Building it responsibly and using it responsibly are the same discipline: keep a human in the loop, and don't do at scale what you wouldn't do by hand.

—

wb-jobs is free and open source: github.com/wissemb11/wb-jobs · npmjs.com/package/wb-jobs · wi-bg.com


</div>