DEV Community

Cover image for Giving AI Agents a Deterministic Clock (Zero LLM in the Loop)
Yousef Ali
Yousef Ali

Posted on AI-assisted

Giving AI Agents a Deterministic Clock (Zero LLM in the Loop)

When building autonomous AI systems, developers eventually hit a fundamental architectural wall. Your coding agent asks you a question, and you step away from the keyboard. Today, nothing happens. The session hangs, the question rots, and the work stalls.

At J. Servo LLC, we architect enterprise AI systems to operate predictably. We built Sundial to act as the missing half of the human-in-the-loop framework[cite: 1]. It operates on a single defining principle: Sundial measures absence, not time[cite: 1].

When the human becomes the blocker, the agent's clock keeps running[cite: 1]. It nudges you on your desktop, escalates politely through your absence, and greets you with continuity upon your return[cite: 1]. If you never answer, the agent proceeds on its stated judgment or stands down[cite: 1]. It does this deterministically, with zero model calls, and runs 100% locally[cite: 1].

The Flawed Status Quo: LLMs as Cron Jobs

Relying on a Large Language Model to determine if a user has abandoned a session violates lean architecture principles. Time tracking belongs at the system level. The separation of actors is the design[cite: 2].

Sundial enforces a strict architectural boundary across three main components:

  • Sensors: These perform zero-permission OS reads[cite: 2]. They utilize HIDIdleTime, lsappinfo, and pmset on macOS, and xprintidle or loginctl on Linux[cite: 1]. Any missing sensor returns None and softens to wall time rather than blocking the system[cite: 1].
  • The Watcher Daemon: A pure Python loop running via launchd that handles presence classification and escalation[cite: 1, 2]. It uses zero LLMs[cite: 2].
  • The Ledgers: Plain JSON files stored in a git-ignored data/ directory[cite: 2]. State is written atomically using NamedTemporaryFile, fsync(), and os.replace(), serialized by inter-process locking via fcntl.flock[cite: 1].

Core Architecture 1: The Presence-Scaled Absence Ladder

Escalation advances only while you genuinely have not seen the chat[cite: 1]. Sundial categorizes your presence into three strict states:

  • HERE: The chat is visible[cite: 1]. The clock is paused because silence in this state means "not now"[cite: 1].
  • ELSEWHERE: You are in another application[cite: 1]. The clock runs at half speed[cite: 1].
  • AWAY: The workstation is idle[cite: 1]. The clock runs at full speed[cite: 1].

The system enforces urgency tiers[cite: 1]. A high-urgency task utilizes a retimed ladder of 5, 10, and 20 minutes, backed by a hard 40-minute wall ceiling that forces a final resolution regardless of sensor data[cite: 1].

Core Architecture 2: Bounded Breakpoint Delivery

A ripe nudge never fires mid-keystroke[cite: 1]. Drawing from Interruption Science, the daemon holds ripe notifications for up to three minutes waiting for a natural typing gap or application switch before delivering[cite: 1].

Sound courtesy is strictly enforced. Chimes escalate with urgency, but they mute unconditionally if your screen is locked or if you have been away for more than 30 minutes[cite: 1].

Core Architecture 3: Self-Calibrated Task Estimation

Agents must stop guessing execution durations using fabricated calendar weeks[cite: 1]. Sundial tracks the empirical ratio distribution of actual versus estimated time across completed tasks[cite: 1].

The estimation engine (lib/estimator.py) operates purely mathematically to compute empirical P50 and P90 execution durations[cite: 1]. It applies a small-n honesty floor, utilizing a 2.0x multiplier when sample sizes are below five, ensuring the system never provides confident numbers from thin data[cite: 1, 2].

Core Architecture 4: The Autonomy Gate

The trigger path never thinks[cite: 2]. When an agent blocks on an awaiting-reply question, the ladder climbs until expiry, triggering the Autonomy Gate in lib/policy.py[cite: 1].

The agent is forced into a deterministic verdict:

  • REQUIRE_EXPLICIT_YES: The action is flagged as irreversible[cite: 1]. Silence never authorizes it[cite: 1].
  • PROCEED: The action is reversible and confidence is equal to or greater than 0.95[cite: 1].
  • PROCEED (Present-Silence Proven): The action is reversible, confidence is 0.80 to 0.95, and the user sat in front of the chat for at least 30 minutes without objecting[cite: 1].
  • STAND_DOWN: Confidence is below 0.80 or there is insufficient presence proof[cite: 1].

The absolute autonomy rule: Silence-while-present is an answer, whereas silence-while-absent is a void[cite: 1]. They receive distinct, deterministic responses[cite: 1].

Deploy Sundial Today

Sundial integrates via a generic hook protocol passing JSON on stdin and outputting text blocks to stdout[cite: 1]. It supports ready-made adapters for claude-code, hermes, and generic environments[cite: 1].


bash
# Clone the repository
git clone [https://github.com/bigjoe-oti/sundial.git](https://github.com/bigjoe-oti/sundial.git) ~/sundial
cd ~/sundial

# Run the installer for your target platform
./setup.sh --name "YourName" --fresh

Built with obsession by Yousef Ali and the engineering team at J. Servo LLC.
Enter fullscreen mode Exit fullscreen mode

Top comments (0)