For AI agents: a documentation index is available at https://www.plungeai.com/docs/llms.txt. Append .md to any page URL, or send Accept: text/markdown, to get markdown. Setup instructions for agents are at https://www.plungeai.com/docs/agents.md. One ozk_ key opens every plane, models included.

Documentation Index: fetch the complete documentation index at /llms.txt. Use this file to discover all available pages before exploring further.

Source: orchestration/mcp-gateway/extras.ts (ScheduleSchema, plungeaiSchedule, ownedJob), orchestration/mcp-gateway/tools.ts (scheduler ids in getResult / getWorkflowStatus), orchestration/mcp-gateway/server.ts (TOOL_DEFS), orchestration/scheduler/scheduler.ts (/jobs routes), orchestration/scheduler/SchedulerDO.ts (heartbeat, model pin, local bots, manual runs), orchestration/scheduler/utils/cronParser.ts, orchestration/scheduler/utils/d1Manager.ts, orchestration/scheduler/README.md.

plungeai_schedule creates and manages cron jobs on the platform scheduler. A job belongs to the user behind your key, and every run of a workflow, agent, query or mission_ref job lands in your normal execution history (heartbeats are the exception, 11.3), where you read it like any other result (Runs, results & follow-ups). The examples use https://mcp.plungeai.com/v1. https://api.plungeai.com/v1/mcp is the same server.

The tool is not marked read-only, but stats, list, get and runs only read. Full parameter table: 14.19.

11.1 How a schedule runs

The scheduler checks for due jobs continuously; the shortest cadence is one minute. A job id looks like job_<timestamp>_<random>.

Everything this tool creates, except heartbeats, runs as a workflow job. Agent and query jobs are wrapped into a saved workflow first, so every run goes through the standard engine pipeline and shows up in your history:

You createWhat is savedWhat each run does
job_type: "workflow", target = one of your workflow idsthe job, linked to that workflowruns that workflow
job_type: "agent", target = an agent id, parameters.prompta new workflow Scheduled: <name> with one task (that agent, that prompt), and the jobruns the wrapper workflow
job_type: "query", target = {"agent": "<id>", "query": "<text>"}the same kind of wrapper workflowruns the wrapper workflow
mission_ref = a pre-built agent card ida wrapper workflow Scheduled: <name> with one harness task pointing at the cardruns the card, resolved live at fire time
job_type: "heartbeat"the jobchecks a condition each tick and acts only when it is met (11.3)

Wrapper workflows are ordinary saved workflows: they appear in plungeai_list_workflows and in Studio. Deleting a job does not delete its wrapper.

A workflow run is handed to a background run and the scheduler moves on; the run finishes on its own and the job's history is completed afterwards. Results can also be delivered to you (parameters.deliver, 11.3).

11.2 Actions

actionNeedsAnswer
statsnothing# Schedule stats with Jobs: N (a active, p paused)
listoptional limit (default 50)# Your scheduled jobs (N) and a table: Name, Type, Schedule, Status, Next run (epoch milliseconds), ID. Or No scheduled jobs. Create one with action "create" (name, job_type, target, schedule).
getjob_id# <name> and the whole job as JSON
createsee 11.3Created scheduled job **<name>** (`<job_id>`) — <cron>. plus a note naming the wrapper workflow, if one was made
updatejob_id and the fields to changeUpdated job `<job_id>`.
pausejob_idJob `<job_id>` is now paused.
resumejob_idJob `<job_id>` is now active.
deletejob_idDeleted scheduled job `<job_id>`. Its run history is preserved — action "runs" with this job id still shows past executions.
run_nowjob_idTriggered job `<job_id>` — execution `<id>` (fetch the output with plungeai_get_result).
runsoptional job_id, limit (default 20)# Scheduled runs (N) and a table: Job, Status, Started, Execution ID, Error
wakejob_id, optional noteWoke job `<job_id>` — it runs at <time>. The job's saved workflow runs once through the scheduler's runAgain, with note as its input; a pending wake is re-timed, never stacked
webhook_mint, email_mint, hooks_mintjob_id; webhook: prompt_template, scheme, filters; email: allowed_from; hooks: url, eventsthe scheduler's answer as JSON (token, URL or address part, signing secret). A secret is in this answer once and never listed again
webhook_list, email_list, hooks_listjob_idthe job's triggers of that kind as JSON (never a secret)
webhook_delete, email_delete, hooks_deletejob_id, trigger_idDeleted <kind> trigger `<id>` of job `<job_id>`. An id the job does not have is Trigger not found.
webhook_rotate, email_rotatejob_id, trigger_idmints a successor with the old trigger's settings, then revokes the old one (the same body as One API POST /v1/triggers/{webhook|email}/{token}/rotate): Rotated <kind> trigger `<id>` of job `<job_id>`: the old one is revoked. and the new trigger as JSON, with "rotated": "<old id>". The new secret is in this answer once. Mint comes first, so a failure in between leaves two live triggers, never none. Hooks have no rotate: delete and mint again

