Scheduling & Background Tasks
Relevant source files
The following files were used as context for generating this wiki page:
Cogmo utilizes an event-driven, durable execution architecture for scheduling and background tasks, primarily powered by Inngest. The system supports both static system-level tasks (like memory extraction and cleanup) and dynamic, agent-initiated scheduled actions (reminders, recurring briefings). By leveraging Inngest, Cogmo ensures that complex workflows are resilient to crashes, support human-in-the-loop approvals, and provide deep observability through step-level traces.
Sources: design/scheduling.md:1-15, CLAUDE.md:73-77
Architecture & Core Orchestration
The orchestration layer is built on Inngest, which allows Cogmo to define functions that trigger on specific events or cron schedules. Each function is composed of durable steps (step.run()), ensuring that if a process crashes during execution, it can resume from the last completed checkpoint.
Component Interaction
The following diagram illustrates how Inngest coordinates between inbound messages, agent logic, and background processing.
This diagram shows the flow from an inbound message through the durable steps of the agent loop, as well as the asynchronous memory extraction triggered by conversation idleness.
Sources: design/scheduling.md:19-54, CLAUDE.md:73-77
Key Orchestration Patterns
| Pattern | Purpose | Implementation Detail |
|---|---|---|
| Durable Loops | Agentic reasoning | Each LLM call and tool execution is wrapped in a step.run() to prevent re-executing expensive operations on retry. |
| Post-Conversation Extraction | Memory evolution | Triggered by conversation/idle, the system sleeps for a debounce period before extracting facts from transcripts. |
| Human-in-the-Loop | Safety/Approval | Uses step.waitForEvent() to pause execution until a user provides a callback (e.g., skill approval). |
| Fan-out Cron | Scalability | A master cron lists items and sends events to per-item handlers, providing independent retry budgets. |
Sources: design/scheduling.md:56-114, CLAUDE.md:103-107
Agent Self-Scheduling
Cogmo provides a primitive for "Scheduled Tasks" that allows the agent to schedule future actions. These tasks are stored in the database and dispatched via a high-frequency ticker. This enables dynamic scheduling (like a user asking for a reminder) without needing to register new static functions at runtime.
Data Model: scheduled_tasks
The scheduled_tasks table tracks the state and timing for all dynamic background tasks.
| Field | Type | Description |
|---|---|---|
kind | Enum | recurring for cron-based tasks or one_off for specific timestamps. |
cron | Text | Standard 5-field cron expression (for recurring tasks only). |
timezone | Text | IANA timezone for accurate cron interpretation. |
prompt | Text | The prompt replayed into the agent loop when the task fires. |
next_run_at | Timestamptz | Computed next occurrence; used by the ticker for polling. |
catchup_missed | Boolean | If true, fires missed occurrences one-at-a-time after an outage. |
Sources: design/scheduling.md:131-150, src/agent/scheduling/scheduling-service.ts:58-75
The Ticker & Fire Loop
The self-scheduling system operates through a two-stage Inngest process:
- Ticker: A static Inngest function runs every minute (
* * * * *). It locks due tasks in the database, advances theirnext_run_atpointers, and fans outagent/scheduled-task.fireevents. - Fire Handler: Processes the fire event by creating a synthetic conversation turn. This turn enters the standard agent pipeline as a
user-rolemessage containing the stored prompt.
Tool Surface for LLM
The agent interacts with the scheduling system via three core tools. These tools are thin adapters around the SchedulingService, which handles validation and database persistence.
Scheduling Tools
schedule_task: Creates a new recurring or one-off task. Rejects 6-field crons (seconds) to enforce a 1-minute minimum interval.list_tasks: Returns a numbered list of all tasks for the user, including enabled/disabled states and prompt previews.remove_task: Permanently cancels a task by its UUID.
Sources: src/agent/scheduling/tools.ts:15-160, src/agent/scheduling/scheduling-service.ts:77-96
Implementation Example: schedule_task
const scheduleTaskSchema = z.object({
schedule: z.discriminatedUnion("kind", [recurringSchema, oneOffSchema]),
prompt: z.string().min(1).max(MAX_PROMPT_LENGTH),
timezone: z.string().optional(),
});
The tool uses Zod schemas to ensure the LLM provides valid cron expressions or ISO timestamps. The MAX_PROMPT_LENGTH is capped at 4000 characters to prevent runaway prompt ballooning.
Sources: src/agent/scheduling/tools.ts:70-85, src/agent/scheduling/scheduling-service.ts:40-45
Validation & Resilience
Cron Interpretation
Cogmo uses croner for cron validation and next-run calculation. The system enforces a standard 5-field format and validates IANA timezones (e.g., Europe/London).
- Spring Forward: If a task lands in a missing hour, it shifts to the next valid instant.
- Fall Back: If an hour is repeated, the task fires only once to prevent duplicates.
Sources: src/agent/scheduling/cron.ts:1-25, design/scheduling.md:204-211
Error Handling
The SchedulingService returns structured SchedulingError objects. These are formatted into human-readable (and LLM-readable) text to allow the agent to self-correct during a tool call.
| Error Kind | Cause | Remediation Message |
|---|---|---|
validation | Malformed cron | "cron expression has X fields, expected 5." |
task_cap_exceeded | Hit task limit | "Remove an unused task before scheduling another." |
invalid_run_at | Past/Bad timestamp | "runAt must be in the future." |
Sources: src/agent/scheduling/scheduling-service.ts:47-56, src/agent/scheduling/tools.ts:173-210
Cogmo's scheduling system provides a robust foundation for proactive agent behavior, ensuring that background tasks are executed reliably while providing the agent with the tools necessary to manage its own future obligations. Re-entering the agent loop via synthetic inbounds allows scheduled tasks to benefit from the same memory and evolution systems as standard user conversations.