# How to Implement Recurring Jobs with cron-parser in Agent-Native

> Learn how to implement recurring jobs with cron-parser in Agent-Native. Discover functions to validate, describe, and schedule cron-based jobs within the framework.

- Repository: [Builder.io/agent-native](https://github.com/BuilderIO/agent-native)
- Tags: how-to-guide
- Published: 2026-06-28

---

**Agent-Native provides a lightweight wrapper around the `cron-parser` library in [`packages/core/src/jobs/cron.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/jobs/cron.ts) that exposes three pure functions—`nextOccurrence`, `isValidCron`, and `describeCron`—to validate, describe, and schedule cron-based recurring jobs within the framework's job queue system.**

BuilderIO/agent-native includes a robust job scheduling system that leverages the `cron-parser` library for recurring task execution. The framework provides pure utility functions in [`packages/core/src/jobs/cron.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/jobs/cron.ts) that handle cron expression parsing, validation, and human-readable description generation, allowing developers to implement recurring jobs safely without side effects.

## Understanding the Cron Utilities in Agent-Native

The cron wrapper exports three pure functions that form the foundation of recurring job handling in Agent-Native.

### Core Functions Overview

The wrapper in [`packages/core/src/jobs/cron.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/jobs/cron.ts) provides:

- **`nextOccurrence(cronExpr, after?)`**: Returns a `Date` object representing the next execution time for a given cron expression, optionally calculated after a specific date
- **`isValidCron(cronExpr)`**: Validates whether a cron expression is parseable by attempting to parse it within a try-catch block
- **`describeCron(cronExpr)`**: Generates human-readable descriptions like "Every weekday at 9 AM" by normalizing and analyzing the expression's fields

These utilities are completely side-effect free and covered by comprehensive unit tests in [`packages/core/src/jobs/cron.spec.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/jobs/cron.spec.ts).

## Creating Recurring Jobs in Agent-Native

Recurring jobs in Agent-Native are stored in the `jobs` table within the core SQL schema. Each record contains the cron expression, target action name, payload, and computed `nextRunAt` timestamp.

### Validating and Describing Cron Expressions

Before persisting a job, use `isValidCron` to validate the expression and `describeCron` to generate a user-friendly description for admin interfaces:

```typescript
// src/actions/recurring.ts
import { defineAction } from '@agent-native/core/actions';
import {
  isValidCron,
  describeCron,
  nextOccurrence,
} from '@agent-native/core/jobs/cron';

interface ReportPayload {
  reportId: string;
}

export const createDailyReportJob = defineAction({
  name: 'createDailyReportJob',
  input: { reportId: 'string' },
  async run({ reportId }) {
    const cron = '0 9 * * *'; // 09:00 UTC every day
    
    if (!isValidCron(cron)) {
      throw new Error('Invalid cron expression');
    }

    const description = describeCron(cron); // "Every day at 9 AM"
    const firstRun = nextOccurrence(cron);

    await db.insert('jobs', {
      cron,
      targetAction: 'sendDailyReport',
      payload: { reportId } as ReportPayload,
      nextRunAt: firstRun,
      description,
    });

    return { ok: true, nextRunAt: firstRun, description };
  },
});

```

## Processing Recurring Jobs with a Scheduler

The scheduler service queries the `jobs` table for entries where `nextRunAt` is less than or equal to the current time, dispatches the target action using Agent-Native's invocation API, and recomputes the next occurrence.

### The Tick Loop Implementation

See [`templates/brain/jobs/process-ingest-queue.ts`](https://github.com/BuilderIO/agent-native/blob/main/templates/brain/jobs/process-ingest-queue.ts) for a reference implementation of a job processor. Your recurring job worker should follow this pattern:

```typescript
// src/server/jobs/worker.ts
import { db } from '@agent-native/server/db';
import { nextOccurrence } from '@agent-native/core/jobs/cron';
import { invokeAction } from '@agent-native/core/actions';

export async function processDueJobs() {
  const now = new Date();
  
  const dueJobs = await db.select('jobs', {
    where: { nextRunAt: { lte: now } },
  });

  for (const job of dueJobs) {
    await invokeAction(job.targetAction, job.payload);
    
    const nextRun = nextOccurrence(job.cron, now);
    await db.update('jobs', job.id, { nextRunAt: nextRun });
  }
}

```

This function runs at your desired interval—whether via `setInterval` in a Nitro plugin or a cloud-scheduled task—to continuously process the recurring job queue.

## Summary

- **Agent-Native wraps `cron-parser`** in [`packages/core/src/jobs/cron.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/jobs/cron.ts) to provide three pure functions: `nextOccurrence`, `isValidCron`, and `describeCron`
- **Job creation** involves validating the cron expression, computing the first run time, and persisting to the `jobs` table with the target action and payload
- **Job processing** requires a tick loop that queries due jobs, invokes the target action, and updates `nextRunAt` using `nextOccurrence`
- **The wrapper normalizes** the `@midnight` alias and handles timezone considerations automatically
- **All utilities are pure functions** with no side effects, making them safe to use in plugins, extensions, or frontend code for previewing schedules

## Frequently Asked Questions

### How does Agent-Native handle invalid cron expressions?

The `isValidCron` function in [`packages/core/src/jobs/cron.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/jobs/cron.ts) wraps the parser in a try-catch block and returns a boolean indicating validity. This allows you to reject malformed expressions at job creation time before they reach the database, preventing scheduler errors downstream.

### What is the @midnight alias and why does it need normalization?

The `@midnight` alias is a historic cron shorthand that `cron-parser` v5 misinterprets. Agent-Native includes an internal `ALIAS_MAP` in the cron wrapper that normalizes this alias to the correct expression before parsing, ensuring consistent behavior across different versions of the underlying library.

### Can I use these cron utilities on the frontend?

Yes. Because `nextOccurrence`, `isValidCron`, and `describeCron` are pure functions with no side effects, you can import them from `@agent-native/core/jobs/cron` into frontend code to preview schedule descriptions or validate expressions before submitting them to the server, reducing unnecessary API calls.

### How do I test recurring jobs in Agent-Native?

Unit tests for the cron utilities are located in [`packages/core/src/jobs/cron.spec.ts`](https://github.com/BuilderIO/agent-native/blob/main/packages/core/src/jobs/cron.spec.ts) and cover expression normalization, timezone handling, and description generation. For integration testing, you can mock the `nextOccurrence` function to return specific dates, or use the patterns shown in [`templates/brain/jobs/process-ingest-queue.ts`](https://github.com/BuilderIO/agent-native/blob/main/templates/brain/jobs/process-ingest-queue.ts) to test your job processor logic independently of the actual clock.