Skip to main content
Glama

Create a schedule

well_create_schedule

Create one workspace schedule: a job Well runs on a clock or on an event, with nobody in the chat. A schedule is either a prompt (a written instruction a headless run follows) or a method (a registered function name plus params).

Use it whenever the user wants something done or sent at a later time, on a rhythm or when an event happens.

A schedule covers three kinds of job:

  • Once, at a set time: "send me a poem at 1:45am", "send me a haiku on Friday". Send max_occurrences 1, run_after at that moment (ISO 8601 with an offset) and a cron_expression that matches that time of day. The run is the message or the job itself. A day with no time runs at 09:00 in the user's time zone: say that time in the cadence_label and in your confirmation. If the start time passed before confirmation, propose a new time.

  • Recurring, on a rhythm: "every Monday 9am send me the runway". Send a cron_expression and no max_occurrences.

  • On an event: "each time a payment is matched to an invoice". Send a trigger_name from well_list_schedule_triggers. A message for the user is a job like any other. Well sends the user the run's result after a run that succeeds, so for a message or a reminder set status_report to "on_success" and write the instruction so the run puts the message itself (the poem, the reminder line) in its result. On WhatsApp the message arrives as written inside the 24 h window; outside it the user first gets a notification with a short summary, and the full result arrives after they reply. A to-do ("add a to-do", "I need to file X by Friday") or a one-time reminder to do something ("remind me Friday to pay Kepler") is a to-do for well_create_task, not a schedule, unless well_create_task answered code "reminder_needs_schedule": then it runs once, at a set time; a reminder that repeats ("every Monday remind me to check the bank") is a schedule.

REQUIRED: name, kind ("prompt" or "method"), routine_summary, cadence_label, status_report, timezone, approved_tools and verified. Send exactly one: cron_expression for a clock, trigger_name (from well_list_schedule_triggers) for an event. An event routine takes no run_after or max_occurrences. For a prompt: instruction (the detailed brief the run follows to the letter, with every decision it must make alone). For a method: method_name, and method_params when the method takes any.

The user never reads the instruction, the cron or a trigger name: the instruction is the detailed brief for the run, and a person does not read a contract. Show the user only the routine_summary, when it runs (with the status report choice) and the permissions, in plain words, and never paste the instruction, a cron expression or a trigger name into the chat. The confirmation card shows the same three things, built by Well from the stored schedule.

routine_summary and cadence_label are written for the user, in the language of the conversation, as plain text with no markdown. routine_summary says what will happen, and who or what outside Well each change reaches. cadence_label says when it runs. For a clock it says the rhythm in words and says the same thing as cron_expression: write both in the same call. Well computes the next run dates from cron_expression and shows them beside cadence_label, so a label that disagrees with the cron is visible to the user. For an event it says the event in plain words, such as "Each time a Qonto payment is matched to an invoice", and never the trigger_name. OPTIONAL, for a clock routine only: run_after (ISO 8601 with an offset: no run happens before it), max_occurrences (a whole number of runs, then the schedule completes; 1 runs once). OPTIONAL, for any routine: ends_at (ISO 8601 with an offset): the moment after which the routine stops. No run happens after it, and the schedule completes once it passes. Send it when the user names an end, such as "until 31 December" or "for the next two weeks"; omit it for no end. It must be after run_after.

cron_expression is a standard 5-field cron: minute, hour, day of month, month, day of week. A seconds field is refused. timezone is an IANA name such as Europe/Paris, and a cron is read in it. A cron whose day-of-month and day-of-week fields are both restricted fires when either one matches. To tie a weekday to its nth occurrence in the month, leave day-of-month as * and write the weekday, then #, then n, in the day-of-week field. A clock routine is held on Sunday in the user's time zone by default. The morning brief is never held by the Sunday gate; its default cron runs on weekdays. For another routine, only an explicit choice lifts the hold: name Sunday in the day-of-week field when asked for Sunday or all seven days (0 alone or in a list or range; * does not name Sunday), save sunday_routines as receive, or set a one-off time. A meeting or Sunday habit does not lift the hold. A routine already scheduled for Sunday must have Sunday removed from its schedule to stop it; other routines already have the default hold. For a cron, two runs of a schedule must be at least 30 minutes apart, and the rhythm must fire at least once a year. A rhythm outside that range is refused, never adjusted: explain the rule to the user and let them choose a rhythm that keeps it.

