$worker

cron

v0.21.0

Schedule functions with cron expressions - registers the `cron` trigger type.

  • macOS: arm64 · x64
  • Linux: arm64 · armv7 · x64
  • Windows: arm64 · x64 · x86
agent-ready brief for v0.21.0
install + config + dependencies + readme + api reference, all in one place. fetch as agent-context.md for an llm to consume.
the same content rendered as discrete blocks below is exposed as a single markdown document at /workers/cron.md. paste it into an llm prompt or pipe it through curl from a worker.

install

install
$iii worker add cron@0.21.0

configuration

iii-config.yaml
- adapter:
    name: local

dependencies

dependencies1

readme

README.md

cron

Schedules registered functions with cron expressions. Any function bound to a cron trigger is invoked by this worker at the next matching UTC time. The worker replaces the built-in iii-cron worker while keeping the trigger type and payload shape stable.

Install

iii worker add cron

iii worker add fetches the binary, writes a config block into ~/.iii/config.yaml, and the engine starts the worker on the next iii start.

Quickstart

Register a function and bind it to this worker's trigger type (cron) with an expression:

use iii_sdk::protocol::RegisterTriggerInput;
use iii_sdk::{errors::Error, register_worker, InitOptions, RegisterFunction};
use serde_json::{json, Value};

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let iii = register_worker("ws://localhost:49134", InitOptions::default());

    iii.register_function(
        "jobs::tick",
        RegisterFunction::new_async(|payload: Value| async move {
            println!("cron fired: {payload}");
            Ok::<Value, Error>(json!({"ok": true}))
        }),
    );

    iii.register_trigger(RegisterTriggerInput {
        trigger_type: "cron".to_string(),
        function_id: "jobs::tick".into(),
        config: json!({ "expression": "*/5 * * * * *" }),
        metadata: None,
    })?;

    tokio::signal::ctrl_c().await?;
    Ok(())
}

The function receives:

{
  "trigger": "cron",
  "job_id": "<trigger-id>",
  "scheduled_time": "2026-07-03T12:00:00+00:00",
  "actual_time": "2026-07-03T12:00:00.123456789+00:00"
}

Configuration

Field Default Description
adapter.name local Lock backend. Use local for process-local locking or redis for multi-instance mutual exclusion.
adapter.config.redis_url redis://localhost:6379 Redis URL when adapter.name is redis.

Configuration is owned by the configuration worker - edit it from the console (Configuration -> Workers -> cron) or seed it once via --config .yaml on first boot. Changing the lock adapter hot-swaps the scheduler under a serialized apply lock: existing jobs are stopped, re-created with the new backend, and never run in two scheduler instances at once.

Trigger type

This worker always registers the cron trigger type. Bind a function to it with:

Field Required Default Description
expression yes - Cron expression parsed by the Rust cron crate. Six-field sec min hour day month weekday expressions are supported, and a seventh year field is accepted.
condition_function_id no - Function invoked before the scheduled handler. Only an explicit JSON false return blocks the fire; missing/null/truthy returns allow it. Condition errors skip that fire.

All schedules use UTC. Missed fires while the worker is stopped are skipped; there is no catch-up replay.

Requires removing the built-in iii-cron worker

The built-in iii-cron worker also owns the cron trigger type. Two owners of the same trigger type on one engine collide - whichever registers last wins - so this worker requires iii-cron to be absent: omit it from the engine's config.yaml (a config that doesn't list a worker won't run it).

On boot, this worker queries the engine for connected workers and refuses to start with a clear error if iii-cron is still active, so a stale config fails loudly instead of silently racing the built-in worker for ownership of cron.

Parity vs builtin

Behavior Builtin This worker
Expressions 6-7 field (cron crate) same
Timezone UTC only same
Missed runs skipped, no catch-up same
Condition only explicit false blocks same
Lock TTL 30s same
Lock backends kv (process-local), redis local (process-local), redis
Service functions none none

api reference (json)

agent-api-reference.json
{
  "functions": [
    {
      "description": "Internal: reload cron configuration from the authoritative store on change.",
      "metadata": {},
      "name": "cron::on-config-change",
      "request_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "title": "ConfigChangeRequest",
        "type": "object"
      },
      "response_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "ok": {
            "type": "boolean"
          }
        },
        "required": [
          "ok"
        ],
        "title": "ConfigChangeAck",
        "type": "object"
      }
    }
  ],
  "triggers": [
    {
      "description": "Cron-based scheduled triggers",
      "invocation_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "description": "Trigger config schema, field-parity with the engine's CronTriggerConfig.",
        "properties": {
          "condition_function_id": {
            "description": "Optional function ID to evaluate before invoking the handler.",
            "type": [
              "string",
              "null"
            ]
          },
          "expression": {
            "description": "Cron expression (6-field format: sec min hour day month weekday; a 7th year field is accepted).",
            "type": "string"
          }
        },
        "required": [
          "expression"
        ],
        "title": "CronTriggerSpec",
        "type": "object"
      },
      "metadata": {},
      "name": "cron",
      "return_schema": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "properties": {
          "actual_time": {
            "description": "Actual execution time (RFC3339)",
            "type": "string"
          },
          "job_id": {
            "description": "Unique job identifier",
            "type": "string"
          },
          "scheduled_time": {
            "description": "Scheduled execution time (RFC3339)",
            "type": "string"
          },
          "trigger": {
            "description": "Always \"cron\"",
            "type": "string"
          }
        },
        "required": [
          "actual_time",
          "job_id",
          "scheduled_time",
          "trigger"
        ],
        "title": "CronCallRequest",
        "type": "object"
      }
    }
  ]
}