Using launchd to Schedule AI Agent Tasks on macOS
Using launchd to Schedule AI Agent Tasks on macOS
Cron works on Linux. On macOS, launchd is the native scheduler - and it handles things cron cannot, like crash recovery, job overlap prevention, and proper system integration.
Why launchd Over Cron
macOS technically supports cron, but it is a second-class citizen. Cron jobs do not get proper access to the user's GUI session, cannot interact with the Accessibility API, and miss runs if the machine is asleep. launchd handles all of these correctly.
For AI agents that need to interact with desktop apps, read the screen, or use accessibility APIs, launchd is not optional - it is required. A cron job running an agent script will fail silently when it tries to access the screen because it lacks the right session context.
Basic Agent Schedule
A launchd plist for an AI agent that runs every 30 minutes looks straightforward. Place it in ~/Library/LaunchAgents/ with a reverse-DNS name. Set StartInterval to 1800 for 30-minute intervals, or use StartCalendarInterval for specific times.
The key settings for agents are KeepAlive with SuccessfulExit: false for crash recovery - if your agent crashes, launchd restarts it automatically. Set ThrottleInterval to prevent rapid restart loops when something is genuinely broken.
Preventing Job Overlap
AI agent tasks can take unpredictable amounts of time. If your agent is still processing when the next scheduled run triggers, you get two instances fighting over the same resources.
launchd does not natively prevent overlap for interval-based jobs, but the fix is simple: use a lock file. At the start of your agent script, check for a lock file. If it exists, exit. If not, create it and delete it when done. Wrap the deletion in a trap to handle crashes.
Crash Recovery
Set KeepAlive to restart the agent if it exits with a non-zero status. Combine this with ThrottleInterval set to 60 seconds so a persistently crashing agent does not consume all your CPU in a restart loop.
For critical agents, add a StandardErrorPath to capture error output to a log file. When something breaks at 3am, you want to know why without having to reproduce it.
Logging
Point StandardOutPath and StandardErrorPath to files in ~/Library/Logs/ or /tmp/. Include timestamps in your agent's output so you can correlate events across runs. launchd does not rotate logs automatically, so set up periodic cleanup or use a log rotation script.
Fazm is an open source macOS AI agent. Open source on GitHub.