status_report is the user's own answer to the report question: "on_error", "on_success", "both", or "none" when they did not ask for a message. Well sends the report itself after each run; never write it into the instruction.

approved_tools is the consent record: the write tools the user signed off before the schedule was armed, as entries { tool, connector? }. The tool of each entry is the exact name of a write tool in your own toolset, one entry for each change the user approved; a read tool or a guessed name is refused, and so is any tool that invites members, buys credits, changes the plan, manages the subscription or sends email: a routine cannot do those, so tell the user instead of listing them. It is required, and [] means the routine only reads. At run time a scheduled run is told to make only the changes the list describes. A method schedule always sends [].

purpose is optional and names the job when a recipe of the schedule skill names it, such as "weekly_missing_invoices_total" for the missing-invoices total. Send it exactly as the recipe names it, and leave it out for any other routine. Well finds a routine by its purpose, never by its text, so a member never gets the same routine twice.

verified is required. false saves a draft that runs nothing and draws no card. true asks to arm the schedule: in Well's chat the schedule runs only after the user approves the confirmation card, and anywhere else it is saved as a draft. Both are required so that a forgotten flag or list is an error, never a default. Only a call that arms a schedule (verified: true) asks the user for approval, through a confirmation card in Well's chat, and the schedule is armed only when the user approves it. Outside Well's chat no card can be drawn, so verified: true arms nothing there: the call saves the schedule as a draft, and the user arms it from Well's chat. Two creates arm at once with no card on every surface, because the ask is the yes and the run writes nothing: an agent's routine (agent_seat_id), and a weekly_missing_invoices_total routine of kind prompt on a cron that fires once a week, with no approved_tools. Saving or editing a draft, pausing, resuming and cancelling draw no card. Editing the routine_summary, the cadence_label, the instruction, the method, the rhythm, the time zone, the start, the end limit or approved_tools returns the schedule to a draft, which runs nothing until it is armed again. Two exceptions. The creator's own edit of a weekly_missing_invoices_total routine that still fits the rule above (kind prompt, a cron that fires once a week, no approved_tools) keeps it armed on the new clock, and arms it when it is a draft, with no card and with Well's own instruction for that job. Moving only the hour and minute of the user's active afternoon or EOD touchbase, on the same weekdays and with a new cadence_label, keeps it armed.

The result states status and next_run_at. Quote them to the user, and say the stored approved_tools in plain words, never as tool names.

WORKFLOW: 1. Load the /schedule skill and follow it. 2. Show the user the routine_summary, when it runs and every permission in plain words, and get an explicit yes. 3. Call this tool once, with verified: true. 4. In Well's chat, wait for the user to approve the card, then quote status and next_run_at. Anywhere else, quote the draft status and tell the user to arm the routine from Well's chat.

The conversation that produces a good schedule (what the run needs, which jobs cannot run alone, the rhythm advice and the permission list the user signs off) belongs to the /schedule skill. Load it before proposing a schedule.

Do NOT use this to run a job once now; the skill that owns the job does that. Do NOT use this to change a schedule that exists (use well_update_schedule), or to add a to-do (use the tasks tool). A scheduled run never calls this tool.

When the token authorizes one workspace, call this directly — no workspace call is needed first. When it authorizes several, this read will not guess which one you mean: pass workspace_id on the call.

Input Schema

