Skip to main content
Trinity
Guides/Scheduling

Scheduling

Cron-based automation for agents using APScheduler. Schedule recurring tasks with timezone support, execution history, and manual triggers.

For a single, agent-initiated, one-shot deferred follow-up rather than a recurring cadence, use Agent Self-Reminders— the durable, one-shot sibling of a cron schedule.

Trinity Platform Demo

May 2026

Concepts

Schedule — A cron expression paired with a message or task sent to an agent at the specified times.
Execution — Each time a schedule fires, it creates an execution record with status, duration, response, cost, and model used.
Autonomy Mode — Master gate for an agent's schedules: nothing fires while autonomy is off. It is a gate, not a bulk edit — it never changes each schedule's own on/off switch, so turning autonomy off and back on restores exactly the schedules you had enabled.
Scheduler Service — Standalone service with Redis distributed locks. Uses async fire-and-forget dispatch with DB polling for status.
Misfire Handling — If the scheduler restarts, missed jobs within a 1-hour grace window are caught up and fired immediately (misfire_grace_time=3600, coalesce=True, max_instances=1).

Timezones

Schedules take any IANA zone name — including legacy aliases like US/Eastern, Asia/Calcutta, and Europe/Kiev. A timezone the platform cannot actually resolve is rejected when you create the schedule, with a message naming the problem, rather than being accepted and then silently never firing.

Schedules from a Template

A template can ship the recurring work its agent is designed to do in a schedules: block, and Trinity creates those schedules when the agent is created — through the UI, the API, and MCP alike. They appear here like any other schedule and are yours to edit, disable, or delete. See Creating Agents.

Keep the message to a bare playbook call. The recommended shape for any schedule message — declared or hand-created — is a single line that invokes one of the agent's skills by name, e.g. /daily-briefing, with no inline instructions. The logic then lives in the versioned playbook, so changing what a scheduled run does is an edit to the skill, never to the schedule. A skill that normally asks questions at its decision points needs a headless mode (the abilities convention is a --autonomous argument) before it goes on a cron; otherwise every run blocks on a prompt nobody sees and burns its whole timeout. See Abilities Marketplace.

Schedule lifecycle: Create (set cron, write prompt, enable) triggers Run (scheduler fires, agent executes, log result)

Creating Schedules

1

Open the agent detail page and go to the scheduling section.

2

Click Create Schedule.

3

Configure: name, cron expression (e.g., 0 9 * * 1-5 for weekdays at 9 AM), message/task, timezone, and description.

4

Optionally select a model override (Fable 5, Sonnet 5, Opus, Haiku, or custom). Fable 5 is the most capable model, for the longest and hardest tasks; Sonnet 5 is fast with a 1M-token context window.

5

Enable or disable individual schedules with the toggle.

6

View execution history with status, duration, and cost.

7

Click Run Now to trigger a schedule immediately.

8

Use the autonomy toggle to pause or resume all of the agent's scheduled work at once. Individual schedules keep their own enabled/disabled state across the toggle — while autonomy is off, an enabled schedule shows a “Will not fire — autonomy off” warning instead of being switched off.

Agent Schedules tab showing three active weekly schedules with cron expressions and execution history

Execution Flow

1

Scheduler fires and sends a POST to /api/internal/execute-task with async_mode=True.

2

Backend spawns a background task and returns immediately.

3

Scheduler polls the database every 10 seconds until execution completes.

4

Execution record is updated with response, cost, and duration.

Schedule API

EndpointMethodDescription
/api/agents/{name}/schedulesGETList schedules
/api/agents/{name}/schedulesPOSTCreate schedule
/api/agents/{name}/schedules/{id}GET/PUT/DELETECRUD operations
/api/agents/{name}/schedules/{id}/enablePOSTEnable schedule (owner/admin)
/api/agents/{name}/schedules/{id}/disablePOSTDisable schedule (owner/admin)
/api/agents/{name}/schedules/{id}/triggerPOSTManual trigger (owner/admin)
/api/agents/{name}/schedules/{id}/executionsGETExecution history
/api/agents/{name}/schedules/{id}/analyticsGETPer-schedule analytics (see below)
/api/agents/{name}/schedules/analytics-summaryGETPer-schedule performance rollup for the whole agent (?window=7d|14d|30d)

Enabling, disabling, and manually triggering a schedule are owner or admin actions — someone the agent is merely shared with can read its schedules and their history but cannot start or stop them. The same applies to the toggle_agent_schedule and trigger_agent_schedule MCP tools.

Per-Schedule Analytics

Each schedule has an analytics view summarizing how it has been performing over a selectable time window.

At-a-Glance Scorecards

Performance shows up in two places without opening any analytics card:

Schedules tab — each schedule row carries inline stats: 7-day success rate, average duration, and a last-run status dot.
Agent Overview tab — a “Schedules performance” section rolls up every schedule for the selected window (success rate, average duration, run count, tool-call count per schedule) and deep-links to the Schedules tab. Tool counts are sampled over the newest runs.

Both are fed by one endpoint: GET /api/agents/{name}/schedules/analytics-summary?window=7d|14d|30d— one row per schedule, including zero-run schedules.

Detailed Analytics Card

1

Open the agent's Schedules tab.

2