stats and list read up to 1,000 of your jobs and leave deleted jobs out. In list, agent and query jobs show the type workflow, because they were wrapped.

11.3 Create a job

Every create needs name and schedule. The rest depends on the kind of job. The tool picks the path in this order: job_type: "heartbeat" first, then mission_ref (when set, job_type and target are not needed), then the plain job_type + target path.

schedule is a five-field cron expression: minute hour day-of-month month day-of-week. For a one-time run use schedule: "@once" with run_at, an ISO-8601 time with a UTC offset (for example 2026-10-06T09:00:00Z); without run_at the call answers run_at required and creates nothing. ends_at (ISO-8601, on create or update) stops a recurring job after that time. The webhook and email triggers belong to workflow jobs, and the hooks (outbound, signed run events) to any job you own; the same set is on the One API as /v1/schedules and /v1/triggers.

FieldValues
minute0–59
hour0–23
day of month1–31
month1–12
day of week0–6, Sunday = 0

* is any value, , a list (1,15), - a range (1-5), / a step (*/15).

ScheduleCron
every 5 minutes*/5 * * * *
every hour0 * * * *
every day at 09:000 9 * * *
weekdays at 09:000 9 * * 1-5
every Monday at 07:000 7 * * 1
the 1st of every month at midnight0 0 1 * *

@once fires through run_at: the job runs once at that time and is then done. For a run right now, use run_now.

timezone is an IANA zone name such as America/Los_Angeles or Europe/Berlin. The cron is read in that zone. Without it the cron is read in UTC. An invalid zone is refused, never silently treated as UTC.

description is optional free text.

parameters is an object of job extras:

KeyMeaning
promptthe per-run goal or input. Required for agent jobs. For a workflow job it is the run's input (the scheduler reads initial_input, then input, then prompt). For a mission_ref job it is the goal, default Run your mission for today.
inputsnamed inputs for a workflow job
deliverwhere results go: an array of {channel, chat_id?, to?} with channel one of inapp, email, slack, telegram, whatsapp, discord, teams. A bare {channel:"slack"} sends you a direct message; a bare {channel:"email"} mails your registered address; any other email address must be a confirmed recipient. A bare string such as "slack" is accepted and stored as {channel:"slack"}

Workflow jobs

