Free AI Opportunity Audit

Running a Company on AI Employees: The Boring Ops That Decide Everything

Shyam Verma
Running a Company on AI Employees: The Boring Ops That Decide Everything

Short answer: If you are deciding how far to trust AI agents in your operations, the question that will actually decide your outcome is not "is the model smart enough?" It is whether your timeouts are set from observed worst-case durations, whether every machine-generated output has a door a human can walk through, whether your own review queue is treated as part of the system, and whether each agent acts under its own identity instead of yours. I have been running a good part of my company on AI agents, and every failure that cost me real money or real data came from that list. None came from the model being dumb.

Here are the incidents, with numbers, because a lessons post without the incidents is just adjectives.

The night my agents lost every saved login

The setup first. I gave my agents their own browsers. Not tabs in my browser — their own logged-in Chrome identities. Each one gets its own cloned Chrome.app (an APFS clone, about 1MB of real disk for a 2.1GB bundle), its own bundle id, its own fixed debugging port, and its own macOS-keychain-backed cookie jar. I tried five alternatives before this — Firefox containers, Arc, Ghost Browser, multi-profile single-window setups — and rejected each on evidence. The rule that survived: the port is the identity. An agent connected to port A is acting as that account and can never silently act as me. There is also a physical-presence gate: creating or renaming an identity requires a human at the terminal.

This is the part of AI operations nobody puts in a demo, and it worked. Agents did real logged-in work — dashboards, consoles, SEO tools — without ever touching my personal browser.

Then one night, one of those identities silently lost every saved login overnight. Google, Stripe, Zoho, LinkedIn, Vercel — gone. No error anywhere. Just a wedged nightly job log.

The root cause is my favorite bug of the year, because no layer of it is an AI problem. Chrome auto-updated. The wrapper re-signed the cloned bundle ad-hoc, which changes its code hash. The macOS keychain entry protecting Chrome's cookie-encryption key was pinned to the old hash. Mismatch, so at 1am the keychain threw a modal permission prompt — to a room with nobody in it. Nobody answered, Chrome couldn't decrypt its cookies, and Chrome's response to cookies it cannot decrypt is to delete them. All of them.

The fix was not "click the prompt." It was signing every bundle with one persistent self-signed certificate, because the keychain ACL binds to identifier-plus-certificate, which survives rebuilds — plus a guard that refuses any unattended rebuild unless the resulting signature is proven identical to the current one. And I verified the mechanism with an actual experiment (sign twice, diff the ACL requirement) before trusting the fix.

The takeaway for anyone building this: an agent that manages its own signed binary will eventually get re-signed by routine maintenance, and that will invalidate an OS-level trust anchor you never knew was coupled to it. The failure mode is silent, and it fires at 1am.

The pattern catalog

The keychain story is the dramatic one. These are the boring ones, which is why they matter more.

41 orphaned browser daemons. A routine "what's using resources" check found 35 orphaned browser-automation daemons on the machine. By the end of the conversation it was 41 — they were accumulating at about six per hour, the oldest was six days old, and together they held 240MB+ of RAM. My first theory (a dangling pointer after a restart) was plausible and wrong. The real answer was in the tool's own --help: it already kills idle daemons after 60 minutes by default, but exempts user-attached browsers — exactly the identity-isolated browsers I had just built. Setting the same 60-minute value as an explicit environment variable removes the exemption. I proved it with a side-by-side test: two identical daemons, one with the explicit timeout, one without.

Then a second discovery: the fix wasn't applying everywhere. Daemons were still surviving, and the reason was two installs of the CLI on the machine — a package-manager copy was shadowing the corrected one on PATH, so every invocation for two days silently ran the old version. A committed fix that is not the code path being executed is indistinguishable from no fix at all. Check which after any CLI upgrade.

The backup job killed nightly by its own timeout. My only off-machine backup had a hardcoded 60-minute timeout. Its successful runs took up to 6.6 hours. So for over a week, the job was SIGTERM'd mid-upload every single night, and the failures looked exactly like Google Drive connectivity flakes. The last good backup was days old before an audit caught it. The fix was one config line: 60 minutes to 480. A timeout set for a job's expected duration instead of its worst observed duration is a recurring kill switch disguised as external flakiness.

A sync job at 200x its schedule. A WhatsApp sync was meant to run 4 times a day. An audit confirmed it had logged 5,631 runs in 7 days — roughly 800 a day against an intended 4. The cause was one schedule string, * 7-21 * * *, written to mean "every 4 hours between 7am and 9pm" and parsed by cron as "every minute, hours 7 through 21." Every individual run was cheap and "succeeded," so nothing alerted. I caught it myself the night before the audit; the audit's job was verifying the fix held and that a downstream cost gate had actually failed closed the whole time (it had). The durable lesson: alert on scheduled-job run counts, not just success/fail. A couple of weeks earlier, a related bug had bitten from the other direction — editing a job's schedule mid-period made the dispatcher's catch-up logic decide the job had been "missed" and re-fire it, rotating a weekly report two days early. Schedulers with backfill logic need reschedules treated as a special case.

