Figment.so
Mac hostingWebsite hostingGuidesHow to usePricing

Restore a Hosted Mac Agent After a Host Reboot

A host reboot is not a rare edge case — it happens after OS patches, kernel updates, and unplanned power events. If your automation agent does not start automatically at login, every reboot means a silent gap in work until someone notices and manually relaunches it. The fix is a correctly configured launchd user agent with verified restart behaviour and a short acceptance test you can run every time.

This guide gives you the exact plist, a phased recovery procedure, and concrete acceptance checks so you can confirm the agent came back cleanly without staring at logs.

Which Figment Plan Fits an Agent Workload

Any Figment Mac can run a launchd user agent that restarts on login — the mechanism is built into macOS. The plan choice affects what the agent can do after it restarts, not whether it restarts. Prices below are entry prices from Figment's Mac hosting page; the physical i3 and M-series plans currently collect configuration requests and the exact hardware is confirmed in the quote.

PlanEntry priceWhat it isBest fit
Virtual Intel macOS$29/mo2 vCPU, 8 GiB RAM, 80 GiB disk; browser-console accessAPI-call agents, git operations, file processing, Shortcuts orchestration
Physical i3 Mac$49/mo (request)Physical Intel MacSame workloads on dedicated Intel hardware
M-series Macfrom $95/mo (request)Apple silicon; exact chip/RAM/disk confirmed in quoteAgents that must execute ARM-only binaries or run Xcode 27
Managed Build Mac$249/moOne M-series Mac, CI setup, backups, monitoring, 30 minutes monthly supportTeams that want Figment to handle setup and post-maintenance verification

