InsightWorker Logo
  • contact@verticalserve.com
Docs / Apps & scheduling / Daemon mode

Daemon mode

The scheduler daemon is a long-running process that watches ~/.insightworker/schedules.yaml and fires skills on their cron schedules. Use it for unattended apps: morning digests, periodic data syncs, monitoring, etc.

Not to be confused with --worker mode. The scheduler daemon runs your schedules.yaml on a cron. insightworker --worker is a different daemon that joins an InsightStudio coordinator's farm and runs whatever jobs the Studio UI enqueues. You can run both at once — they're independent processes.

Start the daemon

insightworker --daemon

Runs in the foreground. To background it during a manual session:

nohup insightworker --daemon > ~/.insightworker/daemon.log 2>&1 &

For long-running setups use a system service (launchd / systemd — see below).

List what's loaded

insightworker schedule list

Output:

Schedules: 4 active, 1 paused
  morning-digest      Next: 2026-05-04 09:00 EDT
  hourly-jira-sync    Next: 2026-05-03 14:00 EDT
  daily-sharepoint    Next: 2026-05-04 06:00 EDT
  weekly-report       Next: 2026-05-09 17:00 EDT  [paused]

Stop

The daemon runs in the foreground or as a managed service — there's no explicit stop subcommand. Use the platform's standard control:

# Foreground: Ctrl-C
# Backgrounded: kill the PID
kill $(pgrep -f 'insightworker --daemon')
# launchd: launchctl unload ~/Library/LaunchAgents/com.verticalserve.insightworker.plist
# systemd: systemctl --user stop insightworker

Schedule file

~/.insightworker/schedules.yaml:

schedules:
  - name: morning-digest
    cron: "0 9 * * MON-FRI"
    timezone: America/New_York
    skill: pm-agent-sprint-digest
    args:
      project: PROJ
      recipients: ["pm@example.com"]
    enabled: true

  - name: hourly-jira-sync
    cron: "0 * * * *"
    skill: jira-to-sharepoint-sync
    enabled: true

The daemon hot-reloads this file every 10 seconds — edits take effect without restart. If the file is malformed, the daemon logs the error and keeps the previous valid version active.

Run as a system service

macOS (launchd)

~/Library/LaunchAgents/com.verticalserve.insightworker.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.verticalserve.insightworker</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/insightworker</string>
        <string>--daemon</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>KeepAlive</key>
    <true/>
    <key>StandardOutPath</key>
    <string>/tmp/insightworker.out</string>
    <key>StandardErrorPath</key>
    <string>/tmp/insightworker.err</string>
</dict>
</plist>

Load:

launchctl load ~/Library/LaunchAgents/com.verticalserve.insightworker.plist

Linux (systemd, user mode)

~/.config/systemd/user/insightworker.service:

[Unit]
Description=InsightWorker daemon
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/insightworker --daemon
Restart=on-failure
RestartSec=5

[Install]
WantedBy=default.target

Enable:

systemctl --user daemon-reload
systemctl --user enable insightworker
systemctl --user start insightworker

Linux (systemd, system mode)

For multi-user servers, run as a dedicated insightworker user with ~/.insightworker/ in that user's home. Standard systemd service config under /etc/systemd/system/insightworker.service.

Logs

WhatWhere
Daemon stdout/stderr/tmp/insightworker.{out,err} (launchd) or journalctl --user -u insightworker (systemd)
Per-run transcripts~/.insightworker/sessions/<timestamp>.jsonl
Scheduler events (fires, skips)~/.insightworker/daemon.log

Concurrency

By default, the daemon runs one skill at a time. If a skill is still running when its next fire is due, the second fire is skipped (logged, not queued).

To run skills concurrently:

# ~/.insightworker/schedules.yaml
options:
  max_concurrent: 3   # up to 3 skills running simultaneously

schedules:
  ...

Be careful with concurrent runs that touch the same files — the agent's edit-file tool detects conflicts but the user-defined skill might not.

Failure handling

If a skill fails (any unhandled error or MAX_AGENT_ITERATIONS), the daemon:

  1. Logs the failure to daemon.log with the full transcript path
  2. Sends a notification (if configured — see below)
  3. Continues — does not retry the failed run automatically
  4. The next scheduled fire happens normally

To configure failure notifications:

options:
  on_failure:
    - type: email
      to: oncall@example.com
    - type: slack
      webhook: https://hooks.slack.com/services/...

Auto-approve tools (required for daemon)

In daemon mode there's no human to approve tool calls. Either:

  • Set AUTO_APPROVE_ALL=true (not recommended — too permissive)
  • Set AUTO_APPROVE_TOOLS=... listing every tool your skills need

Any tool call not on the auto-approve list causes the run to fail. See permissions-and-safety/auto-approve-tools.md.

Resource limits

For unattended use, consider:

# ~/.insightworker/.env
MAX_AGENT_ITERATIONS=80           # raise for complex apps
MAX_TOOL_OUTPUT_LENGTH=20000      # cap per-tool output
DAEMON_MEM_LIMIT_MB=2048          # OOM-kill if agent burns memory

See also


Source: docs/workflows-and-scheduling/daemon-mode.md in the public repo. Open a PR with corrections.