Guides

Operating runs

See what your scheduled work did, start, pause or cancel it, get alerts when it fails and keep it safe through deploys and backups.

Markdown tasks and code workflows share one run history and one set of controls. The hubzoid schedule commands on the server can do everything. Settings shows runs, schedules and health, and starts a code workflow with Run now. People you allow can also start, pause, resume and cancel runs from chat. Every control is recorded in the audit log.

This guide uses the my-hub starter with the Monday brief from markdown tasks. Use it when you look after a Hub that runs scheduled work: to see what ran, start something now, stop a schedule during an incident, set up alerts, prepare a deploy or work out why a run did not happen.

What you need

  • A Hub with at least one markdown task or code workflow, such as my-hub with schedule/monday-brief.md.
  • A terminal on the machine that runs the Hub.

Check what ran

List the scheduled work

Terminal
hubzoid schedule list my-hub

Each markdown task and code workflow is listed with its trigger, state, next run and the account it runs as, or why it cannot run. The command exits 1 when a task file is invalid.

Read the recent runs

Terminal
hubzoid schedule status my-hub

This shows each workflow's state, next run and missed slots, the 20 most recent runs with their status, duration and error, and each markdown task's history: when it was first seen, when it last ran, its last result and its last log.

Read them in Settings

Open Settings → Activity → Runs. It lists the runs of every agent you manage, newest first, and filters by agent, status, time and run id.

Settings, Activity, Runs: filters for agent, status, time and run id, and one run of md:monday-brief on My Hub with the status Succeeded and a result that starts with Published.Settings, Activity, Runs: filters for agent, status, time and run id, and one run of md:monday-brief on My Hub with the status Succeeded and a result that starts with Published.
Every agent's runs in one list. Open a run to see its steps.

Each agent's Workflows tab lists its own workflows, each with a status line, the account it runs as and View runs. See runs in Settings for every screen.

Commands

Every control is a hubzoid schedule command on the server. See the CLI reference for every option.

All schedule commands and how they read names
CommandWhat it does
hubzoid schedule list [hub]Every task and workflow with its trigger, state, next run and account.
hubzoid schedule status [hub]Recent runs, errors, missed slots and each task's history.
hubzoid schedule run <hub> <name>Queues one run now and waits for its result.
hubzoid schedule pause <hub> <name>Stops scheduled runs of one task or workflow until resumed.
hubzoid schedule resume <hub> <name>Resumes scheduled runs.
hubzoid schedule cancel <hub> <run-id>Cancels a queued or running run.
hubzoid schedule deliveries [hub]Webhook events and alert deliveries, without their payloads.
hubzoid schedule redrive <event-id> --hub <hub>Retries a failed webhook event, after you check its side effects.

list, status and deliveries use the current folder when you leave out the Hub, and list, status and deliveries take --json. <name> is a markdown task name, with or without the md: prefix, or a code workflow's function name, where hyphens are read as underscores. Markdown task names are matched first. Run ids come from hubzoid schedule status or Settings.

Run now

hubzoid schedule run queues the run on the same queue a scheduled run would use, so it never overlaps one, and it ignores the schedule, pauses and the wait for chat. In Settings, Run now on the agent's Workflows tab starts a code workflow as a team run.

Run options, exit codes and Run now in Settings

For a markdown task it accepts --timeout, --max-rounds, --model and --dry-run, as described in markdown tasks. For a code workflow, --input key=value passes typed inputs, --dry-run names the file it would run without running any code, and the other three options are refused. The command prints the result and the links of any live reports the run published. It exits 0 on success, 1 when the run failed or ended incomplete, and 2 when the name is unknown, an input is invalid or the workflow does not load.

In Settings, Run now shows a form for the workflow's inputs first when it has any. If a run is already queued or running, Settings says so and starts nothing. If Settings says you can't run it, give yourself run access on the agent's Access tab, under Workflow permissions. Markdown tasks and code workflows both have Copy run command in the row's menu, which copies the server command. Webhook workflows have neither.

Pause and resume

Terminal
hubzoid schedule pause my-hub monday-brief
hubzoid schedule resume my-hub monday-brief

A pause stops scheduled runs. Runs already queued or running continue.

What a pause does and does not stop

A pause is stored in the operational database, so every bridge on a shared database sees it, and it is checked again right before each run is queued.

  • Runs already queued or running continue. Cancel them if they must stop.
  • Manual runs of a paused task or workflow still work.
  • On resume, a markdown task that became due while paused runs once. A code workflow runs at its next slot without catching up.
  • A schedule whose scheduled runs fail 20 times in a row is paused automatically. See alerts.

Cancel

Terminal
hubzoid schedule cancel my-hub md:monday-brief:manual-20261025T210247

