Skip to content

Cronjobs ​

The Cronjobs page is where you manage everything that runs on a schedule — daily summaries, weekly digests, periodic checks, one-shot reminders. Each row is one entry in the scheduled_tasks table; firing a cronjob either spawns a full task agent or injects a static message into the chat, depending on its action type.

Per-user page. Every user sees and manages their own cronjobs and reminders; nobody else's. The admin sees all of them, with an owner column and owner filter, but only toggles or deletes other users' cronjobs.

Ownership and permissions ​

Each cronjob and reminder belongs to the user who created it (existing ones belong to the first admin account). Cronjob tasks run as their owner — with the owner's workspace, facts and email accounts — and results and reminders are delivered only to the owner (web and the owner's linked Telegram account).

ActionOwnerAdmin on a foreign cronjobOther users
See in the UI / API / /cronjobsyesUI and API: yes. Agent: name, owner and status onlyno
Createyes (for themselves)not for others—
Edityesnono
Enable / disableyesyesno
Deleteyesyesno
Run nowyesnono

For foreign cronjobs the admin's row shows the owner and offers only the enabled toggle and Delete. The same rules apply to the cronjob tools of the agent (create_cronjob, edit_cronjob, remove_cronjob, list_cronjobs, get_cronjob, create_reminder): a regular user's agent only ever sees their own cronjobs, and the admin's agent sees only name, owner and status of other users' cronjobs and may disable or delete them. The /cronjobs slash command lists only your own cronjobs.

What is a cronjob? This page is about operating cronjobs. For the architecture — how the scheduler works, the 5-field cron grammar, auto-disable for one-shot patterns, the 55-second deduplication cooldown, the 5-second past-due grace, and why reminders are a separate tool — see Tasks & Cronjobs concept.

Screenshot of the Axiom Cronjobs list

List view ​

The page is a filter toolbar above a list of scheduled cronjobs: a table on desktop, a stack of cards on mobile (see Mobile layout).

Header actions ​

A single button in the page header:

The Refresh button sits at the right end of the filter toolbar, not in the header.

Filter toolbar ​

Six filters sit at the top (seven for admins, who also get an Owner filter), plus a Refresh button. They combine with AND semantics: pick an action type and a provider and a last-run status to narrow down. Filtering happens client-side on the already-loaded list, so it is instant.

FilterOptions
SearchFree text. Matches against the cronjob name, the prompt, and the names of attached skills (case-insensitive).
Enabled stateAll states, Enabled only, Disabled only. Defaults to Enabled only.
Action typeAll actions, Task, Injection.
ProviderAll providers, Default, or a specific Provider (model) pairing. Only matches Task cronjobs; injections never match a provider filter.
Last run statusAll last runs, Running, Completed, Failed, Never ran.
Schedule typeAll schedules, Recurring, Fixed date.
RefreshRe-fetches /api/cronjobs. The list does not auto-poll, so click this to pull in fresh Last Run info after a fire.

A few details worth knowing:

  • Enabled state defaults to Enabled only. Disabled cronjobs are hidden when the page loads. Switch the filter to All states or Disabled only to see them. Because this is the default, it does not count as an active filter (see the mobile badge below).
  • The Provider dropdown is built from the data, not from the configured-providers list: it only offers providers that some Task cronjob actually uses. The Default entry appears only if at least one Task cronjob runs on the task default, and it selects exactly those.
  • Never ran matches cronjobs that have no Last Run timestamp yet.
  • Schedule type is derived from the cron expression. Fixed date means both the day-of-month and month fields are fixed numbers (e.g. 30 11 30 3 *), so the schedule fires on specific calendar dates at most once a year. That is the shape create_reminder produces for one-shot reminders. Everything else is Recurring.

Columns ​

ColumnNotes
NameThe cronjob name, plus badges for any customizations (see Name badges).
OwnerAdmin only. The user the cronjob belongs to.
ScheduleTop line: human-readable (e.g. "At 09:00 on Sat"). Bottom line: the raw 5-field cron expression.
ActionTask (green) or Injection (amber). See Action types.
ProviderDefault (uses Settings → Tasks), a specific Provider (model), or — for injections (no agent runs). A pinned thinking level is appended (e.g. · Thinking: High).
EnabledA live toggle. Flipping it pauses or resumes the cronjob without deleting it.
Last RunStatus badge (completed / failed / running) plus the local timestamp of the last firing. — if never fired.
⋮Row menu — Edit, Run Now, Delete.

Clicking anywhere else on a row opens the same edit dialog as the menu's Edit item.

Name badges ​

