app.startup
Fires exactly once when the Maestro application launches. Ideal for workspace setup, dependency installation, health checks, or any initialization that should happen once per session. Required fields: None beyond the universalname, event, and either prompt or prompt_file.
Behavior:
- Fires once per application launch
- Does NOT re-fire when toggling Cue on/off in Settings
- Does not re-fire on YAML hot-reload (deduplication by subscription name)
- Resets on session removal (so re-adding the session fires again on next app launch)
- Not affected by sleep/wake reconciliation
- Works with
fan_out,filter,output_prompt, andprompt_file
time.heartbeat
Fires on a periodic timer. The subscription triggers immediately when the engine starts, then repeats at the configured interval. Required fields:
Behavior:
- Fires immediately on engine start (or when the subscription is first loaded)
- Reconciles missed intervals after system sleep - if your machine sleeps through one or more intervals, Cue fires a catch-up event on wake
- The interval resets after each trigger, not after each run completes
{{CUE_TRIGGER_NAME}} and {{CUE_EVENT_TIMESTAMP}}.
time.scheduled
Fires at specific times and days of the week - a cron-like trigger for precise scheduling. Required fields:
Optional fields:
Behavior:
- Checks every 60 seconds if the current time matches any
schedule_timesentry - If
schedule_daysis set, the current day must also match - Does not fire immediately on engine start (unlike
time.heartbeat) - Multiple times per day are supported - add multiple entries to
schedule_times
time.once
Fires exactly once at a specific wall-clock moment, then deletes itself fromcue.yaml. This is the subsystem to reach for when a user says “in 20 minutes do X”, “tomorrow at 9am email me a summary”, “remind me at 4pm to push the rc branch”, or “schedule a 1h check-in” - anything that maps to a single action tied to a clock.
Required fields:
Optional fields:
Behavior:
- Poll-based at roughly 30-second granularity
- Fires once when the wall clock crosses
fire_at - Self-destructs from
cue.yamlafter a successful run (statuscompleted) - On
failedortimeout, also self-destructs unlessself_destruct_on_failure: false - Supports all standard
actionvalues:prompt(default, runs the configured agent with the rendered prompt),notify(surfaces a toast through the owning agent - clicking it jumps there), andcommand(shell or CLI invocation) - The CLI command
maestro-cli cue scheduleis the supported way to createtime.oncesubs - it handles ISO formatting, timezone offsets,target_node_keygeneration, and writes directly to the owning agent’s.maestro/cue.yaml. Do not hand-authortime.oncesubscriptions.
The standard
{{CUE_TRIGGER_NAME}}, {{CUE_EVENT_TYPE}}, {{CUE_EVENT_TIMESTAMP}}, and {{CUE_PIPELINE_NAME}} variables are also available.
Creating, listing, and cancelling:
file.changed
Fires when files matching a glob pattern are created, modified, or deleted. Required fields:
Behavior:
- Monitors for
add,change, andunlink(delete) events - Debounces by 5 seconds per file - rapid saves to the same file produce a single event
- The glob is evaluated relative to the project root
- Standard glob syntax:
*matches within a directory,**matches across directories
The
changeType field is also available in filters.
agent.completed
Fires when another Maestro agent finishes a task. This is the foundation for agent chaining - building multi-step pipelines where one agent’s completion triggers the next. Required fields:
Behavior:
- Single source (string): Fires immediately when the named agent completes
- Multiple sources (list): Waits for all named agents to complete before firing (fan-in). See Fan-In
- The source agent’s output is captured and available via
{{CUE_SOURCE_OUTPUT}}(truncated to 5,000 characters) - Matches agent names as shown in the Left Bar
These fields are also available in filters.
The
triggeredBy field is particularly useful when a source agent has multiple Cue subscriptions but you only want to chain from a specific one. See Selective Chaining for a complete example.
task.pending
Watches markdown files for unchecked task items (- [ ]) and fires when pending tasks are found.
Required fields:
Optional fields:
Behavior:
- Scans files matching the glob pattern at the configured interval
- Fires when unchecked tasks (
- [ ]) are found - Only fires when the task list changes (new tasks appear or existing ones are modified)
- The full task list is formatted and available via
{{CUE_TASK_LIST}} - File content (truncated to 10K characters) is available via
{{CUE_TASK_CONTENT}}
github.pull_request
Polls GitHub for new pull requests using the GitHub CLI (gh).
Optional fields:
Behavior:
- Requires the GitHub CLI (
gh) to be installed and authenticated - On first run, seeds the “seen” list with existing PRs - only new PRs trigger events
- Tracks seen PRs in a local database with 30-day retention
- Auto-detects the repository from the git remote if
repois not specified
github.issue
Polls GitHub for new issues using the GitHub CLI (gh). Behaves identically to github.pull_request but for issues.
Optional fields:
Behavior:
Same as
github.pull_request - requires GitHub CLI, seeds on first run, tracks seen issues.
Example:
github.pull_request, except:
The branch-specific variables (
{{CUE_GH_BRANCH}}, {{CUE_GH_BASE_BRANCH}}) are not available for issues.
cli.trigger
Fires only when explicitly triggered from the command line viamaestro-cli cue trigger <name>. Unlike other event types, cli.trigger has no background watcher or poller - it waits for a manual invocation.
No additional fields required - just name, event, prompt, and optionally enabled.
Behavior:
- Does nothing on its own - only fires when you run
maestro-cli cue trigger <subscription-name> - Supports an optional
--promptflag to override or supply the prompt at invocation time - The override text is available in the prompt template as
{{CUE_CLI_PROMPT}} - Ideal for deployment scripts, CI/CD integration, on-demand reviews, or ad-hoc automation
webhook.received
Fires when an external service POSTs to Maestro’s local webhook listener. This is the generic escape hatch: anything that can send an HTTP request - GitHub, GitLab, Slack, a CI system, a cron box, your own script - can drive a Cue pipeline, and the filter decides which payloads matter. Required fields:webhook sub-fields:
A secret is mandatory. A webhook path with no authentication is a remote trigger for an AI agent running with your credentials, so a subscription without
secret or secret_env fails config validation rather than quietly starting to listen.
The listener:
- One listener serves every webhook subscription across every agent. It starts when the first one loads and stops when the last one unloads.
- Binds to
127.0.0.1:17997by default. Override withMAESTRO_CUE_WEBHOOK_PORTandMAESTRO_CUE_WEBHOOK_HOST. - To take deliveries from the public internet, point a tunnel (ngrok, cloudflared) or a reverse proxy at the loopback port. Binding the listener itself to
0.0.0.0is possible but puts an agent trigger directly on your network. - Only
POSTis accepted. Bodies over 1 MB are rejected with413. - Multiple subscriptions may share a
path. Each authenticates independently, and every one that passes receives the delivery.
signature_header, the sender presents the secret:
Authorization: Bearer <secret> works too.
With signature_header, the sender signs the raw body with HMAC-SHA256 and sends the digest in that header. Both bare hex and the sha256=<hex> form GitHub and GitLab use are accepted - so pointing a GitHub webhook at Maestro with signature_header: X-Hub-Signature-256 and the same secret works with no glue code.
Example:
Template variables:
Secrets never reach the payload: the
Authorization, Cookie, X-Maestro-Cue-Secret, and configured signature headers are stripped before the event is built, so they cannot leak into a prompt, the activity log, or the Cue database.