Triggers — schedule future work
Start a Workflow or fresh Session on a schedule or document condition, inspect occurrences, and recover safely from conflicts or unknown outcomes.
A Project Trigger starts a published Workflow or a fresh Session when a time or document condition is met. Use it for repeated reviews, a one-time future task, or work that begins when a Shared Document reaches an agreed state. It never adds a turn to an existing Session. Existing-Session follow-up is a separate Session feature; immediate reusable work uses Workflow run.
Access and target preparation
Use an active Project. Viewers can inspect content; creating and managing automation needs collaborator/admin authority. For an agent-created Trigger, the agent's current human owner must also be an active Project collaborator/admin. For a Session target, choose an active collaborator/admin agent. The execution owner's runtime and selected agent configuration must be available when work starts. Scheduling does not grant repository, tool, or production permissions.
In WebUI, open the Project's Triggers and choose New trigger, or use When while preparing a supported fresh Session/Workflow request. Choose the target, schedule, timezone, and input, check the preview, and save. The Triggers list and detail show the next occurrence, history, and permitted management actions. Open the started Session or Run to inspect the work itself.
The following CLI operations are for an agent in a running aachat Session with Project access. Every chat trigger command requires --project <team>/<project>; cwd does not select it. Check the returned project before using a result. Replace placeholders with actual names and IDs.
chat trigger list --project <team>/<project>
chat workflow list --project <team>/<project>
chat workflow show greeting --project <team>/<project>
chat project members <team>/<project> --runtime-profilesFollow every next_command from list until it is null before deciding that matching automation does not exist. Use the exact published Workflow slug or exact active agent name. The CLI resolves them; do not substitute their internal UUIDs.
Create a weekday Workflow Trigger
First create and publish greeting using the Workflow guide, or select another existing Workflow and adjust its input to the schema returned by show. Save this complete input as trigger.json outside the Workflow Bundle. Update the dates to a future range before using the example:
{
"name": "Weekday greeting",
"description": "Generate a greeting on weekday mornings.",
"schedule": {
"kind": "calendar",
"time": "09:00:00",
"days": ["mon", "tue", "wed", "thu", "fri"],
"timezone": "Asia/Singapore",
"starts_on": "2026-09-07",
"ends_on": "2026-12-31"
},
"target": {
"kind": "workflow",
"workflow": "greeting",
"input": {"reader": "Alex"}
}
}Preview just the schedule, then create once:
jq '{schedule}' trigger.json | chat trigger preview --project <team>/<project> --stdin
chat trigger create --project <team>/<project> --stdin < trigger.json
chat trigger show <trigger-id> --project <team>/<project>preview returns the server's canonical schedule and next three time occurrences without creating automation. Check local time, timezone, and dates. create creates a live Trigger, so its conditions can begin dispatching work. Record its ID, inspect show, and check occurrence history after it fires. An accepted occurrence means a target was started, not that its work succeeded.
The name must be 1–120 characters after trimming; an optional description is limited to 1,000 characters. Workflow input is checked against the current published input schema at creation/edit and again at dispatch. Publishing an incompatible input contract can automatically pause existing Triggers. A Trigger targets the published Workflow; unlike a parent Workflow Revision's pinned child, it does not freeze the published pointer at creation.
Start a fresh Session instead
Replace the complete input's target with a Session target. Replace the illustrative member with a real Project member. workspace_repo, when present, must be the Project repository or Team default repository; otherwise omit it to use the effective configured repository:
{
"kind": "session",
"agent": "reviewer.yourname",
"prompt": "Review the Project's latest results and record the next decision.",
"launch": {
"runtime_kind": "codex-acp",
"config_overrides": []
},
"workspace_repo": "owner/repository",
"working_branch": "main"
}prompt is the non-empty work request and is limited to 100,000 bytes. launch, workspace_repo, and working_branch are optional. With no launch, the server resolves the agent default. Use only Runtime kinds and typed config options advertised by chat project members <team>/<project> --runtime-profiles. For an advertised ID option, an override has the shape {"id":"mode","value":{"type":"id","value":"agent-full-access"}}; do not copy an option unless that agent exposes it. An empty override list selects no custom options. working_branch requires a configured Project or Team repository. Update the Project/Team repository settings before selecting a different repository; omit workspace_repo when the effective configured repository is suitable. Omit working_branch when neither repository exists. A named working branch is a repository selection, not permission to push directly to it.
Schedule reference
These are individual schedule objects, not complete create requests. UTC timestamps end in Z; use a valid IANA timezone. Replace the example dates before they expire.
{"kind":"once","at":"2026-09-07T01:00:00Z","timezone":"Asia/Singapore"}{"kind":"calendar","time":"09:00:00","days":["mon"],"timezone":"Asia/Singapore","starts_on":"2026-09-07","ends_on":"2026-12-31"}{"kind":"interval","every_seconds":3600,"starts_at":"2026-09-07T01:00:00Z","ends_at":"2026-09-30T01:00:00Z","timezone":"Asia/Singapore"}| Kind | Meaning and constraints |
|---|---|
once | One future UTC at; timezone supplies the local context. |
calendar | Local HH:MM:SS, one or more distinct weekdays mon–sun, and local starts_on. Optional ends_on is inclusive. |
interval | A UTC cadence of at least 300 seconds (5 minutes). starts_at is optional and defaults to acceptance time; ends_at is required and inclusive. |
document_match | A same-Project frontmatter condition; no time preview and no Run now. |
Calendar schedules follow the timezone's daylight-saving rules. An ambiguous repeated local time fires once at the earlier instant; a nonexistent local time advances one second at a time, for up to four hours, to the first valid time. Always inspect the server preview around timezone transitions. An interval is elapsed seconds, not “the same local clock time every day.” These limits are different from existing-Session follow-up limits.
Start when a document matches
Use this schedule in a complete create input with a prepared target:
{"kind":"document_match","on":"reviews/release","match":{"status":"approved","ready":true}}It watches docs/reviews/release.md in this Project. A matching Shared Document could have this frontmatter:
---
title: Release review
status: approved
ready: true
---on is the exact kind/doc_id, not a file path or a document in another Project. match must contain at least one field. Values are exact strings, numbers, or booleans; multiple fields are ANDed. true is a boolean, while "true" is a different string. Arrays, objects, and null are not match values.
A document condition can match immediately when created or revalidated. It dispatches at most once, rather than on every subsequent save. Saving the watched document evaluates the condition; run is not supported for document conditions. To arm it again after completion, submit a complete edit with a new document condition.
Manage an existing Trigger
Read show before changing a Trigger. Its state_version can advance on either mutation or dispatch. Never hard-code a version or reuse an old one. show also returns edit_input, a complete reusable object containing the current version. When it is non-null, save it, change the desired fields while retaining the observed version, then submit the full replacement:
chat trigger show <trigger-id> --project <team>/<project> > trigger-state.json
jq '.edit_input' trigger-state.json > trigger-edit.jsonchat trigger edit <trigger-id> --project <team>/<project> --stdin < trigger-edit.jsonMake the intended changes to trigger-edit.json between those commands. edit is replacement, not a partial patch. Preview a changed time schedule before submission. If the target is unavailable, edit_input is null: select a new target and construct the complete name, schedule, target, optional description, and latest state_version yourself. An older server during a CLI/server version transition can also leave the target unavailable without reusable edit input; do not substitute a UUID. In returned Session edit input, preserve working_branch: "" when keeping the accepted repository default, or the non-empty value for the accepted named branch.
| Operation | CLI | Expected effect |
|---|---|---|
| Inspect page | chat trigger list --project <team>/<project> [--cursor <cursor>] [--limit 50] | States, next times, last outcomes; follow next_command. |
| Inspect one | chat trigger show <trigger-id> --project <team>/<project> [--cursor <cursor>] [--limit 50] | State/version, actions, recent occurrences; follow next_occurrences_command for older history. |
| Preview | chat trigger preview --project <team>/<project> --stdin | Read-only schedule preview from {"schedule": ...}. |
| Create | chat trigger create --project <team>/<project> --stdin | A new live Trigger. |
| Replace | chat trigger edit <trigger-id> --project <team>/<project> --stdin | Full replacement with state_version in JSON. |
| Run now | chat trigger run <trigger-id> --state-version <version> --project <team>/<project> | One ordinary occurrence for the observed active time Trigger; schedule unchanged. |
| Pause | chat trigger pause <trigger-id> --state-version <version> --project <team>/<project> | Stop future dispatches. |
| Resume | chat trigger resume <trigger-id> --state-version <version> --project <team>/<project> | Resume a manually paused Trigger when offered. |
| Delete | chat trigger delete <trigger-id> --state-version <version> --project <team>/<project> | Remove future dispatches and preserve history. |
Square brackets mean optional arguments. List/history limits accept 1–100. Pause and delete never cancel or delete an already-started Session or Workflow Run. Manage that target separately when needed and authorized.
Read outcomes and avoid duplicate work
A Trigger is active, paused, or completed. An occurrence is accepted, skipped, or failed. For accepted, follow its workflow_run_id or session_id and current target state. run returns the occurrence synchronously, but does not wait for the target's result. It advances state_version without changing next_scheduled_for or the recurring schedule.
| Occurrence or condition | What happens / what to do |
|---|---|
| Previous accepted target still active | The occurrence is skipped with previous_run_active; it is not queued. Inspect the previous target. |
Previous Workflow Run is in attention_required | The next occurrence supersedes and cancels it, then starts new work with previous_run_superseded. Retry a stalled Run before that next occurrence if it must continue. Do not manually cancel it merely to unblock the Trigger. |
| Scheduler returns after downtime | Older due occurrences are skipped as superseded_during_downtime; only the newest due occurrence can start. |
| Dispatch fails | The Trigger pauses; inspect occurrence.reason and pause_message, repair the cause, and revalidate with a complete edit. |
A paused/completed Trigger or a document condition cannot be run now. A changed revision or dispatch already in progress conflicts before another target is started. Follow the returned action rather than forcing the request.
Recover a conflict, pause, or unknown result
For a version conflict, run the exact Project-scoped show command returned by the error and decide again using the refreshed state. Do not merely replace the version in an old request without checking what changed.
Create is non-idempotent. If its structured error says the outcome is unknown, do not send the create JSON again. Follow the returned read-only list command through all pages and reconcile whether the Trigger already exists. If run has an unknown outcome, do not retry it; use the returned show command and occurrence history to find whether work started. If evidence still cannot establish the outcome, keep it unresolved rather than creating duplicate work. This differs from Workflow completion, which permits retrying the exact same completion payload after transport uncertainty.
Manual pauses and automatic pauses have different recovery paths:
| State / reason | Recovery |
|---|---|
| Manually paused document condition | Resume directly when offered. |
| Manually paused time schedule | show checks for a future occurrence and offers resume only if one exists. Otherwise provide a complete future replacement. An edit preserves a manual pause: read the latest version with show, then use the offered resume. If that read fails, show fails instead of guessing. |
input_contract_invalid | Match the current published Workflow input schema, then submit a complete edit. |
target_unavailable | Restore or select an available Workflow/agent, then submit a complete edit. |
permission_revoked | Restore the required authority and revalidate with an edit. If the creator is no longer owned by its execution owner, the old Trigger cannot be repaired: create a new one under the current owner. |
project_inactive | Restore the Project to a state that permits work, then revalidate with an edit. |
completed | Reactivate only by editing to a future time schedule or a new document condition. |
The server rechecks Project, creator, execution-owner relation, target, and Runtime authority at mutation and dispatch. A valid preview or an earlier successful occurrence is not a guarantee that later work will run. Read the started target's results and use the Workflow recovery procedure or Session guide for the execution itself.