AI Agents·8 min read·

When a Script Is Better Than an AI Agent

Choose a cron script over an AI agent when the steps are known, the failure is binary, and a Linux VPS should not spend tokens to restart nginx.

NB

Netbay Developer Relations

Netbay Engineering

On this page

Agents are expensive uncertainty machines. They earn their keep when the next step is not known until you have seen the data. They waste money and add failure modes when the next step is already written in a runbook. Most "we should make an agent for that" tickets on a Linux VPS are scripts with extra latency.

This post is a decision rule, plus the boring script you should ship instead of a diagnose-and-restart bot for a single unit.

The Test: Could You Write the If-Then Today

If you can draw the decision tree on one page without "it depends on vibes", write a script. Examples that should never be agents:

  • Restart nginx if ActiveState is failed.
  • Certbot renew, then reload the proxy.
  • Delete logs older than seven days in one directory.
  • Fail a health check and page a human.
  • Rotate a systemd journal vacuum when disk is above 80 percent.

Those are predicates and argv. A model in the middle can only skip the restart, invent a second restart, or stall on a tool-call parse error. The script will do the same thing on Tuesday at 04:00 that it did in your test.

Agents start to make sense when the tree is wide and the observations are messy: correlating a 502 with a specific upstream, choosing among three likely units, writing a report a human will read. Even then, the write at the end can still be a script the agent is not allowed to skip.

A Script That Replaces a Whole Bot

The following unit-and-timer pair restarts nginx when it is failed and leaves a line in the journal. No API key. No step budget. No summary hallucinating that the unit was fine.

bash
#!/bin/bash
set -euo pipefail
UNIT=nginx.service
STATE=$(systemctl show "$UNIT" --property=ActiveState --value)
STAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
LOG=/var/log/ops-scripts/nginx-watch.log
mkdir -p /var/log/ops-scripts
if [ "$STATE" = "failed" ]; then
  echo "$STAMP $UNIT failed, restarting" >> "$LOG"
  systemctl restart "$UNIT"
  sleep 2
  NEW=$(systemctl show "$UNIT" --property=ActiveState --value)
  echo "$STAMP $UNIT now $NEW" >> "$LOG"
  if [ "$NEW" != "active" ]; then
    echo "$STAMP $UNIT still $NEW, paging" >> "$LOG"
    exit 2
  fi
else
  echo "$STAMP $UNIT $STATE" >> "$LOG"
fi
ini
[Unit]
Description=Restart nginx when failed
After=network.target

[Service]
Type=oneshot
User=root
ExecStart=/usr/local/sbin/nginx-watch.sh
Nice=10

[Install]
WantedBy=multi-user.target

Put a timer next to it with OnCalendar=minutely and Persistent=true if you must poll. Prefer OnFailure= in the nginx unit so you do not poll at all. Polling is already a smell; polling through a model is a more expensive smell.

Idempotency is free here. If the unit is active, the script logs and exits. An agent asked the same question will often "investigate" for six tool calls because the prompt said to be thorough.

Hybrid: Script First, Agent as Escalation

The grown-up design is a script that handles the known tree and an agent that only runs when the script exits non-zero. The agent gets the script log as its first observation. It cannot restart nginx if the script already tried. It can read journalctl and write a report.

That split also keeps eval sane. The script has tests: fake systemctl, assert restart. The agent has golden traces for the messy leftover. Mixing both in one loop is how you get a bot that restarts a healthy unit because the model wanted to be helpful.

Cost is a clue. If a job is on a timer, compute tokens times fires per month before you write a system prompt. A minutely agent at 2k tokens a pop is not an ops strategy. It is a standing wire to your model bill. Intel Xeon Platinum will run the bash forever for nothing; the API will not.

When a vendor demo shows an agent grepping logs, ask whether grep | tail would have been enough. If yes, ship grep. Save the agent for the ticket where two experienced humans would actually disagree about the next command.

Lucknow DC01, High-Speed SSD, L3/L4 DDoS filtering, pay-as-you-go VPS: that is the environment. A timer unit belongs there. A 40-step autonomous intern usually does not.

Script vs agent decision Ship a script Known if-then, binary fail Timer or OnFailure, no API key Same action every Tuesday Consider an agent Next step unknown until data Messy observations, a report Writes still a script Escalation path Script handles the known tree and exits non-zero on leftover mystery Agent reads the script log; it cannot redo the restart

Takeaway

If the if-then already fits in a page, ship a timer and a script. Use an agent only for the leftover mystery, and keep the write path deterministic. You can run that script on an Ubuntu VPS from Netbay in Lucknow in under 60 seconds — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance