How to automate recurring operations tasks that nobody owns
On 1 October I approved a LinkedIn post in the morning and went about my day. At 9 PM I asked where it was. It had never gone out. The run that should have posted it fell into a three-hour gap in our scheduler, and the runs around it were missing too. Nobody noticed, because noticing wasn't anybody's job.
Most ops trouble at a small company looks like this. Posting a draft, sending the Monday numbers, chasing a renewal: none of it is hard. The trouble is that a recurring task lives in someone's head, or in nobody's. The first sign it stopped is a person asking "wait, did that happen?"
Step 1: find the work nobody owns
You can't automate a task you haven't named. For one week, keep a plain list of every time someone does a small repeated thing, or asks about one. Write down anything that matches these signals.
- "Who's doing X?" Any question like this in a team thread is an ownerless task.
- Found only when it breaks. The card that expired, the domain that nearly lapsed, the report that didn't go out.
- Done by whoever is nearest. If three different people sent the weekly invoice reminder this quarter, nobody owns it.
Sort what you find by what a miss costs. A monthly renewal check can matter more than a daily one. At a 5 to 15 person startup, the list tends to look like this:
| Task | Cadence | What a miss costs | Needs a human yes? |
|---|---|---|---|
| Weekly metrics into one sheet | Monday morning | A late, guessed number in the team update | No, it only reads |
| Failed payment follow-ups | Weekly | Revenue that quietly churns | Yes, before each email |
| Vendor and tool renewals | Monthly check | Paying a year for a tool nobody uses | Yes, before paying or cancelling |
| Open threads waiting on someone | Daily | A customer or candidate left hanging | No, it only lists |
| Contract and domain expiries | Monthly | Something important lapses | No to remind, yes to renew |
| Access review when someone leaves | On event | An ex-teammate who can still log in | Yes, before removing |
| Heard in the thread this week | Standing job | Trigger | Owner |
|---|---|---|---|
| "Who's sending the Monday numbers?" | Weekly metrics sheet | Monday morning | One named person |
| "Did anyone chase that failed card?" | Failed payment follow-ups | Weekly | One named person |
| "Are we still paying for this tool?" | Vendor renewals check | 1st of the month, 09:00 | The person who signs off on spend |
| "Is anyone replying to this candidate?" | Open threads list | Daily | One named person |
Step 2: write each one as a standing job
A standing job is a recurring task written down well enough that anyone, person or bot, could pick it up cold. We use the same seven fields every time:
| Field | What to write | Example |
|---|---|---|
| Name | Plain words | Vendor renewals check |
| Trigger | A time or an event | 1st of the month, 09:00 |
| Inputs | Where the facts live | The vendor sheet, the card statement |
| Output | What lands, and where | A list in the ops thread, 2 weeks ahead |
| Owner | One person, by name | The person who signs off on spend |
| If missed | Run late, or skip | Run late, the same day |
| Needs a yes | Which actions wait | Paying, cancelling, emailing a vendor |
People skip the "if missed" line. We learned why it matters when our model plan ran out of weekly usage one Saturday and six scheduled jobs didn't run. When the limit reset, some of those jobs were worth running late (the overnight summary) and some were stale (a morning social session at 4 PM). Now every job says which kind it is.
Step 3: make every run leave a trace
A job that fails silently is worse than no job, because everyone stops checking. Before you call a job done, check it against this list:
- It posts something every run, even "nothing to report". A missing post is then a signal.
- A failure shows up as a plain message a person can read in two seconds.
- The owner is a person, and that person sees the output.
- Anything that sends, pays or deletes waits for a yes.
- Once a month, the owner reads the list of jobs and kills the ones nobody reads.
An example: the vendor renewals job, start to finish
The company and numbers in this example are made up to show the shape.
The ask, typed into the ops thread: "keep a sheet of our vendor renewals and tell me 2 weeks before each one".
The same hour, an Excel sheet came back with 14 tools, built from the card statement and the team's email receipts: tool, monthly cost, renewal date, billing cycle, who uses it. A note under it listed three tools nobody had logged into for 60 days, about $310 a month together.
The person who owns spend made three changes:
- Added a column for notice period. Two contracts need 30 days' notice to cancel, so two weeks' warning was too late for those.
- Changed the reminder rule to "notice period plus one week".
- Named themselves as owner, and said cancellations and payments always wait for their yes.
Then they approved the schedule ("1st of every month at 09:00, post upcoming renewals in this thread") and one cancellation email the bot drafted. The email went out only after the click. On months with nothing due, the post says "no renewals in the next 45 days", which is how you know it ran.
keep a sheet of our vendor renewals and tell me 2 weeks before each one
Attached vendor-renewals.xlsx. 14 tools, built from the card statement and email receipts. Three nobody has logged into for 60 days, about $310 a month together. Two contracts need 30 days' notice to cancel.
Remind me notice period plus one week. I own this, and cancellations wait for my yes.
Send 1 cancellation email
ApproveDenyApproved.
An example thread, shortened.
How to set it up in Caret
We run our own standing jobs this way. A bot in Caret has a written job and an owner, keeps memory between conversations, and works in the same threads as the team.
- Create an ops bot and write its job from your list, for example "run the Monday metrics sheet, the monthly renewals check and the daily list of open threads".
- Give it an owner, the person who reads its output.
- Connect only the apps those jobs need. Leave the rest off.
- Add a schedule for each standing job, like "every monday 09:00 put last week's signups, revenue and refunds in a sheet and post it here".
- Write the "if missed" and "needs a yes" lines into the job itself. Before the bot sends, posts, pays or deletes, it asks, and an admin approves or denies with one click.
- Save anything you did once and want repeated as a skill: "save how we did the renewals check today as a skill so you can do it next month".
- Put the bot in your ops thread. It's bridged to Slack both ways, so the output and the approvals land where people already look.
Every bot works on its own computer in Caret Cloud, so a 06:00 job runs with your laptop closed. The computer wakes for the job and sleeps after.
FAQ
What operations tasks should a startup automate first? The ones that cost the most when missed and only need reading: the weekly metrics sheet, renewal reminders, the list of what's waiting on whom. They're low risk, and you'll know within a week whether the output is right.
How do I know an automated job ran? Make it post every time, including "nothing to report", and have failures post as plain messages. Then a quiet thread on Monday morning is the alarm. Otherwise you find out the way we did, when someone asks at 9 PM.
Should an AI bot be allowed to pay invoices on its own? We don't let ours. A bot can get the payment ready and check the amount against the contract. Paying waits for a person's yes, and so do cancelling tools and emailing vendors.
If you're the person running ops and want the whole picture, here's what an ops bot can do for operations. Put a bot on it: start your 7-day trial or download the Mac app.