Inside folder watchers
Understand event handling, batching and dispatch for file-triggered work.
In this topic
A folder watcher links a filesystem scope to an agent task. The implementation uses filesystem notifications to decide when to inspect the folder, then compares directory state before dispatching work. This distinction matters: an operating-system event is a signal to look, not a complete description of what the agent should do.
For creating a watcher in the app, see Folder watchers. This chapter explains behavior useful when developing or diagnosing the engine.
The execution cycle
- An enabled watcher resolves its selected folder and security-scoped bookmark.
- An FSEvents notification indicates possible activity in that scope.
- A debounce period groups a burst of edits.
- The engine computes a directory fingerprint and compares it with the previous state.
- Meaningful differences are supplied to the configured dispatch path.
- After the run, the engine allows writes to settle and checks the folder again.
- A stable state returns the watcher to idle; further changes can start another pass.
The public phases are idle, debouncing, processing, and settling. A watcher shown as idle can still be enabled and monitoring; idle means it is not currently dispatching a run.
Scope and folder access
The saved watcher contains its identifier, name, instructions, agent or dispatch target, parameters, folder path/bookmark, enabled flag, recursive choice, responsiveness, and timestamps. The bookmark is the mechanism for retaining approved folder access across launches. A remembered path is not equivalent to a usable grant.
The manager caches resolved bookmark paths during an app session to avoid repeated synchronous bookmark resolution for every event batch. Refreshing the watcher set invalidates that cache. If a folder moved or access changed, reselect it through the app and verify the saved watcher again.
Recursive watchers need careful boundaries. The engine accounts for nested watcher scopes so independent watchers do not blindly duplicate work. Keep generated output separate where possible and write instructions that are idempotent: processing the same stable input should not keep producing new differences.
Responsiveness is a workflow choice
The model supports Fast, Balanced, Patient, Relaxed, Deferred, and Extended responsiveness. Select for the producer of the files. A single document save and a bulk export have different settling behavior. Aggressive triggering can inspect an incomplete export, while a longer settling period trades latency for a more complete batch.
| Responsiveness | Current debounce window | Typical input pattern |
|---|---|---|
| Fast | 0.2 seconds | Single file or screenshot |
| Balanced | 1 second | General folder activity |
| Patient | 3 seconds | Download or short batch |
| Relaxed | 60 seconds | Active document editing |
| Deferred | 300 seconds | Longer writing or periodic sync |
| Extended | 600 seconds | End-of-session changes |
These values are debounce windows, not guaranteed task start times. Model loading, approvals, queueing, and settling can add time.
Do not tune a watcher solely by how quickly a notification appears. Check whether the dispatched task received the complete intended file set and whether follow-up writes trigger unnecessary repeats.
Dispatch and continuity
A watcher can retain an agent and a dispatch target. The target determines where the work is routed; the watched folder remains a resource on its host. A remote or cloud destination must not be assumed to see that folder automatically. Inspect the actual context and permissions supplied to the run.
Run records and the last associated conversation let the user inspect what happened after a trigger. A dispatched task is not evidence of a successful action: check the final result, any outstanding approval, and the resulting files.
A useful regression scenario
Create a temporary folder, attach a watcher with an instruction to summarize new filenames, and save several files in a burst. Confirm one coherent dispatch after settling. Then edit an existing file, add a nested folder if recursion is enabled, and pause the watcher before another edit. Verify paused behavior and re-enable it deliberately. Finally relaunch the app and confirm folder access and enabled state persist.
When diagnosing a repeat loop, record the before/after fingerprints and the files changed by the agent itself. When diagnosing silence, check enabled state, resolved folder access, ignored scope, debounce phase, and dispatch errors in that order.
Implementation landmarks: WatcherManager.swift, Models/Watcher/Watcher.swift, and WatcherStore.swift. Source behavior describes the engine; the regression scenario above must still be run against the build being released.