Click Show execution history on a schedule.

3

An Analytics card appears below the history with a window toggle (24h / 7d / 30d).

The card shows run counts, success rate, duration percentiles (p50 / p95 / p99), total cost, the top tools the schedule called, and a daily timeline of successes, failures, and cost.

Via the API

GET /api/agents/{name}/schedules/{id}/analytics?window_hours=168
window_hours must be one of 24, 168 (7 days), or 720 (30 days). Default: 168.
Returns execution counts by status, success rate, duration p50/p95/p99, cost totals, the top 5 tool calls, and a gap-filled daily timeline (UTC day buckets).
Read-only — works even when the agent is stopped.

On high-traffic schedules the duration percentiles are computed over the newest 5,000 successful runs; the response reports sampled: true when this cap applies. Counts and the timeline always cover the full window.

Automatic Retry

Failed executions can automatically retry with configurable delay and attempt limits.

Configuration

FieldDefaultRangeDescription
max_retries10-5Max retry attempts (0 = disabled)
retry_delay_seconds6030-600Delay between retries

Retry Behavior

1

Execution fails (error or timeout)

2

If max_retries > 0 and attempts remain, scheduler waits retry_delay_seconds

3

Rate-limit errors (429) use 2x delay, capped at 300 seconds

4

Retry creates a new execution record linked to the original

5

Process repeats until success or max retries exhausted

Execution Grouping

Retries are linked to their original execution:

FieldDescription
attempt_numberWhich attempt (1 = first try, 2 = first retry)
retry_of_execution_idLinks to original execution

The execution list groups retries under their parent execution for clarity.

Execution Statuses

StatusMeaning
pending_retryFailed, retry scheduled but not yet fired
runningRetry in progress
success / failedFinal outcome

MCP Tools

ToolDescription
list_agent_schedules(name)List schedules
create_agent_schedule(name, ...)Create schedule
get_agent_schedule(name, id)Get schedule details
update_agent_schedule(name, id, ...)Update schedule
delete_agent_schedule(name, id)Delete schedule
toggle_agent_schedule(name, id)Enable or disable
trigger_agent_schedule(name, id)Manual trigger
get_schedule_executions(name, id)Execution history

Pre-Check Hook

An optional executable shipped by an agent template that gates each cron tick before Claude is invoked. When present, it lets the agent decide at runtime whether the scheduled work is actually needed — so empty polls (no new PRs, no new emails, no alerts) consume zero tokens.

How It Works

1

Template ships ~/.trinity/pre-check as an executable file with a shebang

2

Before each scheduled cron tick, Trinity runs the file inside the agent container

3

Scheduler acts on the output (see table below)

Pre-check resultScheduler action
No ~/.trinity/pre-check fileFire as usual (backward-compatible)
Exit 0, non-empty stdoutFire — stdout becomes the chat message (overrides schedule's configured message)
Exit 0, empty stdoutSkip — record a skipped execution row, no Claude invocation, zero cost
Exit non-zeroFail-open — log the error and fire with the original message
Timeout (>60s) or errorFail-open — fire with the original message

Key Behaviors

Language-agnostic — hook is exec'd directly; interpreter chosen by shebang
Manual triggers bypass the hook entirely — clicking “Run Now” always fires
Skipped executions appear in the execution list with status skipped, zero cost, and a reason string. They do not count against retry limits
Fail-open — a broken or slow hook never suppresses a scheduled invocation

For Template Authors

Place the hook at ~/.trinity/pre-check (no extension), make it executable (chmod +x), and include a shebang. The hook receives no arguments. Print a work description to stdout if there is work, or print nothing if there is nothing to do.

#!/usr/bin/env python3
import sys
# ... check for new items ...
if new_items:
    print(f"Review {len(new_items)} new PRs: {', '.join(new_items)}")
# else: exit 0 with empty stdout → Trinity records a skip

Per-Schedule Timeout

Each schedule has its own timeout_seconds. It cannot exceed the agent's execution_timeout_seconds cap:

Creating or updating a schedule with timeout_seconds > agent.execution_timeout_seconds returns 400 error=schedule_timeout_exceeds_agent_cap.
Lowering the agent cap below an active schedule's timeout returns 400 error=agent_timeout_below_active_schedules.

Raise the agent cap first, then raise the schedule timeout.

Limitations

Execution timeout is per-agent configurable (default 60 minutes, max 2 hours).
Parallel execution is controlled by per-agent capacity slots (default 3).
Missed jobs are only caught up within the 1-hour grace window.
Retries count against the agent's parallel capacity slots.
Pre-check hooks run with the same permissions as the agent's normal tool calls (developer user inside the container).
A template may declare at most 20 schedules. Beyond that the list is truncated, with the reason reported.
If the agent has freeze schedules if sync failing enabled and its git sync has failed three times in a row, the scheduler skips firing until sync recovers.

See Also

Managing Agents — agent lifecycle, start/stop.
Agent Configuration — autonomy mode, execution timeout.
Agent Loops — bounded sequential task repetition.
Agent Self-Reminders — one-shot, durable, agent-initiated deferred follow-ups.
Approvals — human-in-the-loop gates for scheduled work.
Skills and Playbooks — reusable capabilities agents can run on a schedule.