Customizations show up as small badges in the Name cell so you can see at a glance which entries deviate from the defaults. Override badges sit inline next to the name; attached-skill badges get their own line below it.

Inline, next to the name (outline style):

  • custom tools: the cronjob has tool overrides (some tools disabled for this run).
  • custom skills: the cronjob has skill overrides (some skills disabled for this run).
  • custom prompt: the cronjob has a custom system prompt that completely replaces the default task agent system prompt.

On a second line below the name (secondary style):

  • 📎 <skill-name>: one badge per attached skill. Attached skills get their SKILL.md injected directly into the task prompt on every firing. Hover a badge for a tooltip naming the skill. See Tasks & Cronjobs → attached_skills.

A row with no badges runs on the unmodified defaults. On mobile, all badges (overrides and attached skills) share a single wrapping row below the name.

Mobile layout ​

Below the md breakpoint the table is replaced by a vertical stack of cards, one per cronjob. Each card contains the same information as a table row, rearranged:

  • Top row: cronjob name, the Task / Injection badge, and the ⋮ menu (Edit, Run Now, Delete).
  • Badge row: override badges and 📎 attached-skill badges, only shown if the cronjob has any.
  • Schedule: human-readable text with the raw cron expression underneath, next to a Last Run block with status badge and timestamp (or — if never fired).
  • Bottom row: the Provider label (Task cronjobs only) and the Enabled switch.

Tapping anywhere on the card opens the edit dialog, the same as clicking a table row. The switch and the ⋮ menu are exempt from that, so toggling or opening the menu does not open the dialog.

The filter toolbar collapses into a Filters button that opens a popover with all six fields, plus a compact Refresh icon button next to it. The Filters button shows a count badge when any filter differs from its default. Since Enabled only is the default, that filter alone does not produce a badge.

Action types ​

The Action column distinguishes the two cronjob flavors:

BadgeMeaning
TaskEach firing spawns a full task agent with the configured prompt, tools, and skills. Use for anything that needs to think, fetch data, or run tools.
InjectionEach firing inserts the configured prompt verbatim into the parent chat as a system message. No agent runs. Used for static periodic notifications and reminders.

Reminders created via the agent's create_reminder tool show up here with action type Injection — internally they're just cronjobs with a tighter contract. See Tasks & Cronjobs → Reminders.

Enabled toggle ​

The switch in the Enabled column (or on the card, on mobile) flips enabled on the database row immediately. The scheduler skips disabled cronjobs. There is no confirmation dialog: toggling is meant to be a quick, reversible action.

Note that the Enabled state filter defaults to Enabled only, so a cronjob you just switched off disappears from the list. It is not deleted. Set the filter to All states or Disabled only to find it again and switch it back on.

Auto-disable. Some cronjobs disable themselves after firing. If a cron expression matches a single point in time more than 364 days in the future (e.g. 30 11 30 3 * = March 30 at 11:30, fired by create_reminder), the scheduler auto-disables the row after the first run so it doesn't fire again next year. Task-type cronjobs are never auto-disabled.

Row menu (⋮) ​

ItemWhat it does
EditOpens the Create / Edit dialog prefilled with the current cronjob.
Run NowFires the cronjob immediately, ignoring its schedule. Returns a success banner with the cronjob name.
DeleteDestructive — opens a confirmation dialog before removing the row.

Run Now uses the same code path as a scheduled firing: Task cronjobs spawn a fresh task (visible in the Tasks page with trigger cronjob); Injection cronjobs deliver their message into the parent chat right away. Useful for testing a cronjob's prompt without waiting for the next scheduled tick.

Empty state ​

There are two distinct empty states:

  • No cronjobs at all. The list is replaced by a centered message, "No scheduled tasks. Create a cronjob to automate recurring tasks like daily summaries or periodic checks.", with a New Cronjob button right there.
  • No filter matches. You have cronjobs, but none pass the current filters. The message reads "No cronjobs match the filters. Adjust or reset the filters to see more cronjobs." and offers a Reset filters button that restores every filter to its default, including Enabled only for the enabled state.

Because the enabled filter defaults to Enabled only, a fresh install whose only cronjobs are disabled shows the no filter matches state, not the no cronjobs one.

Create / Edit dialog ​

Both New Cronjob and the row's Edit item open the same modal dialog. The form is split into three sections: basics, provider (Task only), and a collapsible Advanced Configuration block (Task only).

Basics ​