job_type: "workflow" and target = the id of one of your saved workflows (from plungeai_list_workflows).

  • The workflow must be in your account, or the answer is No workflow `<id>` found in your account — pass a workflow id from plungeai_list_workflows, or build one with plungeai_build_workflow.
  • The scheduler refuses a workflow that names an agent id that does not exist: Scheduler rejected the job: Cannot schedule — no such agent: <ids>. …
  • Model pin. When you create the job, the first model: line in the workflow YAML is recorded, at any indentation (a task's model: counts). If that first model: value changes later, each run is skipped instead of running on the new model. The run is still recorded as completed in runs, and the notice ⚠️ Skipped this run: the model changed from <old> to <new> since you scheduled it. Re-save the schedule to accept the new model. goes to the job's parameters.deliver targets. With no deliver the skip is silent. The update action does not re-record the model; create a new job to accept it. A workflow with no model: line anywhere is not pinned.
  • Local bots. A workflow of kind bot whose YAML says local: true runs on your own computer. When your computer is offline at fire time, the run is skipped instead of failing, and a notice (⏭️ Skipped "<name>" — this bot runs on your computer, which was offline …) goes to the job's parameters.deliver targets, if it has any.

Agent and query jobs

  • Agent: job_type: "agent", target = an active registry agent id, and parameters.prompt = what the agent should do each run. Without the prompt: Agent schedules need a prompt — pass parameters: { "prompt": "what <agent> should do each run" }.
  • Query: job_type: "query", target = a JSON string {"agent": "<agent-id>", "query": "<what to run>"}. Both keys are required.

The agent is checked when you create the job: an unknown or inactive agent is refused before anything is saved in the scheduler (No such agent: … / Not permitted: … is not status:active …). Take agent ids from plungeai_list_agents (Discovery).

Pre-built agent cards (mission_ref)

Pass mission_ref with the card id, plus name and schedule. Each run executes the card as a one-task harness workflow with parameters.prompt as its goal. The card is resolved live at fire time, so edits to the card apply to future runs automatically.

Heartbeats

A heartbeat is a proactive check, such as "check my inbox for urgent email every 30 minutes". It needs job_type: "heartbeat", name, schedule, check_agent (or check_workflow) and condition_prompt; trigger_workflow, notify_channel and notify_chat_id are optional. The tool builds the job's target from these fields.

Each tick:

  1. check_agent is asked condition_prompt and told to answer only YES or NO. With check_workflow instead, that saved workflow runs as you with condition_prompt as its input and its last task must answer YES or NO.
  2. On NO, nothing else happens.
  3. On YES, trigger_workflow (a workflow id) runs with condition_prompt as its input, if set.
  4. Then a notification goes to notify_channel / notify_chat_id, if both are set.

A heartbeat's check and its trigger_workflow run directly on the engine as system runs and create no execution in your history. run_now and runs show only the scheduler's own exec_… id, which the result tools cannot open, and the triggered workflow's output does not appear in plungeai_executions. Set notify_channel / notify_chat_id to see the outcome.

check_agent must be an active agent. check_workflow must be the id of a workflow you own, with no unknown agent in it. Studio's Gmail trigger is a heartbeat built this way: a Gmail search task, then a YES/NO judge. notify_channel is one of telegram, whatsapp, discord, slack, teams, email. WhatsApp notifications are partial: the WhatsApp adapter needs a phone-number id a heartbeat does not carry, so a WhatsApp heartbeat sends nothing today.

Create errors

All isError: true:

AnswerCause
create requires: name, job_type (agent|query|workflow), target, schedule (cron).a plain create with a field missing
heartbeat create requires: name, schedule (cron), check_agent or check_workflow …, condition_prompt. …a heartbeat with a field missing
mission_ref create requires: name, schedule (cron). …a mission_ref create with a field missing
Scheduler rejected the job: Failed to parse cron expression: …not a valid five-field cron
Scheduler rejected the job: Invalid timezone: <zone>not an IANA zone
For job_type "query", target must be JSON: {"agent": "<agent-id>", "query": "<what to run>"}. / Query target must include both "agent" and "query".a malformed query target
The scheduler hit a temporary storage error while saving the job — please retry; it usually succeeds on the second attempt.a transient storage error

Heartbeat rejections read Scheduler rejected the heartbeat: ….

The wrapper is saved first. For agent, query and mission_ref jobs, the Scheduled: <name> workflow is saved before the scheduler validates the job. If the scheduler then rejects it (a bad cron, a bad zone), the wrapper stays in your workflows. Delete it with plungeai_workflow {action:"delete"} (Workflows).

Try asking:

  • "Run the S&P 500 weekly performance analysis every Monday at 7am." Your client finds the workflow, then creates a workflow job with 0 7 * * 1 (and your time zone).
  • "Every weekday at 9, have the news agent brief me on AI chip news and send it to Slack."

Create a workflow job. This saves a job that runs, and costs credits, on every tick (not verified here):

curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_schedule","arguments":{"user_request":"run the S&P 500 weekly performance analysis every Monday at 7am","action":"create","name":"S&P 500 weekly","job_type":"workflow","target":"<workflow_id>","schedule":"0 7 * * 1","timezone":"America/New_York","parameters":{"deliver":[{"channel":"email"}]}}}}'

Schedule one agent directly (the tool saves the wrapper workflow for you):

curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_schedule","arguments":{"user_request":"every weekday at 9 brief me on AI chip news","action":"create","name":"AI chip news","job_type":"agent","target":"newsapi-get-articles","schedule":"0 9 * * 1-5","parameters":{"prompt":"Top AI chip news of the last 24 hours, five bullets with links.","deliver":["slack"]}}}}'

11.4 Update, pause, resume, delete

job_id must be one of your jobs; anything else answers Job not found. Passing an execution id by mistake (exec_…) answers That looks like an execution id (exec_…), not a job id (job_…). ….

update changes only what you pass: name, description, schedule, timezone, target, parameters. parameters replaces the stored object, so send the whole object. Other keys (job_type, mission_ref, the heartbeat fields) are ignored on update.

  • A workflow job runs the workflow it was linked to at create. A new target does not change that link. To schedule a different workflow, create a new job and delete the old one.
  • A rejected update answers Scheduler update failed (HTTP <status>). without the reason. Check the cron and the zone: an invalid cron comes back as HTTP 500, an invalid zone as HTTP 400.

pause and resume set the job to paused or active.

delete is soft. The job stops and is marked deleted; its run history stays readable with runs and the job id. A deleted job refuses update, pause and resume (This job is deleted — it cannot be modified. …) and run_now (This job is deleted — it cannot be run. …). Deleting it again answers Job `<job_id>` is already deleted. Deleted jobs drop out of list and stats. The wrapper workflow of an agent, query or mission_ref job is not deleted.

Busy storage. When the scheduler's storage is briefly throttled, the job lookup is retried once. If it still fails, the answer is The scheduler’s storage is briefly busy (D1 throttling) — the job most likely still exists. Retry in a few seconds., never "Job not found".

Try asking: "What do I have scheduled?", "Pause the S&P 500 job.", "Move it to 8am.", "Delete that schedule."

Pause a job. This changes its state (not verified here):

curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_schedule","arguments":{"user_request":"pause the S&P 500 job","action":"pause","job_id":"<job_id>"}}}'

11.5 Run now and run history

run_now runs a job immediately, outside its cadence, and reports the scheduler's real outcome, not just "triggered".

  • Success: Triggered job `<job_id>` — execution `<id>` (fetch the output with plungeai_get_result). A workflow run is handed to a background run, so this answer comes back once the run has started, not when it has finished. Poll plungeai_get_workflow_status with that id, then read it with plungeai_get_result.
  • When the scheduler has only its own run id: Triggered job `<job_id>` — scheduler run `exec_…` (see action "runs").
  • Failure: Run failed (scheduler run `exec_…`): <reason> (isError: true).

runs lists run history:

  • with job_id: that job's runs, including the runs of a deleted job;
  • without job_id: the runs of your current jobs. Runs of deleted jobs are left out; ask for them by job id.

limit defaults to 20 (1–100). The columns are Job, Status, Started, Execution ID and Error (first 120 characters). The Execution ID is the id plungeai_get_result and plungeai_get_workflow_status accept: the platform execution id, or the engine's exec-… id. Heartbeat runs, and only very old runs of other jobs, fall back to the scheduler's own exec_… id, which those tools redirect back here. No executions for your jobs yet. means there are none.

Try asking: "Run it now.", "Show me the run history of that job."

Run history (read-only):

curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_schedule","arguments":{"user_request":"show me the run history of that job","action":"runs","job_id":"<job_id>","limit":10}}}'

Your schedule at a glance (read-only):

curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_schedule","arguments":{"user_request":"what do I have scheduled?","action":"stats"}}}'

Run a job now. This runs the job and costs credits (not verified here):

curl -s https://mcp.plungeai.com/v1 \
  -H "Authorization: Bearer $PLUNGE_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"plungeai_schedule","arguments":{"user_request":"run it now","action":"run_now","job_id":"<job_id>"}}}'

Planned: TI-34

The docs assistant is not available yet. You can hand these docs to your own assistant instead.