This is chapter 7 of my book **Building Autonomous AI Agents with Claude Code* — a field guide to turning Claude Code from a coding assistant into an agent that remembers, verifies its own work, and knows when to stop. Everything below is from a system I actually run every day on one Windows PC.*
1. The Basic Shape of a Pipeline
The minimal setup for scheduled execution is three pieces.
The human's role changes from "running" to "reviewing" — this is the essence of automation.
If you added automation but still have to click something every day, that's not automation, it's a keyboard shortcut.
2. The 3 Big Windows Traps (All Based on Real Incidents)
Trap 1 — Console Window Flashing
If the scheduler runs python or a .bat directly, a black window pops up every few minutes and interrupts your work.
-WindowStyle Hidden still leaves a flash, because it hides the window only after it has been created.
The proper approach is a wscript + .vbs wrapper.
Set shell = CreateObject("WScript.Shell")
rc = shell.Run("""C:\Python312\python.exe"" ""C:\TaskWrappers\run.py""", 0, True)
WScript.Quit rc
The third argument 0 means "no window," and the fourth, True, means "wait until it finishes."
You must include WScript.Quit rc for the scheduler to recognize a failure as a failure. If you leave this out,
the script can fail every single day while the scheduler's history records success.
Trap 2 — Korean Path Encoding
If you register a Korean path in the scheduler through a shell, the encoding can get corrupted as it is saved.
This is the worst kind of failure: registration looks successful, only execution fails.
The proper approach is to split the path chain.
run.py is a launcher of fewer than ten lines. This single layer blocks the entire class of encoding incidents.
import subprocess, sys
sys.stdout.reconfigure(encoding='utf-8')
sys.exit(subprocess.run([sys.executable, "run_collect.py"],
cwd=PROJECT, encoding='utf-8', errors='replace').returncode)
After registering, always verify that the saved content contains no Korean characters.
Trap 3 — Orphan Process Accumulation
When unattended execution fails repeatedly, zombie processes pile up, and one day the whole computer slows down.
This is the number one cause of "my computer suddenly got slow."
import tempfile, time, sys
from pathlib import Path
lock = Path(tempfile.gettempdir()) / "collect.lock"
if lock.exists() and time.time() - lock.stat().st_mtime < 3600:
lock.touch()
try:
main()
finally:
Without the finally, one crash turns it into automation that never runs again.
3. Safety Rules for Unattended Execution
① No silent failures. Do not swallow per-source failures — surface them in the report as a "failures section."
Treat a zero-item collection not as "a successful zero" but as a "suspected structure change" warning.
② Registered ≠ working. After registering the schedule, always run it manually once and check the exit code
and the output artifact. A successful-registration message proves nothing.
schtasks /run /tn MyTask
timeout 60
③ Prevent duplicates with a state file. Record "what has already been seen" so only new items appear each day.
If the report says the same thing every day, people stop reading it — and an unread report is the same as no report.
seen = set(json.loads(SEEN.read_text())) if SEEN.exists() else set()
new = [i for i in items if i["id"] not in seen]
SEEN.write_text(json.dumps(sorted(seen | {i["id"] for i in items})))
4. Deployment Checklist (Follow This As-Is and Incidents Don't Happen)
- [ ] Does running the script standalone produce the output artifact?
- [ ] Is the exit code non-zero on failure? (check with
echo $?) - [ ] Does the vbs wrapper propagate the exit code?
- [ ] Is the path registered in the scheduler free of Korean characters?
- [ ] Did you run it manually once after registering and confirm the output artifact?
- [ ] On failure, does the failure show up in the report? (test by disconnecting the network)
- [ ] Is the duplicate-execution lock released via
finally? - [ ] A few days later, is the process list free of leftovers?
The last two items must be checked a few days later. They never show up on deployment day.
5. How Often Should It Run?
| Interval | Suited for | Caution |
|---|---|---|
| Every 5–15 min | Watching (monitoring), alerts | Orphan processes accumulate fastest here |
| Once daily | Collection, summaries, reports | Most automation belongs here |
| Once weekly | Cleanup, checkups, backups | hooks self-checks go here too |
When in doubt, start with once a day. Short intervals surface problems faster, but they
accumulate side effects at the same speed.
Want the whole system? The book has 10 chapters plus 4 ready-to-use templates (CLAUDE.md starter, memory files, auditor checklist, measurement guide) and a hands-on section for every chapter. It's $19 as a PDF: https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code
Not sure yet? The first three chapters are free, same PDF format: https://dbsoul.gumroad.com/l/autonomous-ai-agents-claude-code-free-sample
Questions about the setup are welcome in the comments — I'll answer with what actually happened, not theory.
Top comments (0)