Triggers and Schedules

A loop’s triggers say what starts a run. A conversation is the default: a person starts the run through a delivery. The other three triggers start a headless run, a run with no user.

TriggerWhat starts a run
conversationA person, through the embed, the SDK or your own interface.
scheduleA time, written as a five-field cron, in UTC.
event with source: webhookA signed POST from your own system.
event with source: collectionA record written to one of the loop’s collections.
apiYour server, through the run API.

Rules for a run with no user

  • It has a subject and no user. The subject is what the run works on, read from the payload or fixed by the schedule. The per-user cap counts per subject.
  • It cannot ask anyone a question. A run with no user is never offered ask_user. A step can still wait for your decision.
  • It must send its result somewhere. Publish refuses a headless loop with no outputs.
  • Its input is data, never instructions. A webhook body, a record or a schedule’s subject reaches the run as untrusted content.
  • A flood is stopped before a model runs. concurrency caps how many runs one trigger may have in flight. It is required on event and api triggers, and optional on schedule.
  • The entry agent must be able to read the payload. Publish refuses the trigger otherwise.

On a schedule

triggers:
  - kind: schedule
    cron: "0 9 * * 1"        # 09:00 UTC every Monday
    subject: weekly_digest

Publishing the version installs the schedule, and the loop’s detail on Loops shows it. A new version moves the schedule to that version. Archiving the loop removes it.

Schedules lists every schedule in the account. For each one you can Run now, pause, resume or delete it, and read its recent runs with what each cost. A run that woke an agent says so and links to the run it woke.

Each firing starts one run, with the subject the trigger names.

From a signed webhook

triggers:
  - kind: event
    source: webhook
    subject: $.lead_id       # where the payload names what the run works on
    concurrency: 5
    secret_ref: ssm:/…       # where the signing secret lives

A loop can declare one webhook trigger. If secret_ref is wrong, publish refuses it and names the path it expects.

Once the version is published, the loop’s page shows the webhook’s address with Copy the address, and a form to store its secret. Every request is refused until the secret is stored. The value is never shown again, and storing a new one replaces it.

Sign each request with the Pio-Signature header: the same scheme as the platform’s outbound webhooks. Webhooks shows the header, the limits and every refusal.

From a new record

triggers:
  - kind: event
    source: collection
    collection: leads
    subject: $.lead_id
    concurrency: 2

Each record written to leads starts one run. The collection must be one the loop declares. Records that such a run writes start nothing, so collection triggers never chain. To do a second step, do it in the same run, or in a schedule that reads the collection.

When the trigger is at its concurrency cap, the write still lands, and its run ends at once as cancelled, in words that name the fix.

From your server

An api trigger lets your server start headless runs with POST /api/runs/batch, up to 25 at a time, under an API key. See Runs.