Most writing about AI automation describes something a person did once. This post describes things that ran last night, will run tonight, and will run when I am asleep or on a plane. That difference is the whole subject. A prompt you type is a tool. A job on a schedule is a system, and a system needs a kill switch, a test, a budget, and an owner.
The inventory below is real. It runs on one small virtual server, a Mac with scheduled jobs, and a handful of repositories. Nothing here needs a platform team. Most of it is Python from the standard library, cron, and a language model called a few times a day. I am publishing the list because people keep asking me what to automate first, and the honest answer is that the useful automations are duller than the demos.
The question is never "can an agent do this?" It is "what happens at 3 a.m. when it does this wrong, and who finds out?"
Why the server, not the laptop
The first decision that mattered had nothing to do with models. I moved every scheduled job off my Mac and onto a small cloud server. A laptop is the wrong host for automation: it sleeps, it travels, it needs screen unlock for permissions, and its disk is synchronised by a file-sync client that will happily corrupt a repository being written by a background process. The server is inexpensive and never sleeps. It has its own credentials. Jobs that need my physical machine — the ones that drive a logged-in browser session — stayed on the Mac, and those are the exceptions that prove the rule.
The second decision was that the repository, not the folder, is canonical. My automation code used to live in a synced cloud folder. Two copies drifted, both were edited, and neither was authoritative. Now the server holds the working copy, commits and pushes daily, and every other machine pulls. The old folder was archived as a tarball with a date in the filename and is never edited again.
The inventory
1. A nightly worker that turns issues into pull requests
Every night at 2 a.m. an agent wakes up, reads my issue tracker, picks the low-priority items labelled for automation, and works them into pull requests. It never pushes to the main branch. That constraint is the whole design: the agent may write code, but a human merges. The output arrives as a diff I can read over coffee, and the ones I do not like get closed with no cost beyond the tokens.
The transferable idea: give the agent a queue it does not control and an output boundary it cannot cross. The queue is the backlog. The boundary is the pull request.
2. A code reviewer that reads what actually runs
A nightly job builds a census of every script the server truly executes. It reads the crontab and the service manager, follows one level of references from those entry points, and ranks files by how often they are on a live path. A second file records, per script, the last commit that was reviewed. A script needs review when it has commits newer than its last review. Priority is usage rank times staleness. The job reviews at most three files a night with one model call each and a fixed rubric: correctness bugs, unhandled failure paths, quoting and parsing hazards.
It fixes only what it can prove. Where a file has a mechanical verifier — a syntax check, a nearby self-test, a dry-run mode — the job generates a minimal patch, applies it to a backup-protected copy, and runs the verifier. Pass, and it commits and closes the issue. Fail, and it reverts and files the finding instead, tagged as attempted. Everything else becomes an issue for the nightly worker or for me. The transferable idea is attention allocation. You cannot review everything, and a language model reviewing random files is a waste. Rank by what runs, then by what changed.
Review What Actually Runs sets out the census, the priority formula, the rubric, and the revert test in full.
3. A monthly security check with no model in it
Once a month a script checks five things: that credential files are readable only by their owner, that no secret-shaped string has entered the repository in the last month of commits, that every listening network port is on an allowlist, that the authenticated pages are still authenticated, and how many security updates are pending. It reports the file and line of a suspected secret and never the value.
The six checks, the redaction rule, and why SKIPPED is a first-class result are in A Security Check With No Model In It.
Two design choices are worth copying. First, zero model calls — every one of these checks is a regular expression or a system command, so it is free, fast, and deterministic. Second, monthly, not daily. The checks are stable, and the real failure mode of a security job is alert fatigue. A monthly report gets read. A daily one gets filtered into a folder.
4. A weekly chronicler that turns exhaust into a record
On Sunday evening a job collects the week's operational exhaust — commits, run logs, memos — and writes it into a durable record, then nominates the handful of items worth turning into writing later. It never publishes anything.
The clever part is capture, not synthesis. I can put a [chronicle] marker in any commit message, and a one-line command appends a note to a file from anywhere. Tagging happens at the moment something interesting occurs, which costs two seconds. Synthesis happens weekly, when I would otherwise have forgotten. Almost everyone gets this backwards and tries to remember on Friday what Tuesday was about.
5. An orchestrator that proposes work in three tiers
A daemon watches for signals — stale logs, open items in a citation file, issues waiting for an agent, escalations from other jobs — scores them, and proposes small bounded projects. Then it sorts each proposal into one of three tiers.
| Tier | Policy | Test that puts work here |
|---|---|---|
| A | Run it automatically | A cheap mechanical check can prove the result — a test, an exit code, a diff. |
| B | Open an issue and send one message to my phone | A human must judge whether it is right. No mechanical check exists. |
| C | Never | Publishing, sending mail, touching secrets, deleting things. |
This tier test is the single most useful thing in this post. "Is there a cheap mechanical check that proves this worked?" answers the autonomy question for almost any task. If yes, let it run. If no, the agent's job is to prepare the decision, not to make it.
The loop, the caps, the done rule, and the reason Tier C is an absence rather than a deny-list are in The Mechanical Check Test.
6. A relationship database that starts as a read-only report
A local database links the people in my directory to their email addresses, phone numbers, and professional-network profiles, and to the threads I have actually had with them. It refreshes daily in the morning.
The first version did exactly one thing: print how much of the directory has a linked contact channel, and where the gaps are. Read-only, no network writes, safe to run a hundred times. Everything else was built on top of that after it had been correct for a week. Ship the read-only report first. It is the cheapest way to find out that your data is worse than you thought, and it is the version you can leave running while you lose interest.
The phase gates, the acceptance tests written as prohibitions, and the one-in-three rejection rate that killed automatic matching are in Ship the Read-Only Report First.
7. A monitor for absence, not events
A scheduled job flags email threads that have gone quiet — messages I received, did not answer, and have now aged past a threshold. Most alerting watches for things that happen. The expensive failures in a personal system are things that stopped happening: the reply you never sent, the job that silently stopped running, the invoice nobody chased. Watching for absence is harder to build and worth more.
8. An offline mirror of the system of record
My notes and databases live in a hosted tool. A job periodically mirrors the whole workspace into plain markdown files on disk — around a thousand pages across a few dozen databases. Agents read the mirror for cheap context without hammering an API.
One rule keeps this honest, and I wrote it down after being burned: the mirror is a snapshot, not the truth. When currency matters, the job goes to the live API. A stale mirror that looks authoritative is worse than no mirror.
9. The phone as the approval surface
Every job that needs a human decision sends one line to a private chat channel on my phone, with the context and the options. I answer there. The same channel lets me drive the whole system from anywhere — it is a chat bridge to a coding agent on the server, restricted to my account only.
Put the decision where the human already is. An approval queue on a dashboard nobody opens is not an approval queue; it is a backlog.
10. A public page with expiry built into the data
My public profile carries a list of opportunities I am circulating for other people. Each entry in a small data file has a deadline. A daily scheduled action re-renders the page and drops anything past its date. I add an entry and forget it; the system forgets it too, on time.
Expiry in the data is the cheapest maintenance strategy that exists. Anything you publish that has a natural end date should carry that date in its record, and something should act on it without you.
11. Automatic failover between model providers
A small daemon watches my usage against my subscription's rate window. At 80 percent it routes traffic through a metered alternative provider, and when the window resets it switches back to the subscription automatically. I packaged this one and put it on the public package index, because the problem is not personal: anyone running agents on a subscription hits the same wall mid-task.
The general pattern is graceful degradation. Your automation should have a worse but working mode, and enter it by itself.
12. A publishing gate that blocks my own agents
Nothing reaches this site until two artifacts exist: a grounding brief that maps every load-bearing claim to a source someone actually checked, and a recorded score from a detector that flags machine-sounding prose. The checklist is appended to the brief with dates. No checklist, no publication.
If you let agents write in your name, the quality gate must be mechanical and must sit in front of the publish step, not in your good intentions afterwards.
13. Heartbeats and backups that prove themselves
A heartbeat job reports that each machine is alive. A backup bridge copies what matters off the machine that holds it. Both are dull. Both have caught real failures. The heartbeat has also produced false alarms, which is its own lesson, below.
14. A weekly routine that improves the routines
One job's only purpose is to look at the other jobs — their logs, their escalations, their skipped runs — and propose changes to them. It is the meta-level, and it earns its place because a fleet of fourteen scheduled jobs develops problems that no single job can see: two of them fighting over the same file, one silently skipping every run since a refactor, three sending nearly identical notifications.
Eight rules that make unsupervised running safe
These rules are not theory. Each one was written after something went wrong, and they now bind every scheduled job I add.
- Observe and propose, never act. A job reads, analyses, and files findings. It does not edit code outside its own directory, does not send outward communication, and does not spend money. Fixes flow through the issue tracker, where a human or the nightly worker picks them up.
- Exactly two kinds of output. An issue and a report. Capped at five new issues per run, with a duplicate search before filing. A job that can produce arbitrary output produces noise, and noise is how you stop reading your own system.
- A kill switch that is one file. A file named
STOPPEDin the job's directory makes every entry point exit immediately and successfully. No flags, no config, no redeploy. When something is misbehaving at midnight you want one command. - A self-test that must pass before any schedule is installed. Hermetic: no model calls, no network writes. If it cannot prove itself in a sandbox, it does not get a cron line.
- Idempotent installers, under a lock. Several jobs install their own schedules. Unlocked read-modify-write on a shared crontab loses entries, and it will lose them quietly. Take a file lock.
- No model call where parsing suffices. The infrastructure checks have zero model calls. The jobs that do use one name their model, carry a per-run cost cap, and log what the run actually cost. Cost discipline is a design property, not a monthly surprise.
- Never stage everything. Committing with a blanket "add all" is the single most dangerous line in an automated repository, because other jobs keep the working tree dirty. Each job commits only its own paths, rebases before pushing, retries once, then stops and logs.
- Enumerate state against signal. Every job carries a short table of failure modes. A signal arriving in a state nobody enumerated is how the first half-dozen bugs in my system happened — the message that came during quiet hours, the directive that arrived while the queue was empty, the heartbeat that fired during a reboot.
Four ways it broke
An inventory without failures is marketing. These are the four that changed the rules.
A refactor deleted the scripts a running loop depended on. The loop did not stop. It crash-looped for about seven hours overnight, burning budget and filling logs. Nothing checked that the thing it was about to run still existed. The fix was not a better loop; it was a pre-flight existence check and a crash-loop counter that trips the kill switch.
A scheduler starved its own priority work. Items I had explicitly marked as directives kept losing to routine scoring, so the urgent work never ran. The fix was an additive priority boost rather than a multiplicative one, and a manual override that ignores quiet hours — in both the gate that checks the schedule and the gate that checks the cycle. I had fixed only one of those two gates the first time, which is a very ordinary way to ship a half-fix.
A draft went live because a static host has no staging. I published to a static site host and assumed an unlisted page was a private page. It is not: anyone with the URL sees it, and a catalogue link makes the URL public. An emergency takedown followed, and now a continuous-integration check fails any push that puts a hidden page in the published directory. Drafts live behind a gate, in a different directory, and the check is not allowed to be weakened — only the content gets moved.
A network change caused a fleet of false alarms. A routing redirect I had added for convenience began intercepting connections and hanging them. Every remote check timed out, and my monitoring cheerfully reported that half my machines were down. They were fine for 42 hours while I was told they were not. The redirect is gone, with a note explaining why it must not come back. False negatives make you miss outages; false positives make you stop believing your monitors, which is worse.
What to build first
If you want to start, the order matters more than the tooling. Build these three, in this sequence.
- One read-only report, on a schedule, delivered where you already look. Coverage gaps in your contacts, unanswered messages older than a week, subscriptions renewing next month. No writes. It will be wrong at first, and finding out is the point.
- One queue with a boundary. A list of small tasks the agent may work on, and a place it must stop — a pull request, a draft, an item in an inbox. Never let the first automation both decide and act.
- One deterministic check, monthly. Permissions, expiries, backups, listening ports. No model. It is the job that will still be correct in a year, when the fashionable parts have been rewritten twice.
Then apply the tier test to everything else you are tempted to automate. If a cheap mechanical check can prove the result, let it run unattended. If not, the job is to prepare your decision and put it on your phone. Almost every bad automation I have built violated that one line, and almost every good one respects it.
Four of these in depth
Each of the following takes one item above and gives it the detail a reader would need to build their own version — the algorithm, the caps, the failure-mode table, and the tests.
- The Mechanical Check Test — the three-tier autonomy rule, the scoring caps, the done rule, and why "never publish" is implemented as a missing capability rather than a blocked one.
- Review What Actually Runs — building a census of executed code, ranking review by usage times staleness, the six-item rubric, the failure-scenario rule, and proving the auto-fix revert before scheduling it.
- A Security Check With No Model In It — six deterministic checks, why monthly beats daily, read-only always, and testing that an output does not contain a secret.
- Ship the Read-Only Report First — phase gates with acceptance tests as prohibitions, deterministic-only linking with human review, provenance in the schema, and verifying a history purge from a fresh clone.
This piece describes systems the author runs personally. Details of client, employer, and pre-publication work are deliberately excluded.