Using Agents to Operate Self-Made Platforms
Notes from letting Claude Code and similar agents run the systems I've built, not just write their code — where that works, where it breaks, and what it takes to make a platform safe to operate this way.
Most writing about AI agents in software is about code generation: an agent reads a ticket, writes a diff, opens a PR. That's real, but it's not the interesting part of what's changed for me this year. The interesting part is handing agents the operator's job on systems I built myself — kicking off a scrape, checking whether a worker process is actually healthy, deciding whether a batch of imported data looks wrong, restarting a stuck job, walking through a deploy. Work that used to mean me opening a terminal, a dashboard, and a mental checklist.
"Operating" a platform is a different skill than building it, and it's the one most self-hosted, single-maintainer systems are missing entirely — because when you're the only operator, you never had to write the checklist down. An agent can't read your mind. It can only read what you exposed. That gap is the whole subject here.
Operating is not coding
Writing a scraper is a coding task. Deciding that today's scrape returned suspiciously few rows, checking whether that's a real drop in the underlying data or a provider outage, and deciding whether to re-run with a wider window — that's ops. It requires the same judgment a human admin uses: is this expected, is this a known failure mode, is this worth waking someone up for.
The category of work agents can now plausibly do includes:
- Running the system's own jobs — triggering a scrape, an import, a batch job — instead of just writing the code that runs them.
- Triage on the output — reading logs, import warnings, or row counts and deciding if something needs a human, a retry, or nothing.
- Deployment mechanics — checking build status, watching a rollout, deciding whether to promote or roll back.
- First-pass incident response — a worker hasn't reported a heartbeat in ten minutes; is that a crash, a slow job, or a stuck lock? An agent can check all three faster than I can tab between three dashboards.
None of that is novel as a category — it's what a human on-call engineer does. What's new is that it's now economical to have an agent do the first pass on all of it, on infrastructure that never had a team behind it in the first place.
What makes a platform agent-operable
This is the part that actually has to be designed in, and it's mostly the same discipline that makes a system operable by a human on-call rotation — an agent just has zero tolerance for the gaps you used to paper over with tribal knowledge.
Clear, narrow APIs over general-purpose access. An agent operating my review-intelligence tool doesn't get a database connection; it gets a small number of endpoints — trigger a scrape, check run status, list import warnings. The API is the contract for what "operating" means on that system. If an action isn't exposed as an API, the agent can't safely take it, which is a feature, not a limitation — it forces the same scoping decision I'd want a junior engineer to have.
Idempotency, everywhere an agent might act twice. Agents retry. They re-run steps after an ambiguous result, they get interrupted, they misjudge whether a previous action succeeded. If triggering a scrape twice can produce duplicate data, that's a landmine waiting for an agent (or a human, honestly) to step on. On the review-intelligence system, imports upsert on a content hash instead of assuming append-only inserts — the same import can run twice, overlap a previous window, or be retried after a timeout, and the result converges instead of duplicating. That property matters more once an agent is the one deciding when to retry.
Observability an agent can actually consume. A human operator tolerates ambiguous logs because they have context — they remember what normal looks like. An agent doesn't, unless normal is written down somewhere it can read: structured status fields, explicit "warnings" vs. "errors," heartbeats with timestamps, a distinction between "job failed" and "job hasn't reported yet." Free-text logs meant for a human skimming a terminal are a much worse interface for an agent than a status enum and a last_heartbeat_at column.
Rollback and dry-run as first-class operations, not incident-only tools. If undoing an action requires improvising a fix under pressure, an agent shouldn't be the one taking that action unattended. Systems that expose a real dry-run mode, or a rollback that's just another API call rather than a manual database surgery, are the ones where letting an agent operate them doesn't feel reckless.
The tradeoffs are real
None of this makes unattended agent operation free of risk, and I don't think it ever will be for anything with a meaningful blast radius.
Blast radius scales with scope, not intent. An agent with access to "trigger a scrape" has a small blast radius. An agent with access to "run arbitrary SQL against the review database to investigate an anomaly" has a much larger one, even if its intent in the moment is completely reasonable. The fix isn't trusting the agent more or less — it's keeping the tool surface as narrow as the task actually requires, the same principle as least-privilege for a human service account.
Unattended action needs a different bar than assisted action. An agent proposing an action and waiting for me to approve it is a fundamentally safer mode than an agent executing autonomously on a schedule. I treat that as a dial, not a binary: read-only checks and triage run unattended; anything that mutates state outside of tightly scoped idempotent operations gets a human in the loop, at least until the system has enough of a track record that I trust the failure modes are actually covered by the guardrails and not just by luck.
Approval gates only work if they're cheap to use. If getting a human's sign-off on an agent's proposed action takes five minutes of context-switching, people route around it, and the gate becomes theater. The gates that actually hold up are the ones baked into the tool itself — a dry_run: true flag every mutating endpoint respects, a diff-style preview before a destructive call executes — not a separate approval workflow bolted on afterward.
Patterns that hold up in practice
A few concrete things, drawn from building and then operating small systems this way:
- Scope the agent's tool surface to the smallest set of operations that covers the job, and name them after what they do operationally (
trigger_scrape,get_run_status) rather than exposing anything resembling raw infrastructure access. - Log every agent-initiated action with the same audit trail a human action would get — who (or what) triggered it, what parameters, what the result was. When something goes wrong at 2am, the question "did the agent do this, and why did it think that was right" needs an answer that doesn't depend on reconstructing a chat transcript.
- Build dry-run into the operation, not around it. A
dry_runflag that runs the same code path minus the final write is worth more than a separate "simulation mode" that can drift from what actually executes. - Make destructive operations explicit and separately scoped from read/trigger operations, so granting an agent broad visibility into a system never implicitly grants it broad authority over it.
- Treat "agent can operate this" as a property you design for, not a capability that shows up for free once the code is agent-readable. The review-intelligence tool didn't become operable by an agent because an agent got smarter; it became operable because the import layer was already idempotent and the run status was already a queryable field, for reasons that had nothing to do with agents in the first place.
That last point is the actual thesis: the systems that turn out to be easy to hand off to an agent are, almost without exception, the ones I'd already built with reasonable operational hygiene — clear state, safe retries, real audit trails. Agent-operability isn't a separate feature to bolt on. It's what falls out of building the platform properly and then being willing to let something other than you push the buttons.
Related Projects
Software
activeGoogle Review Intelligence
Single-admin internal tool that manually triggers Google review scrapes, imports them idempotently, and turns the result into rating trends, phrase analysis, and formula-safe CSV exports.
Next.js · TypeScript · PostgreSQL · Prisma · pg-boss · DataForSEO · Apify · Docker
Updated 2026-09-23
Infrastructure
experimentalHomelab Bootstrap Scripts
The shell scripts that turn a fresh Ubuntu box into a managed homelab node in one pass — Docker, the Portainer agent, and whatever comes next as the lab grows.
Bash · Docker · Portainer
Updated 2025-05-31
AI / Agents
experimentalHomelab playground: Nous Research Hermes
Nous Research Hermes running in the homelab with terminal-level Proxmox access. It now picks up flaking Docker containers from Beszel monitoring, troubleshoots them, asks for approval over Telegram, and then fixes the root cause instead of just restarting the container.
Nous Research Hermes · Proxmox · Beszel · Telegram · Uptime Kuma · n8n · Docker
Updated 2026-10-23