Pipelines that ran perfectly and produced nothing. An SMS-signal capture pipeline ran on schedule for 13 months. It read 4,383 messages, whitelisted 2,666, wrote 1,291 database rows. The only SQL SELECT against that table in the entire codebase was the write path's own dedup check. Its Gmail sibling had written 6 rows in 18 days, every one classified "unknown." Both were green in every monitoring view for their entire lives. I cut both — and kept the two adjacent pipelines that an audit proved fed real downstream records. "Runs reliably and writes rows" is not evidence of value. Trace every capture pipeline forward to at least one thing that reads what it wrote.

293 days of useful output nobody could reach. The mirror image. A nightly job generated a genuinely useful daily worklog — committed to git every night for 293 days straight — and I did not know it existed. It had no dashboard route, no nav entry, no documentation. The original design note said it plainly: "machine-consumed by design." A reader was never built. The fix was small: a /worklog page with a date picker, a link from the daily brief, and (while in there) fixing its 10-minute timeout, which was routinely too short for runs that took 24,000 seconds. A silently-successful pipeline with no human-facing surface is functionally identical to a broken one.

Self-improvement blocked on me for 14 days. Two of my automated improvement loops write their own fixes and wait for a human merge. I found both had been sitting blocked for 14–15 days on a single merge/ack action — mine. During that wait, the unmerged fix for a test-database isolation bug let 271 rows of test junk leak into the live audit log. The AI had done its job weeks earlier. "The fix is written" and "the problem is solved" are different milestones, and the queue between them is part of the system whether you manage it or not.

What actually failed, in one table

Incident Looked like Actually was
All logins wiped overnight Mysterious data loss Chrome update → re-sign → keychain ACL mismatch at 1am
Nightly backup failing for a week Google connectivity flakes 60-min timeout on a 6.6-hour job
41 zombie daemons A leak in my code Documented default with an exemption matching my exact setup
Fix not working after shipping The fix was wrong Wrong binary on PATH for two days
Sync at 200x schedule for a week Nothing — every run "succeeded" One cron field, * where a step belonged
13 months of healthy pipeline Working automation Write-only table nothing ever read
293-day worklog Nothing — invisible Useful output with no human-facing door
Stalled improvement loops AI limitation 14 days of unmerged human queue

Not one row is about model intelligence. This holds beyond the recent incidents, too: back in February the most persistent failure in a 10-agent orchestration experiment was agents repeatedly calling the wrong API endpoint, and after documentation fixes didn't stick, the durable fix was consolidating 10 agents into 6 — fewer independently-acting parties, fewer contract mistakes.

The rules I now run on

For an owner-led business or agency deciding how much operational trust to extend to AI, this is my current working set:

  1. Set every timeout from the worst observed duration, not the expected one. Then log durations so "observed" means something. Two of my incidents were timeouts strangling healthy jobs.
  2. Every machine-only output needs a human-facing surface before it ships. A route, a page, a line in a brief that names its source. Otherwise you will pay for it for 293 days and get nothing.
  3. Alert on run counts and output counts, not just success/fail. Success/fail missed a 200x over-firing job and a 13-month write-only pipeline. Counts would have caught both in days.
  4. Your review queue is production infrastructure. If agents wait on your merges, your merge latency is a system metric. Fourteen days of my inattention did more damage than any bug the agents wrote.
  5. Agents get their own identities, their own browsers, their own tabs. Process-level isolation, not tab-level. The port is the identity. And assume the OS will one day break the trust chain underneath you — at 1am, silently.

The intelligence in these systems has stopped being the bottleneck. What decides whether AI employees work is the same thing that always decided whether human ones could: whether the operations around them are boring, observed, and honest about their failure modes. If you want the uncomfortable version — most of what I fixed was my own plumbing.


Shyam Verma founded Ready Bytes in 2009 and has been building software since 2005. He writes about legacy modernization, migrations and applied AI at readybytes.in/blog.

Shyam Verma

Shyam Verma

Full Stack Developer & Founder

Shyam Verma is a seasoned full stack developer and the founder of Ready Bytes Software Labs. With over 13 years of experience in software development, he specializes in building scalable web applications using modern technologies like React, Next.js, Node.js, and cloud platforms. His passion for technology extends beyond coding—he's committed to sharing knowledge through blog posts, mentoring junior developers, and contributing to open-source projects.

Comments