tools.scheduled_prompt module

Cron-based scheduled prompt tools (v3)

Schedule prompts to fire at specified times or on cron intervals. Prompt metadata is persisted in Redis. When a prompt comes due it is handed to a runner registered via set_bot_runner (runner.handle_webhook); that legacy hook predates the Phase T3 microservices split and is no longer wired up, so delivery is a no-op unless a runner is supplied.

Module-level tick_scheduled_prompts and cleanup_expired_prompts are used by background_tasks.py and accept a redis client directly.

tools.scheduled_prompt.set_bot_runner(runner)[source]

Store a runner reference used by _execute_prompt to deliver a prompt via runner.handle_webhook.

This hook predates the Phase T3 split into separate gateway, inference, agents, consolidation, and web services. Nothing in the current microservices layout calls it, so _bot_runner normally stays None and _execute_prompt short-circuits with an error until a runner is supplied.

Return type:

None

Parameters:

runner (Any)

async tools.scheduled_prompt.tick_scheduled_prompts(redis)[source]

Scan all scheduled prompts and fire any that have come due.

The polling sweep that complements the per-prompt asyncio timers: it iterates every active/scheduled record and dispatches the ones whose time has arrived, so prompts still fire even if their dedicated timer task was never spawned or was lost (for example across a restart before hydration). Each due delivery is launched fire-and-forget via asyncio.create_task so a slow send does not stall the sweep.

For one-time prompts it compares schedule_time to now and, on firing, flips the record to executed. For cron prompts it uses croniter to find the previous fire boundary and fires when that boundary is newer than the stored last_execution (or, on first run, the created_at time), updating last_execution afterward. Reads via _list_all and persists status changes via _save; all errors are logged and swallowed so one bad record cannot abort the tick.

Called by background_tasks.scheduled_prompt_tick, which the agents service’s periodic scheduler runs roughly once a minute (registered in agents_main.py).

Parameters:

redis – An async Redis client.

Return type:

None

async tools.scheduled_prompt.hydrate_scheduled_prompts(redis, active_platforms, limit=500)[source]

Re-spawn in-memory timer tasks for surviving scheduled prompts.

Recovery routine run at startup: the per-prompt _run_cron / _run_one_time asyncio tasks live only in process memory and are lost on restart, so this walks the persisted index and re-instantiates a timer for each still-pending prompt. Without it, after a restart prompts would only fire via the slower tick_scheduled_prompts polling fallback.

Reads the _INDEX set and each record via _load, skipping prompts that are not active/scheduled, that target a platform not in active_platforms, that already have a live task in _running_tasks, or (for one-time prompts) whose time has already passed. For each eligible prompt it adds the id to _running_tasks and launches _run_cron or _run_one_time via asyncio.create_task. Processing stops once limit prompts have been hydrated. All exceptions are caught and logged.

Called at startup by the agents service wiring (see callers of hydrate_scheduled_prompts); also exercised directly by tests/test_scheduled_prompt_hydration.py.

Parameters:
  • redis – An async Redis client.

  • active_platforms (List[str]) – Platform keys currently served; prompts for other platforms are skipped so timers are not spawned for offline platforms.

  • limit (int) – Maximum number of prompts to hydrate in one pass. Defaults to 500.

Returns:

The number of prompts for which a timer task was re-spawned (0 on an empty index or on error).

Return type:

int

async tools.scheduled_prompt.cleanup_expired_prompts(redis, *, days_to_keep=30)[source]

Purge old executed and cancelled prompts past a retention window.

Retention sweep that keeps the scheduled_prompts namespace from growing unbounded: it deletes terminal records (status executed or cancelled) whose created_at is older than days_to_keep. Active and scheduled prompts are always left untouched, as are records with an unparseable created_at (those are logged and skipped).

Reads candidates via _list_all and removes each match via _delete (which clears both the per-prompt key and its index entry). Errors are caught and reported in the returned JSON rather than raised.

Called by background_tasks.scheduled_prompt_cleanup (which passes days_to_keep=7) on the agents service’s periodic scheduler, and by the cleanup_expired_prompts tool handler _cleanup_expired_tool in this module.

Parameters:
  • redis – An async Redis client.

  • days_to_keep (int) – Age threshold in days; terminal prompts older than this are removed. Defaults to 30.

Returns:

A JSON string – on success {"success": True, "message": ..., "days_kept": int}; on failure {"error": ...}.

Return type:

str