Schedules

Purpose and Scope

Schedules are Flue’s recommended way to admit time-based work into the same durable agent and workflow primitives used elsewhere in an application. The guide frames scheduled work as recurring or delayed business tasks, such as daily summaries, recurring reports, synchronization, or cleanup. The central design choice is not which timer library to use, but whether each occurrence is bounded work or another event in a continuing conversation. Bounded work should become a workflow run; continuing stateful work should become input for a persistent agent instance.

Sources: apps/docs/src/content/docs/guide/schedules.md

Flue deliberately does not provide a universal scheduler abstraction. That decision keeps scheduling tied to the deployment environment, where clock behavior, replica coordination, persistence, time zones, and failure handling are usually decided. Cloudflare applications use Cron Triggers and a scheduled handler. Node applications choose an ecosystem scheduler appropriate for their hosting model. In both cases, Flue starts after the scheduler fires: the application calls the runtime entrypoint that admits the work and lets Flue track the resulting workflow or agent operation.

Sources: apps/docs/src/content/docs/guide/schedules.md

Relevant Source Files

  • apps/docs/src/content/docs/guide/schedules.md — The public schedules guide. It defines when to use workflow invocation versus agent dispatch, gives Cloudflare and Node examples, and describes key runtime expectations such as run admission, run identifiers, UTC cron behavior, and persistent agent session reuse.

Core Primitives

A scheduled workflow occurrence is modeled as a finite operation. The application imports a discovered workflow default export and calls the runtime invocation helper with input describing the scheduled task. The guide emphasizes that every admitted occurrence receives its own run identifier, lifecycle events, and run history. That makes workflow scheduling a good fit for work that should be inspectable as a separate unit, retried or observed independently, and understood as complete after it reaches a result.

Sources: apps/docs/src/content/docs/guide/schedules.md

A scheduled agent input is different. The runtime dispatch helper sends a message to an intentionally continuing agent instance. The stable instance identifier is important because it reuses the same agent instance and conversation, so each scheduled occurrence becomes part of one persistent session rather than a separate workflow history. This is useful only when later occurrences should share memory or context with earlier ones. If a daily summary should stand alone, use a workflow. If a monitoring agent should accumulate context over time, dispatch to the same agent.

Sources: apps/docs/src/content/docs/guide/schedules.md

Scheduling Workflows on Cloudflare

On Cloudflare, scheduling starts in the platform configuration. The guide shows adding a Cron Trigger to a project configuration file so the Worker receives scheduled events at the desired cadence. The example uses a morning cron expression and then implements a scheduled handler in the Cloudflare entry file. Inside that handler, the application imports the workflow and invokes it with a prompt plus a timestamp derived from the scheduled controller. Cron Triggers use UTC, so the schedule should be written with that interpretation in mind.

Sources: apps/docs/src/content/docs/guide/schedules.md

{
  "triggers": {
    "crons": ["0 9 * * *"],
  },
}
import { invoke } from '@flue/runtime';
import dailySummary from './workflows/daily-summary.ts';
 
export default {
  async scheduled(controller: ScheduledController) {
    await invoke(dailySummary, {
      input: {
        prompt: 'Review recent activity and prepare the daily summary.',
        scheduledAt: new Date(controller.scheduledTime).toISOString(),
      },
    });
  },
};

The invocation call is an admission boundary, not a synchronous completion boundary. The guide states that it resolves after the workflow run is admitted and returns a run identifier; it does not wait for the scheduled job to finish. This distinction matters for serverless environments because the scheduler callback should remain small and reliable. The workflow does not need to export an HTTP route for cron use, because the platform calls the scheduled handler directly and the application admits the workflow from there.

Sources: apps/docs/src/content/docs/guide/schedules.md

Scheduling Workflows on Node.js

Node does not include a built-in cron scheduler, so the application must choose a scheduler that matches how it is deployed. The guide’s example uses Croner because it supports asynchronous callbacks, overlap protection, and timezone configuration. The callback is intentionally simple: it invokes the workflow with the same kind of input used on Cloudflare, including a current timestamp. The example also includes an error handler for admission failures, which is useful because failure to admit the run is separate from any later failure inside the workflow itself.

Sources: apps/docs/src/content/docs/guide/schedules.md

import { invoke } from '@flue/runtime';
import { Cron } from 'croner';
import dailySummary from './workflows/daily-summary.ts';
 
new Cron(
  '0 9 * * *',
  {
    protect: true,
    timezone: 'UTC',
    catch: (error) => console.error('Scheduled workflow admission failed', error),
  },
  async () => {
    await invoke(dailySummary, {
      input: {
        prompt: 'Review recent activity and prepare the daily summary.',
        scheduledAt: new Date().toISOString(),
      },
    });
  },
);

For production Node deployments, scheduler durability and replica coordination are application concerns. The guide warns that an in-process scheduler only runs while that process is alive. That is acceptable for simple local services or single-process jobs, but it is not enough when schedules must survive restarts or avoid duplicate admissions across replicas. In those cases, use a persistent scheduler such as BullMQ or another deployment-level system, then keep the Flue side of the integration the same: admit the workflow when the external scheduler says the occurrence is due.

Sources: apps/docs/src/content/docs/guide/schedules.md

Dispatching Scheduled Agent Input

Dispatch scheduled input to an agent only when the schedule represents another event for the same long-lived context. The guide’s example sends a signal-style message with a type, body, and timestamp attributes to a stable agent identifier. That stable identifier is the mechanism that targets the same agent instance every time. The result is a dispatch identifier rather than workflow run history, so readers should not expect separate workflow-style lifecycle records for each occurrence. The tradeoff is continuity: the agent can build on its existing conversation.

Sources: apps/docs/src/content/docs/guide/schedules.md

import { dispatch } from '@flue/runtime';
import dailySummary from './agents/daily-summary.ts';
 
await dispatch(dailySummary, {
  id: 'daily-summary',
  message: {
    kind: 'signal',
    type: 'schedule',
    body: 'Review recent activity and prepare the daily summary.',
    attributes: { scheduledAt: new Date().toISOString() },
  },
});

Implementation Guidance and Next Steps

A practical scheduling design starts by naming the lifetime of the work. If the task has a clear beginning and end, define it as a workflow and let each occurrence produce its own run identifier, events, and history. If the task is an input to an agent that should remember earlier occurrences, dispatch to a stable agent instance. Then choose the scheduler from the target platform: Cloudflare Cron Triggers for Workers, or a Node scheduler with the durability properties your deployment requires. Keep scheduled callbacks focused on admission so the durable Flue primitive owns the work.

Sources: apps/docs/src/content/docs/guide/schedules.md

Next, read the workflow guide when defining finite scheduled operations, the agent guide when building a continuing scheduled worker, and the Cloudflare or Node target material when deciding where the scheduler should live. For production systems, also review durable execution and database persistence so accepted work, conversation state, and run history have the recovery guarantees your schedule requires.