NameRequiredDescriptionDefault
kindYes"prompt" for a written instruction, "method" for a registered method.
nameYesThe routine's name, as `<Subject> · <moment>`: the subject in the user's own words, then when it runs. The moment is always present, because the report subject, the WhatsApp notice and the run thread title show no rhythm beside the name. Never a cron expression. Inside 60 characters.
ends_atNoThe moment after which the routine stops (ISO 8601 with an offset): no run after it, then the schedule completes. Omit for no end.
purposeNoThe job the routine does, when a recipe of the schedule skill names it, such as "weekly_missing_invoices_total" for the missing-invoices total. Omit it for any other routine. A "weekly_missing_invoices_total" routine of kind "prompt" on a cron that fires once a week (one minute, one hour, one day of the week), with an empty approved_tools list, only reads and reports to its creator, so Well arms it at once on every surface, with its own instruction for that job: send verified: false and draw no card. A faster rhythm is saved as a draft.
timezoneYesAn IANA time zone name. The cron is read in it. An event routine (trigger_name) stores no zone.
verifiedYesfalse saves a draft with no card, except two creates that Well arms at once with no card: an agent's routine (agent_seat_id), and a weekly_missing_invoices_total routine as the purpose field describes. true arms the schedule once the user approves Well's card; outside Well's chat it saves a draft.
run_afterNoNo run happens before this moment (ISO 8601 with an offset).
instructionNoThe detailed brief a prompt run follows. The user never reads it. Required for a prompt, refused for a method.
method_nameNoThe registered method to run. Required for a method, refused for a prompt.
trigger_nameNoThe event that starts the routine, instead of a cron. Send this or cron_expression, never both.
workspace_idNoTarget workspace. Omit when the token authorizes one workspace. Required when it authorizes several — a write lands in exactly one workspace and this call would not say which.
agent_seat_idNoThe seat_id (from well_list_agent_seats) of the workspace agent that does this routine's work, when the user handed the work to an agent. An agent's routine is kind "prompt" with an empty approved_tools list: each run drafts in its report, and the report goes to the agent's sponsor. The complete order is the yes, so Well arms it at once on every surface: send verified: false and draw no card. Omit it for any other routine.
cadence_labelYesWhen it runs, in plain words, in the language of the conversation. For a cron_expression, the rhythm, saying the same thing as the cron. For a trigger_name, the event, such as "Each time a Qonto payment is matched to an invoice". No cron, no trigger name, no markdown.
method_paramsNoThe method's params, when it takes any.
status_reportYesThe user's answer to the report question: a message when a run fails ("on_error"), when it succeeds ("on_success"), both, or "none". "none" when the user did not ask for a message.
approved_toolsYesThe write tools the user signed off, as { tool, connector? } entries. [] when the routine only reads.
conversation_idNoThe conversation id returned by the previous Well result, in its meta under well/conversation_id, in its structuredContent, or in its JSON text block. Pass it back on every call in the same conversation, including a call a card makes, so the chosen workspace and the earlier answers still apply. It decides the conversation on its own: nothing the host states about the session replaces it. Omit it only on the first call of a conversation.
cron_expressionNoA 5-field cron: minute hour day-of-month month day-of-week. Send this or trigger_name, never both.
idempotency_keyNoOptional client-supplied key. A retried write with the same key returns the original result instead of re-applying the operation.
max_occurrencesNoHow many runs, then the schedule completes. 1 runs once. Omit for no end.
routine_summaryYesWhat will happen, in plain words for the user, in the language of the conversation. Names who or what outside Well each change reaches. No markdown.
workspace_scopeNoRestrict this call to the family: the token's primary workspace plus the company workspaces under it that you are a member of. Unrelated authorized workspaces drop out of the read; row reads merge across the family, while a per-workspace figure still reports exactly one workspace.

Output Schema

