Config Sync

Hot-reload and change detection for zero-downtime configuration updates in Argus MCP.

Config Sync watches the configuration file for changes and automatically reloads backends, middleware, and the tool catalog without restarting the server. This enables zero-downtime configuration updates.

How It Works

Poll-Based Detection

The ConfigWatcher uses os.stat() polling with a configurable interval (default: 2 seconds). When the file's modification time changes:

  1. A debounce window (default: 1 second) opens to collapse rapid saves from editors that perform multiple writes.
  2. After the debounce period, if no further changes are detected, the on_change async callback fires.
  3. The callback triggers ArgusService.reload(), which re-reads the config, reconciles backend connections, and rebuilds the tool catalog.
os.stat(config.yaml)
  ├─ mtime unchanged → sleep → poll again
  └─ mtime changed → debounce (1s) → on_change() → service.reload()

Detection Methods

The current implementation uses mtime comparison. The TUI settings panel shows three options that represent the planned detection spectrum:

MethodDescriptionOverhead
mtimeCompare os.stat().st_mtime (current implementation)Minimal
hashSHA-256 of file contents -- catches changes even if mtime is unreliable (NFS)Low
inotifyOS-level file event notifications (Linux inotify, macOS FSEvents)Near-zero

For most deployments, mtime is sufficient. Hash-based detection is recommended for network file systems. Inotify support would require the watchdog library.

Debounce and Failure Handling

ScenarioBehavior
Rapid successive editsDebounce collapses them -- only one reload fires
Reload callback raises an exceptionError is logged, watcher continues polling
Config file temporarily missingStat returns 0.0 -- treated as "no change"

Configuration

sync:
  enabled: true
  poll_interval: 2.0
  debounce: 1.0
  detection: mtime
  on_failure: backoff

Config Fields

FieldTypeDefaultDescription
enabledbooleantrueEnable or disable config watching
poll_intervalfloat2.0Seconds between file stat checks
debouncefloat1.0Seconds to wait after a change before triggering reload
detectionstring"mtime"Detection method: "mtime", "hash", or "inotify"
on_failurestring"backoff"Failure strategy: "backoff", "fixed", or "stop"

Implementation Status

ComponentFileStatus
ConfigWatcherargus_mcp/config/watcher.pyImplemented -- poll-based async file watcher with debounce
ArgusService integrationargus_mcp/runtime/service.pyImplemented -- watcher started after service reaches RUNNING state
SyncStatusWidget (TUI)argus_mcp/tui/widgets/sync_status.pyUI only -- renders status line + event log table, but no data flows to it yet
SyncConfigPanel (TUI)argus_mcp/tui/widgets/sync_status.pyUI only -- settings form with no persistence
Config schema fields--Not wired -- no sync: section in ArgusConfig yet

Note:

The backend watcher logic is solid and production-ready. Two gaps remain: configuration schema integration and TUI data binding.