Only a queued or running run can be cancelled. Work already done is not undone.

How a cancel takes effect

For any other run the command reports its status and does nothing. A queued run is cancelled before it starts. A running run stops at its next step. Work already done is not undone: a sent message, a git push or a script's effects stay. Cancelling a webhook run fails its event, which then waits for an explicit redrive.

From chat

Two capabilities on the agent's Access tab, under Hubzoid tools, then Workflows, let people work with runs from chat or an assistant:

CapabilityWhat it allows
See workflows and runs (workflows_view)List the agent's workflows and schedules, their state, next and last run, and recent runs with their steps.
Run and control workflows (workflows_manage, sensitive)Start a run now, pause or resume a schedule, and cancel a queued or running run.

Nobody has them until they are granted. A run started from chat acts as the workflow's own account, never as the person asking.

How chat controls are checked and where they work

The tools act only on the agent they run in. A run started from chat acts as the workflow's own account, never as the person asking, and that person is recorded as the one who started it. The agent names the workflow and waits for a yes before it acts, but the grant, the check on every call and the audit are the real controls. The tools work in the web app, the API, MCP, WhatsApp and Telegram, and are never offered on Slack or inside a scheduled run. HUBZOID_WORKFLOW_TOOLS=false in a Hub's .env removes them from that agent.

Who did what

Each control is written to the audit log. Read it in Settings → Activity → Audit log.

What the audit log records for each control

A server command records the operator as cli:<user>@<host>. A start from chat or Run now records the person and where they acted. Server commands act with the authority of whoever can run them on the server.

Read the Workflows tab

Each workflow on the agent's Workflows tab has one status line that says whether it will run. Banners at the top flag a stopped scheduler, runs missed while the agent was stopped and a workflow that could not be loaded.

Every status line and what it means
Status lineMeaning
On. Runs (when). Next run (time).Scheduled and on time.
On. Runs when its webhook receives an event.Started by a named webhook or the inbox.
Runs when someone starts it.No schedule.
Off. Turn it on with enabled: true in (file).A markdown task with enabled: false.
Schedules are offA code workflow on a machine without HUBZOID_SCHEDULES=1, or HUBZOID_DISABLE_SCHEDULE is set.
Paused. Resume it with hubzoid schedule resume.An operator, a person in chat or the failure limit paused it.
The scheduler stopped. Restart the agent to run it again.No heartbeat from the scheduler for 150 seconds.
Can't run: (reason)The file could not be loaded, or the account it runs as cannot be used.

Open View runs to list a workflow's runs, newest first, with how each one started (Team schedule, Personal schedule, Chat, Run now, CLI, Webhook or Update now), who started it, the account it ran as, its inputs and its result. Open a run to see each step with its output or error.

Run status labels and who sees a result
LabelMeaning
QueuedWaiting for a slot in its queue.
RunningStarted and not finished. A run interrupted by a stop stays here until the Hub starts again and resumes it.
SucceededFinished. A markdown run that ended incomplete shows here too, with incomplete in its result.
FailedThe run raised an error, including a markdown run that ended error.
Gave upThe engine stopped trying to recover the run.
CancelledCancelled by an operator, or at start because the workflow code changed.

A run's result belongs to the account it acted as. The Hub's managers see its workflow, status, timing and a failure summary, while the result, step outputs and detailed errors read as Private. hubzoid schedule status on the server shows everything.

People's own schedules

When a workflow lets people run it and schedule it for themselves (see Run for me), each person manages theirs in chat or in Settings → My schedules. Administrators see Settings → Team schedules: everyone's schedules with their 30-day model cost, to pause or stop, and every live report with its company link. See schedules and reports.

When a personal schedule pauses or does not run

A personal schedule pauses itself, with the reason shown, after three failures in a row, when the person's access changes or when the workflow's inputs change. Only an administrator resumes a schedule an administrator paused. People's schedules run only while the Hub runs with code workflows on, so a laptop that sleeps does not run them.

Alerts

Alerts tell you about problems without anyone watching Settings. Each one is stored, then delivered and retried up to five times. They are off until you set a destination.

my-hub/workflows/settings.yaml
alerts:
  to:
    - webhook: ALERT_WEBHOOK_URL     # an environment variable that holds the URL
    - slack: OPS_SLACK_WEBHOOK_URL   # a Slack incoming webhook, also from the environment
    - email: ops@example.com
  cooldown: 1h
  failures_in_a_row: 3
  pause_after_failures: 20