FieldNotes
NameRequired. Free text. Shown in the list, in <task_injection> blocks, and on the Tasks detail view.
PromptRequired. For Task: what the task agent should do on each firing. For Injection: the literal text to insert into chat.
ScheduleRequired. 5-field cron expression — minute hour day-of-month month day-of-week. Examples: 0 9 * * * (daily at 9:00), */15 * * * * (every 15 min), 30 14 * * 1-5 (weekdays at 14:30).
Action TypeTask (full agent) or Injection (lightweight). Switching to Injection hides the provider and Advanced Configuration sections — they don't apply.

Schedules are evaluated in the timezone configured under Settings → Agent. Changing the timezone reinterprets every enabled cronjob on the next tick.

Provider ​

Only visible when Action Type is Task. Pick:

  • Default provider — uses whatever is configured under Settings → Tasks. When you later change the default, this cronjob picks it up automatically.
  • A specific Provider (model) pairing — pins the cronjob to that exact provider/model combination regardless of any future default changes.

Each entry expands every provider's enabled models into its own option, so the same provider can appear multiple times for different models.

Thinking level ​

Only visible when Action Type is Task. Default uses the background thinking level at run time; any other value pins the reasoning effort for every run. The list only offers the levels the selected model supports; a stored level the model doesn't support is marked not supported and runs as the nearest supported level.

Codemode ​

Only visible when Action Type is Task. The Scripted tool calls (codemode) control decides whether this cronjob's task agent gets the codemode tool:

ValueBehavior
Inherit (default)Follow the global background-task switch.
OnThis cronjob's runs get codemode even when the global switch is off.
OffThis cronjob's runs never get it, even when the global switch is on.

Tool restrictions still apply inside scripts: a tool you disabled in the tool override list cannot be called from a codemode script. codemode itself is deliberately absent from that list — this three-way control is the only place to manage it.

Advanced Configuration ​

Collapsible section, only available for Task-type cronjobs. The header carries a customized badge whenever any override is set, so you can tell at a glance whether to expand it.

It bundles four overrides:

Tool Overrides ​

A switch for every tool in the agent's tool registry. By default every tool is enabled — flipping a switch off excludes that tool for this cronjob's firings. Newly added tools (after a code update) default to enabled, so disabling here is allowlist-by-exception.

If a previously disabled tool no longer exists (e.g. it was renamed or removed), it shows up below the live list with strike-through styling so you can clean up the dead override.

Skill Overrides ​

Same pattern, but for installed skills. Each row shows the skill's emoji, display name, and ID. Disabled skills stay out of the cronjob's <available_skills> list. As with tools, stale entries appear crossed out so you can remove them.

Attached Skills ​

Different mechanism — these get baked into the prompt. For every selected skill (both agent skills under /data/skills_agent/<name>/ and installed user skills), the runner reads its SKILL.md and prepends it to the spawned task's system prompt under an <attached_skills> block.

This is the deterministic alternative to relying on the agent's routing decision: when a cronjob's reliability depends on a skill (e.g. a daily Nitter scrape that needs the nitter skill's URL conventions), attaching it guarantees the rules are in the prompt every time.

A small tag next to each skill name marks it as either agent or installed. Selected skills also appear as a 📎 badge row at the bottom of the section, mirroring how they show up in the list view.

See Tasks & Cronjobs → attached_skills for the full mechanics.

System Prompt Override ​

A free-text textarea. When set, it completely replaces the default task agent system prompt — including the STATUS / SUMMARY final-message contract, the /workspace pointer, and everything in <task_system>. Leave empty to use the default.

Use sparingly. The defaults exist for a reason; the most common use case is a cronjob that needs a very different persona or output format than a normal task agent.

Submitting ​

The footer has Cancel and Create / Save (depending on mode). The button shows Saving… while the request is in flight; on success the dialog closes and the list reflects the change immediately.

Delete confirmation ​

Selecting Delete from the row menu opens a ConfirmDialog:

Delete cronjob? This will permanently remove the scheduled task. Any running instances will not be affected.

The destructive Delete button is styled red. Confirming removes the scheduled_tasks row and cancels the in-memory timer. Tasks that were already spawned by this cronjob in the past stay visible in the Tasks page — only the schedule itself is gone.

See also ​

  • Tasks & Cronjobs concept — scheduler internals, cron grammar, action types, reminders, attached skills, the OS-scheduler safety rule.
  • Settings → Tasks — defaults that apply to every Task-type cronjob (provider, max duration, loop detection, telegram delivery, status updates, background thinking level, codemode).
  • Settings → Agent — timezone, which controls how cron expressions are interpreted.
  • Tasks — every Task-type firing creates a row there with trigger cronjob.

Released under the MIT License.