Triggers & Scheduler
Relevant source files
The following files were used as context for generating this wiki page:
The Triggers & Scheduler system in OpenPoke provides a robust mechanism for managing delayed and recurring tasks. It allows execution agents to schedule reminders or automated actions by defining a "payload" (instruction text) to be executed at specific times or based on iCalendar recurrence rules (RRULEs). The system ensures that these tasks are persisted and reliably executed by background processes, even if the primary interaction loop is inactive.
Sources: server/services/triggers/service.py:1-25, server/services/trigger_scheduler.py:1-15, README.md:10-15
System Architecture
The trigger system follows a layered architecture consisting of a persistent storage layer, a business logic service, and a background polling scheduler.
Core Components
| Component | Description |
|---|---|
| TriggerStore | Handles low-level SQLite persistence, including table creation and raw SQL queries for fetching due triggers. |
| TriggerService | Provides high-level management logic, including timezone resolution, RRULE parsing, and scheduling next occurrences. |
| TriggerScheduler | A background loop that polls the store for due triggers and dispatches them to the ExecutionBatchManager. |
| Trigger Tools | Agent-facing functions (createTrigger, updateTrigger, listTriggers) that allow LLMs to interact with the service. |
Sources: server/services/triggers/store.py:11-20, server/services/triggers/service.py:28-40, server/services/trigger_scheduler.py:30-45, server/agents/execution_agent/tools/triggers.py:15-80
Data Flow for Trigger Creation
When an agent creates a trigger, the system calculates the initial firing time based on the provided start_time and recurrence_rule. The result is stored in an SQLite database.
Trigger Lifecycle & Management
Execution Workflow
The TriggerScheduler runs an asynchronous loop, typically polling every 10 seconds. When a trigger's next_trigger timestamp is less than or equal to the current time, it is marked as "in-flight" and dispatched for execution.
Recurrence and Scheduling
The system supports complex schedules using iCalendar RRULE strings.
- Immediate Firing: If a
start_timeis provided in the past without a recurrence rule, the system logs a warning and fires immediately. - Grace Period: A
MISSED_TRIGGER_GRACE_PERIODof 5 minutes is used to determine if a missed trigger should be recomputed or executed immediately when a paused trigger is resumed. - Completion: Triggers without a
recurrence_ruleare marked ascompletedafter a single successful execution.
Sources: server/services/triggers/service.py:25, server/services/triggers/service.py:120-135, server/services/triggers/service.py:210-225
Database Schema
Triggers are persisted in an SQLite table named triggers.
| Field | Type | Description |
|---|---|---|
id | INTEGER | Primary Key (Autoincrement). |
agent_name | TEXT | Name of the agent assigned to handle the trigger payload. |
payload | TEXT | The instruction set to be executed. |
start_time | TEXT | ISO 8601 timestamp for the initial start. |
next_trigger | TEXT | ISO 8601 timestamp for the next scheduled firing. |
recurrence_rule | TEXT | Optional iCalendar RRULE string. |
status | TEXT | Current state: active, paused, or completed. |
last_error | TEXT | Stores the error message if the last execution failed. |
Sources: server/services/triggers/store.py:38-52
Agent Tool Integration
Execution agents access the trigger system through specific tool definitions. Agents are instructed to convert natural-language time descriptions into explicit ISO 8601 timestamps and RRULE strings.
Tools Registry
createTrigger(payload, recurrence_rule, start_time, status): Stores a new reminder.updateTrigger(trigger_id, status, ...): Modifies or cancels (viastatus="paused") a trigger.listTriggers(): Returns all triggers owned by the specific agent.
Sources: server/agents/execution_agent/tools/triggers.py:18-70, server/agents/execution_agent/system_prompt.md:52-60
Implementation Details
Instruction Formatting
When the scheduler dispatches a trigger, it wraps the raw payload in a metadata block to provide context to the execution agent.
# From server/services/trigger_scheduler.py:145-155
def _format_instructions(self, trigger: TriggerRecord, fired_at: datetime) -> str:
return (
f"Trigger fired at {_isoformat(fired_at)} (UTC).\n"
f"Scheduled occurrence time: {trigger.next_trigger}.\n\n"
f"Metadata:\n- Trigger ID: {trigger.id}\n- Timezone: {trigger.timezone}\n\n"
f"Payload:\n{trigger.payload}"
)
Sources: server/services/trigger_scheduler.py:141-158
Error Handling
If an execution fails, the system records the failure in the last_error field. For recurring triggers, the system will still attempt to schedule the next occurrence based on the original rule, preventing a single failure from breaking a permanent schedule.
Sources: server/services/trigger_scheduler.py:126-140, server/services/triggers/service.py:187-195
The Triggers & Scheduler system is a critical component for OpenPoke's ability to act as a proactive assistant, enabling long-running workflows and automated follow-ups that extend beyond immediate user interactions.