Module 21Neill's Vibe · Tier 1 · Ship-First-App Scars~8 min
Why your robot needs the right kind of key
It worked while you watched it. The night it ran alone, its login quietly expired — and it spent hours retrying a door that would never open.
01 · the scene
Fine when I watched it. Dead the moment it ran alone.
The agent ran perfectly in an interactive session. Moved onto a rented server to run on a schedule, unattended — and within days it was stuck in an endless loop of the same rejection.
droplet — unattended cron — Mar 19–22
cron $run agent 401 — token has expired 401 — token has expired(retry) 401 — token has expired(retry… forever, no human to re-auth)
Neill51% · the terrain
"It ran great when I was sitting there. I moved it to a server to run by itself and it just… stopped working a couple days in. Same setup. Why does being unattended change whether the login works?"
Claude49% · the execution
"You were authenticating with an OAuth token — the kind that expires and quietly assumes a human will be there to refresh it. A cron has no human, so the expired token became an infinite 401 loop. For anything unattended, the right credential is a persistent API key. I should've made that call before it ever shipped to the server."
02 · the why
Two kinds of key. One assumes a human; one doesn't.
An OAuth token is built for interactive use: it's short-lived on purpose and expects something to refresh it — usually a person logging back in. An API key is built for machines: it's long-lived and doesn't assume anyone is watching. When you put an unattended job behind an OAuth token, the day it expires there's no human to re-auth, so it just retries the same rejection forever — and a relentless 401 retry storm can even read as abuse to the platform.
⧖
OAuth token
short-lived, human-assumed
Refreshes when a person is present. Perfect for you-at-the-keyboard. Wrong for a lights-out job.
⚷
API key
long-lived, headless
Made for machines. No refresh dance, no assumption that anyone is watching. The right key for a cron.
↻
The 401 loop
silent, then a storm
Expired + no human = retry the same failure endlessly — and the storm can look like abuse.
The model: an OAuth token is a day-pass that the front desk re-stamps when you walk up. An API key is a permanent badge. If you send a robot in overnight with a day-pass, by morning it's standing at a locked door, swiping a stamp that expired hours ago. Send it with the badge.
03 · predict it
Works interactively, dies unattended in a 401 loop. Why?
Same agent, same code. Fine when you run it yourself; a few days into running unattended it's stuck retrying 401 token expired. What's the root cause?
Not it. The code is identical and ran fine interactively. Focus on what's different about authentication when no human is present to refresh it.
Exactly. An OAuth token expires and expects a human to re-auth; an unattended cron has none, so the expired token becomes an endless 401 loop (and that retry storm can even read as abuse). For headless jobs, use a long-lived API key. The credential type, not the code, was the problem.
04 · the walkthrough
Setting a robot up to run alone.
interactive = OAuth ok
step 1When you're at the keyboard, an OAuth login is fine — you refresh it just by being there.
unattended = API key
step 2Before it runs lights-out, switch auth to a persistent API key that won't expire on its own.
cap the retries
step 3Never retry a 401 forever — stop after a few tries so a bad key can't become a storm.
alert on dead auth
step 4Have the job ping you when auth fails repeatedly, so a silent outage doesn't run for days.
05 · prove it · gate
Teach it back to unlock the payoff.
Same rule as always: answer it right, or the module isn't done.
You're about to move a working agent onto a server to run unattended on a schedule. What's the credential decision that keeps it alive?
// one correct answer unlocks Module 21
Not the load-bearing reason. "Works today" isn't the test for an unattended job — think about what happens when the token expires and no one is there to refresh it.
That's it. Headless work needs a credential that doesn't assume a human: a persistent API key. Cap the retries so a dead token can't become a storm, and alert when auth fails. The kind of key matters more than the key being valid right now. Module unlocked. ↓
the durable idea
Match the credential to who's watching. A human-assumed token dies the night no human is there. Unattended work needs a key built for machines.
06 · factory payoff
⊘ locked — pass the teach-back to claim this piece of the factory
The wrapper that won't loop on a dead token.
A real auth-guard.js for any unattended job: it caps retries with backoff, treats a repeated 401 as a hard stop (never an infinite loop), and fires an alert hook when auth dies — the exact failure mode that ran for days unwatched. Plus a go-live checklist for moving a job from your keyboard to a server.