NameRequiredDescriptionDefault
errorNo
statusNo
messageNo
successYes
scheduleNo
next_run_atNo
approved_toolsNo
conversation_idNoThe conversation this result belongs to. Pass it back as the conversation_id argument on every later Well call in the same conversation.
newly_connectedNoTools that connected to this workspace since the last result and that no session was told about yet, oldest first. Present only when at least one tool is new. The connected-line rule says when to tell an entry; when it does, one line per entry, in the person's language: "<name> is connected.". Never fold several entries into one sentence. Each entry comes back once, on one result only: never repeat its line later.
resolved_workspaceNoThe workspace that answered, when the caller named none and the token authorizes several.
conversation_id_noteNoPresent only when the server opened a fresh lane, stating that no choice recorded earlier was read.
conversation_id_sourceNoWhere the conversation id came from: the host's own request meta, the caller's argument, or a fresh lane the server opened.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / timezone / description
      Previous value: -"An IANA time zone name. The cron is read in it."New value: +"An IANA time zone name. The cron is read in it. An event routine (trigger_name) stores no zone."
  2. Changed4 schema fields changed
    • removedOutput schema / properties / next_run_at / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / next_run_at / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / resolved_workspace / properties / name / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / resolved_workspace / properties / name / type
      Added value: +[
      +  "string",
      +  "null"
      +]
  3. Changed3 schema fields changed
    • addedInput schema / properties / approved_tools / items / properties / browser
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "On a well_create_task entry only: the browser task the routine may start (\"buy\", a purchase that stops at the payment page; \"invoice_fetch\", the collection of the missing invoices of the counterparties it names). Without it the entry covers plain tasks only.",
      +  "properties": {
      +    "goal_kind": {
      +      "enum": [
      +        "buy",
      +        "invoice_fetch"
      +      ],
      +      "type": "string"
      +    }
      +  },
      +  "required": [
      +    "goal_kind"
      +  ],
      +  "type": "object"
      +}
    • changedInput schema / properties / purpose / description
      Previous value: -"The job the routine does, when a recipe of the schedule skill names it, such as \"weekly_missing_invoices_total\" for the missing-invoices total. Omit it for any other routine."New value: +"The job the routine does, when a recipe of the schedule skill names it, such as \"weekly_missing_invoices_total\" for the missing-invoices total. Omit it for any other routine. A \"weekly_missing_invoices_total\" routine of kind \"prompt\" on a cron that fires once a week (one minute, one hour, one day of the week), with an empty approved_tools list, only reads and reports to its creator, so Well arms it at once on every surface, with its own instruction for that job: send verified: false and draw no card. A faster rhythm is saved as a draft."
    • changedInput schema / properties / verified / description
      Previous value: -"false saves a draft with no card. true arms the schedule once the user approves Well's card; outside Well's chat it saves a draft."New value: +"false saves a draft with no card, except two creates that Well arms at once with no card: an agent's routine (agent_seat_id), and a weekly_missing_invoices_total routine as the purpose field describes. true arms the schedule once the user approves Well's card; outside Well's chat it saves a draft."
  4. Changed1 schema field changed
    • changedInput schema / properties / purpose / enum
      Previous value: -[
      -  "weekly_missing_invoices_total",
      -  "monthly_back_office",
      -  "daily_spending_sweep",
      -  "agenda_recap_daily",
      -  "daily_due_invoices"
      -]New value: +[
      +  "weekly_missing_invoices_total",
      +  "monthly_back_office",
      +  "daily_spending_sweep",
      +  "agenda_recap_daily",
      +  "daily_due_invoices",
      +  "follow_ups_daily"
      +]
  5. Changed1 schema field changed
    • addedInput schema / properties / agent_seat_id
      Added value: +{
      +  "description": "The seat_id (from well_list_agent_seats) of the workspace agent that does this routine's work, when the user handed the work to an agent. An agent's routine is kind \"prompt\" with an empty approved_tools list: each run drafts in its report, and the report goes to the agent's sponsor. The complete order is the yes, so Well arms it at once on every surface: send verified: false and draw no card. Omit it for any other routine.",
      +  "format": "uuid",
      +  "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
      +  "type": "string"
      +}
  6. Changed1 schema field changed
    • addedInput schema / properties / ends_at
      Added value: +{
      +  "anyOf": [
      +    {
      +      "format": "date-time",
      +      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$",
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "description": "The moment after which the routine stops (ISO 8601 with an offset): no run after it, then the schedule completes. Omit for no end."
      +}
  7. Changed1 schema field changed
    • changedInput schema / properties / purpose / enum
      Previous value: -[
      -  "weekly_missing_invoices_total",
      -  "monthly_back_office",
      -  "daily_spending_sweep"
      -]New value: +[
      +  "weekly_missing_invoices_total",
      +  "monthly_back_office",
      +  "daily_spending_sweep",
      +  "agenda_recap_daily",
      +  "daily_due_invoices"
      +]
  8. Changed3 schema fields changed
    • changedInput schema / properties / name / description
      Previous value: -"A short name for the routine, in the user's words."New value: +"The routine's name, as `<Subject> · <moment>`: the subject in the user's own words, then when it runs. The moment is always present, because the report subject, the WhatsApp notice and the run thread title show no rhythm beside the name. Never a cron expression. Inside 60 characters."
    • changedInput schema / properties / name / maxLength
      Previous value: -255New value: +60
    • changedOutput schema / properties / newly_connected / description
      Previous value: -"Tools that connected to this workspace since the last result and that no session was told about yet, oldest first. Present only when at least one tool is new. Start the reply with one line per entry, in the person's language: \"<name> is connected.\". Never fold several entries into one sentence. Each entry comes back once, on one result only: never repeat its line later."New value: +"Tools that connected to this workspace since the last result and that no session was told about yet, oldest first. Present only when at least one tool is new. The connected-line rule says when to tell an entry; when it does, one line per entry, in the person's language: \"<name> is connected.\". Never fold several entries into one sentence. Each entry comes back once, on one result only: never repeat its line later."
  9. Changed1 schema field changed
    • addedInput schema / properties / purpose
      Added value: +{
      +  "description": "The job the routine does, when a recipe of the schedule skill names it, such as \"weekly_missing_invoices_total\" for the missing-invoices total. Omit it for any other routine.",
      +  "enum": [
      +    "weekly_missing_invoices_total",
      +    "monthly_back_office",
      +    "daily_spending_sweep"
      +  ],
      +  "type": "string"
      +}
  10. Added

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses approval-card behavior, draft vs armed states, when verified:true arms nothing outside Well's chat, exceptions that arm without a card, the consent role of approved_tools, and the effects of later edits. These are material behavioral traits not conveyed by readOnlyHint=false, destructiveHint=false, or idempotentHint=false.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is structured with clear sections and front-loads the purpose, but it is very long and dense with edge cases, policy exceptions, and workflow detail. Much of that could be offloaded to the /schedule skill it already references, so it is adequately organized but not appropriately concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity, 22 parameters, nested objects, and high-stakes approval behavior, the description is complete enough for an agent to call it correctly. Since an output schema exists, it does not need to explain return values in detail, and it still notes that the result contains status and next_run_at.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although schema coverage is already 100%, the description adds substantial cross-parameter meaning: send exactly one of cron_expression/trigger_name, event routines take no run_after or max_occurrences, prompt vs method parameter requirements, approved_tools as a signed-off list, and the recipe-specific purpose semantics. This goes well beyond the per-field schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: create one workspace schedule, a job Well runs on a clock or event without anyone in chat. It clearly distinguishes prompt vs method schedules and names sibling alternatives such as well_update_schedule and well_create_task.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use guidance (later time, rhythm, event), when-not-to-use guidance (running a job once now, changing an existing schedule, adding a to-do), and names the alternative tools. It also provides a workflow and tells the agent to load the /schedule skill first.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources