Documentation Index
Fetch the complete documentation index at: https://docs.crewship.ai/llms.txt
Use this file to discover all available pages before exploring further.
Agent Scheduling
Crewship includes a built-in scheduler that triggers agent runs on a cron schedule. Scheduled runs are fully autonomous — the agent receives a prompt, executes inside its crew container, and the result is recorded as a run with the SCHEDULED trigger type.
How It Works
The scheduler is a background goroutine that manages a pool of cron jobs, one per enabled agent schedule. On startup it loads all agents with schedule_enabled = 1 from the database and registers their cron expressions. Each tick of a cron job triggers a full agent run cycle.
Scheduler goroutine
|
v
cron library fires at scheduled time
|
v
triggerAgent(agent)
|
+--> Create chat session (deterministic ID)
+--> Resolve chat (credentials, system prompt, skills)
+--> Ensure crew container is running
+--> Create run record (trigger: SCHEDULED)
+--> Execute agent via orchestrator.RunAgent
+--> Update run record (COMPLETED or FAILED)
+--> Update schedule_last_run and schedule_next_run
Enabling a Schedule
Schedules attach to a saved routine (pipeline) and fire it on a cron expression. Manage them via crewship routine schedules:
| Subcommand | Purpose |
|---|
list [--slug <routine>] | List schedules in this workspace, optionally filtered by target routine. |
create --slug <routine> --cron '<expr>' [--name ...] [--timezone <IANA>] [--inputs <json>] [--enabled=false] | Create a schedule. --slug and --cron are required; defaults to UTC and enabled. |
update <id> [--cron ...] [--timezone ...] [--name ...] [--enabled / --enabled=false] [--inputs <json>] | Patch one or more fields. |
enable <id> | Enable a paused schedule (fires on next 30 s tick). |
disable <id> | Pause a schedule without deleting it. |
now <id> | Force-fire out of cycle (useful for smoke tests). |
delete <id> [--yes] | Permanently delete; prompts for confirmation unless --yes. |
crewship routine schedules create --slug summarize-text \
--name "daily-summary" --cron "0 9 * * *" --inputs '{"text":"..."}'
crewship routine schedules list --slug summarize-text
crewship routine schedules now <schedule_id>
The same operations are also available on the REST API under /api/v1/workspaces/{ws}/pipeline-schedules — the CLI is a thin wrapper around those endpoints, so server-side behavior (cron parsing, 30 s tick resolution, timezone handling) is identical.
Per-agent schedule_cron fields described elsewhere in this guide are a separate legacy path. New work should go through crewship routine schedules against a saved routine.
The scheduler uses standard 5-field cron expressions:
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-6, Sun=0)
│ │ │ │ │
* * * * *
Examples:
| Expression | Schedule |
|---|
0 9 * * 1-5 | Every weekday at 9:00 AM |
*/15 * * * * | Every 15 minutes |
0 0 * * * | Daily at midnight |
30 8 1 * * | 8:30 AM on the 1st of every month |
0 */2 * * * | Every 2 hours |
Invalid cron expressions are rejected at registration time. The API call will return an error if the expression cannot be parsed.
Execution Flow
Each scheduled trigger follows this sequence:
1. Chat Session Creation
A new chat session is created with a deterministic ID (format: sched_{unixnano}_{random_hex}). The chat title is set to "Scheduled: {agent_name}".
2. Chat Resolution
The ResolveChat call loads the full agent context: credentials, system prompt, skills, MCP servers, network policy, and crew membership. This ensures the scheduled run has the same capabilities as an interactive run.
3. Container Management
If a container provider is configured, the scheduler ensures the crew container is running before execution. Default resource limits:
| Resource | Default |
|---|
| Memory | 4096 MB |
| CPUs | 2.0 |
4. Run Record
A run record is created with trigger type SCHEDULED before execution begins. Metadata includes the CLI adapter, crew info, and a scheduled tag.
5. Agent Execution
The agent runs through orchestrator.RunAgent with the same pipeline as interactive runs: sidecar proxy, credential injection, memory, and conversation history.
6. Result Recording
After execution completes, the run record is updated with:
- Status:
COMPLETED or FAILED
- Duration in milliseconds
- Cost and usage metadata (if available from the LLM provider)
The assistant response is persisted to the conversation store and the message count is incremented.
Timeout
Each scheduled run has a 45-minute timeout. If the agent does not complete within this window, the context is cancelled and the run is marked as failed.
ctx, cancel := context.WithTimeout(s.ctx, 45*time.Minute)
This is separate from the per-agent timeout_secs setting, which controls the LLM execution timeout within the container. The 45-minute limit is the outer boundary for the entire scheduled run cycle including container startup and chat resolution.
Monitoring
Timestamp Fields
The scheduler maintains two fields on each agent:
| Field | Updated | Description |
|---|
schedule_last_run | After each run | ISO 8601 timestamp of the last completed run |
schedule_next_run | After each run and on schedule update | ISO 8601 timestamp of the next scheduled run |
These fields are updated even on error — schedule_next_run always reflects the next trigger time so monitoring dashboards stay accurate.
Run Records
Scheduled runs appear in the standard agent runs list with trigger = "SCHEDULED":
# List scheduled runs for an agent
curl http://localhost:8080/api/v1/agents/{id}/runs?trigger=SCHEDULED
Each run record contains:
trigger: "SCHEDULED"
tags: ["scheduled", "{cli_adapter}"]
duration_ms: execution time
total_cost_usd: LLM cost (if reported)
num_turns: conversation turns
status: COMPLETED or FAILED
Dynamic Updates
When an agent’s schedule is modified via the API, the scheduler hot-reloads the cron entry without restart. The UpdateSchedule method:
- Removes the old cron entry (if any)
- Registers the new cron expression
- Immediately calculates and persists the next run time
Disabling a schedule (schedule_enabled: false) removes the cron entry and stops future triggers. The schedule_last_run timestamp is preserved for audit purposes.
Error Handling
If any step in the trigger pipeline fails (chat creation, resolution, container startup), the scheduler:
- Logs the error
- Updates
schedule_next_run to the next trigger time
- Does not update
schedule_last_run (only updated on successful execution start)
The next scheduled trigger will attempt the full pipeline again. There is no exponential backoff — the cron schedule determines retry timing.
What’s Next