Every alert and when it fires
AlertWhen
A failed runA code workflow or markdown task run fails. A webhook event alerts only after its last attempt.
Failures in a rowA workflow fails failures_in_a_row times in a row, 3 by default. One alert per streak.
A paused scheduleScheduled runs fail pause_after_failures times in a row, 20 by default, and the schedule is paused. Manual runs, runs started in Settings and webhook runs do not count. 0 turns this off.
An overdue runA code workflow run passes its deadline.
A stopped scheduleA code workflow's schedule stopped firing.
A failed eval suiteA scheduled eval suite has a failing case.
A content mismatchA webhook event key arrives again with different content.
A stale engineA Hub's workflow engine stops reporting, and again when it recovers.
Cooldowns, destinations, signing and delivery
  • Failed runs, overdue runs, failed eval suites and stopped schedules have a cooldown per workflow, one hour unless cooldown says otherwise, and the next alert counts what the cooldown held back.
  • alert_to= on a code workflow, or alert_to: in a markdown task, replaces the Hub destinations for that workflow. alerts: {to: []} turns alerts off for a Hub. on_failure from older releases still works as one webhook destination. HUBZOID_ALERT_URL is the deployment's fallback webhook.
  • An alert carries the Hub, its kind, a link to Settings and, when they apply, the workflow, the run id and a count. Run output and error text stay on the server.
  • A webhook delivery is a JSON POST with Idempotency-Key and X-Hubzoid-Timestamp headers. With HUBZOID_ALERT_SECRET set, it also carries X-Hubzoid-Signature: sha256= and the hex HMAC-SHA256 of the timestamp, a . and the raw body. Email uses the deployment's SMTP settings, and preview mode writes to .hubzoid/alert-preview/.
  • Delivery is at least once. A receiver can see a repeat after a network failure, so deduplicate on the idempotency key.
  • A missing destination or a delivery that ran out of attempts shows in hubzoid schedule deliveries, never as a success.
  • The first start of a Hub looks back 24 hours. Older failures are not alerted. After that, downtime of any length is caught up.

Missed slots

Markdown tasks catch up once after downtime or a pause. Code workflows do not catch up. hubzoid schedule status prints a missed count per workflow.

Catch-up rules in detail
  • Markdown tasks catch up once after downtime or a pause. The catch-up run records how many extra slots it stood in for in the task's missed_log in .hubzoid/schedule-state.json, kept for 31 days.
  • Code workflows do not catch up. When the scheduler falls behind, or a backup hold ends, only the latest due slot runs and earlier ones count as missed. When the Hub starts more than 90 seconds after the last heartbeat, it counts the slots that fell in the gap, logs a warning and shows a banner in Settings. A workflow declared with catch_up=True runs the latest missed slot once, unless its next slot is close.

Concurrency limits

Markdown tasks run one at a time per Hub. Each code workflow runs one at a time, and different workflows run side by side.

Capping concurrency and slots that overlap

To cap how many code workflows run at once in a Hub, set max_concurrent_workflows: N in workflows/settings.yaml and restart. A workflow with its own concurrency=N or concurrency_key has a separate queue and limit, as described in webhooks.

A code workflow slot that comes due while the previous run is still going waits and runs after it. If a workflow often takes longer than its interval, runs pile up, so choose an interval longer than a typical run.

Drain before a deploy

Runs belong to the code that started them. When the Hub starts under different code, runs that were queued or interrupted under the old code are cancelled so they cannot block a queue, and show as Cancelled.

How code changes affect queued and running work

The code is a hash of the installed Hubzoid version and every workflows/**/*.py file. Markdown runs that were queued but not started are queued again, with :requeued added to the id. Webhook events that never started run on the new code, and an event whose attempt had started is failed for an explicit redrive.

At shutdown, runs in flight get up to 5 seconds to finish. Anything still running resumes at the next start if the code has not changed.

To avoid cancelled runs, drain first:

Stop new runs

Pause the schedules you are about to change with hubzoid schedule pause, or pick a moment between slots.

Wait for the queue to empty

Run hubzoid schedule status my-hub until no run is PENDING or ENQUEUED. Cancel any you do not need.

Deploy and restart

Deploy the change or upgrade Hubzoid, then restart the Hub. When hubzoid run serves several Hubs, hubzoid restart <hub> restarts one of them. See upgrading.

Resume and catch up

Resume what you paused. If a cancelled run is still needed, start a fresh one with hubzoid schedule run.

Backup holds

hubzoid backup holds new scheduled runs for every Hub in the deployment while it copies, and chat keeps working. See backup and restore.

Waiting, release and what a hold refuses

It first waits up to --wait seconds (default 600) for running runs to finish. If runs are still going, the backup stops with Scheduled runs are still in progress and names them. Try again later, cancel them, or pass --wait 0 to take the backup anyway.

When the backup ends, the hold is released. Due markdown tasks then run once, and each code workflow runs the latest slot that fell inside the hold. A hold also expires on its own if the backup process dies. While a hold is active, hubzoid doctor warns under scheduler.health, and a start from chat or Run now is refused.

