Skip to content

Routines

A routine is a scheduled APX task. The daemon runs a scheduler tick every 5 seconds and fires any routine that is due. Each routine has a kind, a schedule, an optional spec JSON blob, and optional shell hook arrays (pre_commands / post_commands).

KindLLM?Tools?Description
heartbeatNoLogs a marker. Useful as a “still alive” ping.
shellNoRuns a shell command. Stdout captured.
exec_agentYesNoneLoads a project agent’s prompt, sends spec.prompt, returns plain text. Single call.
super_agentYesAllRuns the default APX agent with the full tool registry. Multi-iteration loop.
telegramNoSends a hardcoded spec.text via the Telegram plugin.

Picking rule of thumb:

  • Need text from a model, no tool calls? → exec_agent.
  • Need orchestration (write files, call MCPs, create tasks, send dynamic Telegram)? → super_agent.
  • Pure shell without LLM? → shell.
  • Fixed Telegram message on a schedule? → telegram.
FormatExamplesNotes
every:<N><unit>every:30s, every:5m, every:24h, every:7dMost common.
once:<iso-8601>once:2026-12-01T08:00:00ZFires once, then disables itself.
Cron expression*/5 * * * *, 0 8 * * *Standard 5-field cron.
Terminal window
apx routine add <name> \
--kind <kind> \
--schedule <schedule> \
[--spec '<json>'] \
[--pre-commands 'cmd1,cmd2'] \
[--post-commands 'cmd'] \
[--skip-prompt-on signal|pre_failure|pre_success|always|never] \
[--permission-mode total|automatico|permiso] \
[--allowed-tools tool1,tool2] \
[--project <name|id|path>]

Kind-specific JSON config:

KindRequired spec keysOptional
exec_agentpromptagent (slug, defaults to default)
super_agentprompt
shellcmd
telegramtext
heartbeat(none)

Comma-separated shell commands. They form a pipeline around the LLM call:

  1. pre_commands run sequentially. Their combined stdout is available as:

    • {{pre_output}} — substituted into spec.prompt before the LLM call.
    • $APX_PRE_OUTPUT — environment variable for post_commands.
    • $APX_PRE_OUTPUT_FILE — path to a temp file with the full output (for large payloads).
  2. The kind handler runs. Its text result is exposed as $APX_LLM_OUTPUT.

  3. post_commands run sequentially with $APX_LLM_OUTPUT, $APX_PRE_OUTPUT, and $APX_STATUS in the environment.

Controls what happens when pre_commands exit non-zero:

ValueBehavior
signal (default)Skip LLM only on SIGINT/SIGTERM; non-zero exit still runs the LLM.
pre_failureSkip LLM + post on any non-zero exit.
pre_successSkip LLM + post unless every pre command exits 0. Same effect as pre_failure in most cases.
alwaysAlways skip the LLM — useful for pure pre→post pipelines.
neverAlways run the LLM, even if pre commands crash.

Overrides the global super_agent.permission_mode for this routine: total | automatico | permiso.

Terminal window
apx routine list [--project <name|id|path>]
apx routine get <name> [--project <name|id|path>]
apx routine history <name> [--project <name|id|path>]
apx routine run <name> [--project <name|id|path>] # force-trigger now
apx routine enable <name> [--project <name|id|path>]
apx routine disable <name> [--project <name|id|path>]
apx routine remove <name> [--project <name|id|path>]
apx
$ apx routine list --project myapp
project #2 routines:
NAME                EN KIND        SCHEDULE         NEXT_RUN              LAST
morning-standup     ✓  exec_agent  every:1h          2026-06-14 10:00:00   ✓ 2026-06-14 09:00:02
daily-weather       ✓  telegram    once:08:00        2026-06-15 08:00:00   ✓ 2026-06-14 08:00:01
healthcheck         ✓  heartbeat   every:5m          2026-06-14 09:35:00   ✓ 2026-06-14 09:30:00
nightly-backup      ✗  shell       once:02:00        —                     ✗ 2026-06-13 02:00:04
apx routine list — name, kind, schedule, enabled, next run, last run
Terminal window
apx routine add daily-weather \
--project myapp \
--kind exec_agent \
--schedule "every:24h" \
--spec '{"agent":"default","prompt":"El clima es {{pre_output}}. Una frase amigable, sin saludos."}' \
--pre-commands "curl -s 'https://wttr.in/London?format=%t+%C+viento+%w'" \
--post-commands 'apx telegram send "$APX_LLM_OUTPUT"'
Terminal window
apx routine add morning-standup \
--project myapp \
--kind super_agent \
--schedule "0 9 * * *" \
--spec '{"prompt":"List open tasks across projects and send me a short summary via Telegram."}' \
--permission-mode automatico
Terminal window
apx routine add db-backup \
--project myapp \
--kind shell \
--schedule "every:24h" \
--spec '{"cmd":"pg_dump mydb > /backups/mydb-$(date +%F).sql"}'
Terminal window
apx routine add deploy-prod \
--project myapp \
--kind super_agent \
--schedule "once:2026-07-01T10:00:00Z" \
--spec '{"prompt":"Run the production deploy checklist and report status."}'
Terminal window
# ✗ Fragile — relies on suppression heuristic
--kind super_agent \
--spec '{"prompt":"El clima es {{pre_output}}. Mandalo por Telegram."}' \
--post-commands 'apx telegram send "$APX_LLM_OUTPUT"'
# ✓ Clean — model writes text, shell delivers it
--kind exec_agent \
--spec '{"prompt":"El clima es {{pre_output}}. Una frase amigable, sin saludos."}' \
--post-commands 'apx telegram send "$APX_LLM_OUTPUT"'
Terminal window
apx routine history <name> --project myapp # last N runs with status and output
apx log -f # tail the unified daemon log
apx messages tail --channel routine -n 20 # last 20 routine-channel messages

A routine that “sends nothing” most often means: enabled: false, next_run_at is in the future, or the LLM returned empty text. Check apx routine history first — the result.text field shows exactly what the model produced.

  • Tasks — per-project TODO list that routines can read and write.
  • Super-agent — the mode that super_agent routines run under.
  • Configuration — global model fallback and permission settings.