The virtual Intel macOS plan is a macOS environment — compatible Intel Xcode 26-or-earlier toolchains run on it (see Apple's porting guide) — so a Python, Node, Shortcuts or bash polling agent will work the same way it would on a physical Mac. Choose M-series if the agent has to execute arm64-only tools or Xcode 27.

For an unattended agent, enable auto-login for the agent user account in System Settings → Users & Groups → Automatic login so launchd user agents load after any reboot without someone logging in.

Anatomy of a Reboot-Safe launchd Plist

The Apple launchd guide and the launchd.plist(5) manual describe three restart patterns. Pick the one that matches how your agent exits:

PatternBehaviourUse when
KeepAlive: trueRestart after every exit, clean or notLong-running process that must never stop
KeepAlive dict with SuccessfulExit: falseRestart only after a non-zero (crash) exitPolling loop that exits 0 when the queue is empty
KeepAlive dict with SuccessfulExit: trueRestart only after a clean exitJob you want to repeat continuously
RunAtLoad: true and no KeepAliveRun once at load, do not restartOne-shot initialisation task

A polling agent that exits 0 when the queue drains should use SuccessfulExit: false: launchd restarts it on crash, and StartInterval schedules the next poll on its own.

<!-- ~/Library/LaunchAgents/com.yourteam.agent.plist -->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
    "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.yourteam.agent</string>

  <key>ProgramArguments</key>
  <array>
    <string>/bin/bash</string>
    <string>/Users/agent/agent-workspace/agent-loop.sh</string>
  </array>

  <!-- Poll every 90 seconds even after a clean exit -->
  <key>StartInterval</key>
  <integer>90</integer>

  <!-- Restart on crash; leave alone on clean exit -->
  <key>KeepAlive</key>
  <dict>
    <key>SuccessfulExit</key>
    <false/>
  </dict>

  <!-- Log both streams for post-reboot diagnosis -->
  <key>StandardOutPath</key>
  <string>/Users/agent/agent-workspace/agent.log</string>
  <key>StandardErrorPath</key>
  <string>/Users/agent/agent-workspace/agent-err.log</string>

  <!-- Run once immediately when loaded (and after each login) -->
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

Apple's guide warns that a job which exits within 10 seconds of launch may be treated as crashing and throttled — by default launchd will not spawn it more than once every 10 seconds. Your agent script should take at least that long to exit on startup; a short health check (DNS, API reachability, Keychain unlock) is a good way to spend that time usefully.

The Recovery Procedure

Run this sequence in order after a reboot. Each phase has one acceptance check so you know it passed before continuing.

Phase 1 — Verify the plist loaded

# Is the agent known to launchd?
launchctl list | grep com.yourteam.agent

Expected output: a row with the label and either 0 (not currently running) or a PID. If the label is missing, reload the plist:

launchctl load ~/Library/LaunchAgents/com.yourteam.agent.plist

Acceptance check 1: the label appears in launchctl list.

Phase 2 — Verify the agent ran after the reboot

# Compare the last boot time to the newest log line
last reboot | head -1
tail -20 ~/agent-workspace/agent.log

The log should show at least one entry timestamped after the reboot. If it is empty or stale, read agent-err.log for a startup error.

Acceptance check 2: at least one log line timestamped after the reboot.

Phase 3 — Verify credentials are usable without a prompt

Keychain items survive a reboot, but they will prompt for access the first time they are retrieved after a reboot if the Keychain is not set to stay unlocked. Set the login Keychain to not auto-lock on timeout or sleep:

# Disable the timeout and sleep auto-lock on the login keychain
security set-keychain-settings ~/Library/Keychains/login.keychain-db

Then confirm the agent can retrieve its secret without a GUI prompt:

security find-generic-password -a "$USER" -s "llm-api-key" -w >/dev/null && echo OK

If this triggers an interactive Keychain unlock, the agent will block unattended after a reboot. Keep the secret in the system Keychain owned by the agent user, or source it from the CI secret manager at job start instead.

Acceptance check 3: security find-generic-password returns with exit code 0 and no GUI prompt.

Phase 4 — Send a canary task

Push one known-good task through your queue and confirm it is processed within two poll intervals:

# After enqueuing the canary, wait 3 minutes then inspect the agent's output
sleep 180
git -C ~/agent-workspace log --oneline -3

Acceptance check 4: the canary commit (or equivalent downstream artefact) appears.

Post-Reboot Failure Checklist

If an acceptance check fails, use this list first:

  • Label missing from launchctl list: plist is not in ~/Library/LaunchAgents/ or is malformed — validate with plutil -lint ~/Library/LaunchAgents/com.yourteam.agent.plist.
  • Log empty after reboot: auto-login is not configured, or the script path moved — verify with ls -la /Users/agent/agent-workspace/agent-loop.sh.
  • Keychain prompts interactively: run security set-keychain-settings without a timeout, and make sure the item's ACL lists the agent binary.
  • Canary not processed: API key expired, deploy key rotated, or the remote endpoint moved — the first line of agent-err.log normally tells you which.
  • Agent throttled by launchd: the script is exiting in under 10 seconds — add a startup health check that takes longer than that.

A Faster Recovery: Watch the Log Instead

Running the acceptance checks by hand after every reboot is fine during setup, but for ongoing operation, watch the log from a second host or a monitoring service. Alert when no new line has been written in more than 2× your StartInterval. That catches both a reboot that launchd did not recover from and a running-but-stalled agent.

# On a monitoring host — alert if agent.log has not been modified in 10 minutes
find ~/agent-workspace/agent.log -mmin +10 -exec \
  curl -s -X POST "$ALERT_WEBHOOK" -d '{"text":"Agent log stale"}' \;

Cost and Plan Decision

The virtual Intel macOS plan is $29/month on Figment's Mac hosting page. It is a monthly charge, not pro-rated by uptime, so keeping an agent online for a partial month still costs the full $29. If your agent only runs Python, Node, bash or Shortcuts, that is the plan to start on.

Move up only when the workload actually needs it: the physical i3 Mac starts at $49/month for dedicated Intel hardware, and M-series plans start at $95/month when the agent has to execute arm64-only binaries or run Xcode 27 (exact chip, RAM and disk are confirmed in the quote). The Managed Build Mac at $249/month includes one M-series Mac, CI setup, backups, monitoring and 30 minutes of monthly support — worth it if you want someone else to re-run these acceptance checks for you after each macOS update.

Start a hosted Mac request · Mac hosting plans

Related: Mac agent API polling · Mac agent large uploads · GitHub Actions self-hosted runner on Mac


Subscribe for Figma design and website publishing guides.


Figment.so

Contact

Twitter

Website pricing

Compute index

About

Privacy

Terms