Skip to main content
Background forks run autonomously, but unchecked notifications would defeat the purpose of an ADHD-friendly bot. The ping budget is a refill-on-read token bucket that limits how many times background forks can ping you, so proactive features stay helpful without becoming noisy.

Overview

The ping budget applies only to background forks. Messages sent in the main session or interactive forks are user-initiated and never counted against the budget. When a background fork calls ping_user or discord_embed, the budget is checked first. If tokens are available, one is consumed and the message goes through. If the budget is exhausted, the tool returns an error to the agent (you are not notified) suggesting it use report_updates to pass findings to the main session instead.
The budget file at ~/.ollim-bot/state/ping_budget.json is ephemeral state — it is written atomically but never committed to git.

How the bucket works

The ping budget uses a refill-on-read model. Tokens are not refilled on a timer — instead, every time the budget state is loaded, elapsed time since the last refill is used to calculate how many tokens have accumulated.
FieldDefaultDescription
capacity5Maximum tokens the bucket can hold
refill_rate_minutes90Minutes to regenerate one token
available5.0Current token count (fractional during refill)
daily_used0Pings consumed today (resets at midnight)
critical_used0Critical pings today (resets at midnight)
A full bucket of 5 tokens with a 90-minute refill rate means up to 5 pings can fire in quick succession, then one more becomes available every 90 minutes, capped at the capacity.

Critical bypass

Both ping_user and discord_embed accept a critical parameter. When critical=True:
  • The ping bypasses all three checks — per-session limit, busy state, and ping budget. It is never blocked (unless allow_ping is false).
  • The critical_used daily counter is incremented for tracking, but no budget token is consumed.
The agent is instructed to reserve critical=True for things you would be devastated to miss — time-sensitive deadlines, health routines, urgent accountability nudges.
The allow_ping: false setting on a background fork overrides everything, including critical=True. When a fork author disables pings, that intent is respected unconditionally.

Busy state

When you are mid-conversation (the agent lock is held), background forks enter a “quiet when busy” mode:
  • Non-critical pings are blocked — the agent receives an error telling it to use report_updates instead
  • Critical pings go through regardless
  • Background forks still run on schedule; only their output delivery is affected
Non-critical pings are checked in this order:
  1. Per-session limit — each background fork is hard-limited to 1 ping (bg_ping_count() >= 1). This is enforced in code, not just advisory.
  2. Busy check — if the user is mid-conversation, the ping is blocked.
  3. Budget check — if no tokens remain, the ping is blocked.
A ping blocked at any stage does not consume a budget token.

Agent awareness

At job-fire time, the background fork preamble injects the current budget status, upcoming schedule, and refill timing. This gives the agent enough context to make informed decisions about whether to ping or report. The preamble instructs the agent to:
  • Send at most 1 ping or embed per background fork (enforced by the per-session limit above)
  • Ask “would the user regret missing this?” before pinging
  • Use report_updates for informational summaries and low-stakes check-ins
  • Save pings for time-sensitive actions, accountability nudges, and health routines
  • When budget is tight, prioritize tasks you would regret missing

/ping-budget command

View or configure the ping budget from Discord.
/ping-budget
Returns the current budget status: available/capacity, refill rate, daily usage, and critical count.

State format

The budget is stored as a single JSON file:
~/.ollim-bot/state/ping_budget.json
{
  "capacity": 5,
  "available": 3.0,
  "refill_rate_minutes": 90,
  "last_refill": "2026-02-24T10:30:00-05:00",
  "critical_used": 0,
  "critical_reset_date": "2026-02-24",
  "daily_used": 2,
  "daily_used_reset": "2026-02-24"
}

Next steps