Health checks

hubzoid doctor my-hub reads without changing anything. Add --json for stable check ids. See the doctor reference.

Workflow checks and the uptime endpoint
CheckReports
schedule.tasksEvery schedule/*.md parses, or which files are invalid and why.
workflows.definitionsEvery code workflow loads, with its schedule and time zone.
scheduler.healthA backup hold, a failed dispatch, a scheduler with no recent heartbeat, or paused work.
deps.sqliteThe workflow engine can run on this Python's SQLite.

For an external uptime monitor, the public port answers GET /healthz/workflows with 200 while every Hub's workflow engine is healthy and 503 otherwise. The answer names no Hub and no error. Monitor it from another machine, because a host cannot report its own failure, and supervise the process separately.

If something goes wrong

What you seeWhat to do
A code workflow never runs and Settings says schedules are offSet HUBZOID_SCHEDULES=1 in the Hub's .env and restart, or run it in a deployment of several Hubs.
The scheduler stopped. Restart the agent to run it again.The Hub process stopped or crashed. Restart it. Slots missed meanwhile are counted, not run.
Can't run: and a definition errorRun hubzoid doctor my-hub, fix the file named under workflows.definitions and restart.
A markdown task is due but does not startThe Hub is answering chat, the task is paused, a backup holds runs, or HUBZOID_DISABLE_SCHEDULE is set. Wait, resume it, let the backup finish, or remove the variable and restart.
Runs show Cancelled after a deployThey were queued or interrupted under the old code. Drain before deploys and start a fresh run if needed.
No alert arrivesNo destination is set, its environment variable is missing, or delivery failed. Check hubzoid schedule deliveries my-hub.
More problems and fixes
What you seeWhat to do
A workflow offered for Run for me is missing in chatTurn code workflows on, grant the person Run for that workflow, check HUBZOID_WORKFLOW_TOOLS and restart after adding workflow code.
Workflows are off for a Hub, with an error in workflow healthworkflows/settings.yaml is not valid. Fix it and restart. Chat and other Hubs keep running.
A new markdown task has not run yetIt first runs at its next future match. Run it now with hubzoid schedule run.
The first markdown task never fires on a running HubThe scheduler starts only when the Hub starts with a task. Restart the Hub.
A markdown run ends incompleteIt reached max_rounds without STATUS: DONE. Raise timeout or max_rounds, or give the body a clear done condition and have it save progress.
A run failed with interrupted by a restartThe Hub stopped during the work step, which is never repeated. The next slot runs the task.
An outside system received the same change twiceA code workflow step was interrupted and ran again. Make the step safe to repeat: a key the other system deduplicates on, a check before writing, or a marker in hub.state.
A schedule is paused and nobody paused itIts scheduled runs failed 20 times in a row. Fix the cause, then hubzoid schedule resume.
A person's schedule is pausedIt failed three times in a row, or their access or the workflow's inputs changed. They check the reason in My schedules, then resume or edit it.
git pull --rebase failedThe remote moved and the rebase conflicted. Resolve it on the server. The commit is local and nothing was pushed.
is not inside a git repositoryThe task declares commit: but the Hub is not in a git checkout. Set up the repository, or use write:.
has no account to run asAdd run_as, set HUBZOID_WORKFLOW_USER, or sign in once as the owner.
no signed-in account exists for that emailThe configured account has never signed in. Have that person sign in once, or change the account.
awaiting approval, blocked or was replaced, or has no access to hubThe configured account cannot be used. Approve it, choose another account, or give it Use this agent. Hubzoid never falls back to another account.
A restricted tool is refused inside a runGrant the permission to the account the run acts as, or point run_as at an account that holds it. See restrict tools.
A run's result shows as PrivateResults belong to the account the run acted as. Sign in as that account, or use hubzoid schedule status on the server.
ModelOutputError fails a code workflowThe model's reply did not match the requested shape. Tighten the prompt or the Pydantic model.
The engine does not start on Python 3.12 (deps.sqlite fails)That Python links SQLite older than 3.42. Use a Python build with a newer SQLite, such as python.org, Homebrew, Debian 13 or Ubuntu 24.04, or PostgreSQL.
Scheduled runs are still in progress from hubzoid backupTry later, cancel the runs, or pass --wait 0.
A named webhook answers 401 or 503See webhooks and check workflow health.
A webhook event shows as failedCheck its side effects, then hubzoid schedule redrive <event-id> --hub my-hub.
The generic webhook answers forbiddenCheck WEBHOOK_INBOUND_SECRET and WEBHOOK_INBOUND_HMAC. See inbox authentication.

Next steps

Choose which cookies Hubzoid can use. You can change this at any time from Cookie settings in the footer. Read the Cookie Policy for details.