Docs/Guides/Schedule recurring plans
Deploy6 min read

Schedule recurring plans

A plan you can run on demand is useful. A plan that runs itself — on a cadence, with its tools connected and its output delivered — is a product. Diaphora schedules turn any plan into a recurring, hands-off job on the managed runtime: you pick when it runs and what parameters it runs with, and the platform handles the rest.

The running example in this guide is a real one: the Weekly Market Intelligence Brief plan. Every Monday at 9:00 AM Eastern it analyzes the past week of debt-relief market data, renders an email-ready HTML brief, and sends it to the sales team through the Resend MCP server — no servers, cron jobs, or delivery scripts of your own.

Why schedule on Diaphora

The point isn't just "cron in the cloud." Scheduling on Diaphora means the whole job — trigger, computation, tool access, delivery, and observability — lives in one place, versioned with the plan.

ConcernRoll your ownOn Diaphora
TriggerA cron daemon on a box you maintainNative schedules — timezone-aware, with a human-readable cadence preview
Tool accessStore, inject, and rotate API keys yourselfMCP servers connected once and shown ready; auth is managed for you
DeliverySeparate email/reporting pipelineThe plan sends its own result through an MCP server — delivery is the run
ParametersHardcode or thread through env varsPer-schedule runtime parameters, edited in the UI
ObservabilityBuild your own logging and alertsExecution history and an executions-over-time chart, per plan
Changing cadenceEdit crontab, redeployEdit the schedule in the UI — no redeploy

Because the plan and its schedule are the same artifact, there's no glue code to drift out of sync. Change the plan, and every schedule that runs it picks up the change on the next fire.

The plan behind the schedule

A schedule runs a plan — so first you have a plan worth running. The full Weekly Market Intelligence Brief is in the plan marketplace; the excerpts below are the parts that matter for scheduling. (Open the marketplace item to read it end to end, HTML renderer and all.)

Declare the tool and the parameters up front. A system(...) line sets the analyst persona, require mcp Resend connects the email tool, and two parameter(...) lines expose the values the schedule fills in each run:

FML
system("You are an expert financial researcher and industry analyst for a major debt settlement company.")
require mcp Resend
parameter("timeframe", type=string, default="this past week")
parameter("to_address", type=string, title="To Address")

timeframe and to_address aren't hardcoded — the schedule freezes their values per run (below), so the same plan can drive this week's brief, a monthly recap, or a one-off to a different inbox.

Each research session gathers one slice and types its output. There are five independent search sessions; the economic dashboard is representative — note how the schema names exactly the columns the email table needs:

FML
session("economic_dashboard") {
    use search

    + Find the most recently published data (from FRED or the Federal Reserve)
      for the fed funds rate, unemployment, credit card delinquency, APR, and more.
    - Extract the data to populate the Leading Indicators Dashboard.

    schema {
        metrics: {
            indicator: string         # The name of the economic indicator
            currentValue: string      # Most recent value (include date/period)
            priorPeriodValue: string  # Value from the previous reporting period
            trend: string             # "Up", "Down", or "Flat"
            source: string            # e.g., "FRED", "Federal Reserve"
        }[]
    }
}

The final session renders and delivers. It runs after="economic_dashboard", builds the branded HTML in a deterministic code() PreCall (Resend can't loop over arrays, so the plan assembles the rows itself), then hands the finished html/text to Resend's send-email:

FML
session("send_email", after="economic_dashboard") {
    use mcp Resend

    # Render branded HTML + a plain-text fallback from every session's output.
    call("render_email") -> vars:email {
        code( /* build html + text from $(context)  */ )
        data      = $( context )
        timeframe = "{{ .params.timeframe }}"
    }

    call("send-email") {
        to      = $( [params.to_address] )
        from    = "notifications@acme.ai"
        subject = "Weekly Industry Brief: {{ .params.timeframe }}"
        html    = $( vars.email.html )
    }

    - Output true for sentSuccessfully to confirm the session ran.
    schema { sentSuccessfully: bool }
}

Three things worth calling out:

  • Frags resolves the run order from the after declaration. The five research sessions run independently; send_email waits on economic_dashboard. You declare the dependency and the runtime works out the order — there's no imperative sequence (see Control the flow of a plan).
  • $(...) passes real values, not strings. data = $( context ) hands the code block the actual object graph, and to = $( [params.to_address] ) builds a real array for Resend — that typing is what lets the renderer loop over metrics and the rest. See Templates and expressions.
  • require mcp Resend connects the Resend MCP server; the plan calls its send-email function directly. This is the connection that shows as Resend · ready in the plan's Tools panel — its credentials are managed by the platform, not baked into the plan. For how MCP tools are declared and called, see Connect Frags to your data.

Create a schedule in the UI

Open the plan and select Schedules in the left rail. The first time, you'll see an empty state — click Create the first one (or + New schedule in the top right on later visits).

The Schedules tab before any schedule exists — start with "Create the first one."
The Schedules tab before any schedule exists — start with "Create the first one."

1. Name the schedule. Give it something you'll recognize in the list — e.g. Monday Report — week prior. A plan can hold several schedules, so the name is how you tell them apart.

2. Set the timezone. Cadences fire in the timezone you pick — here, America/New_York. This matters for "9 AM": the platform resolves the fire time in your timezone and handles daylight-saving shifts.

3. Pick the cadence. Choose one of Hourly · Daily · Weekly · Monthly. For the newsletter, select Weekly, then:

  • Days of Week — select Mon.
  • Hours — select 09. (Any fires every hour; leaving hours unset behaves the same.)
  • Only in specific months — optional; leave it closed to run year-round.

As you choose, the panel shows a plain-English preview so there's no cron syntax to second-guess:

🕘 Every Monday at 9:00 AM (America/New_York)

4. Set the runtime parameters. Under Parameters, fill in the values this run should use. The newsletter plan exposes timeframe, so set it to this past week. These are the same parameters the plan declares with parameter(...) — the schedule freezes the values each run uses.

The New schedule form: timezone, a weekly cadence on Monday at 09:00 with the plain-English preview, and the timeframe parameter set to "this past week."
The New schedule form: timezone, a weekly cadence on Monday at 09:00 with the plain-English preview, and the timeframe parameter set to "this past week."

5. Save. The schedule appears in the plan's Schedules list with its name and cadence, and edit (✏️) / delete (🗑️) controls. It will fire on the next matching time — no further action needed.

The saved schedule in the plan's Schedules list, showing its name and "Every Monday at 9:00 AM (America/New_York)" cadence with edit and delete controls.
The saved schedule in the plan's Schedules list, showing its name and "Every Monday at 9:00 AM (America/New_York)" cadence with edit and delete controls.

Watch it run

Back on the plan overview, the Executions over time chart tracks runs over the last few days, so you can confirm the schedule is firing and spot a run that didn't. Each fire executes the plan end to end: the five research sessions gather the week's regulatory, competitor, lending, marketing, and economic data, then send_email renders the branded HTML and delivers it through Resend — the same structured output you'd get from a manual run, on autopilot.

To change the cadence or parameters, edit the schedule in place — there's nothing to redeploy. To pause the job, delete the schedule; the plan itself is untouched and still runnable on demand.

Next steps

← All guides

Run a plan automatically on a cadence — schedule a weekly market brief that analyzes data and emails an HTML report through the Resend MCP server, all on Diaphora's managed runtime.