Triggers
A trigger is how a session starts, or how a parked one resumes. Each arrival is a firing. For every trigger the environment’s published version declares, the platform keeps a deployment: the scheduler, the polling cursor or the registration that makes the trigger fire. You declare triggers in the editor; publishing deploys them.
Declaring a trigger
Section titled “Declaring a trigger”A trigger is declared under the triggers: of the state it enters, keyed by its id. That state
is the trigger’s start state, and a trigger has at most one. A state may be the entry for several
triggers, each with its own declaration:
states: intake: triggers: manual: description: Look into one order. requires: - order_id nightly: type: schedule cron: "0 2 * * *" timezone: Europe/Berlin order-hook: type: webhook connection: orders-hook guards: body.type: - order.created - order.paid new-email: type: ap piece: microsoft-outlook trigger: newEmail connection: outlook-support guards: from.emailAddress.address: "*@example.com" instructions: Work out what arrived and answer it. This state is terminal. chat-answer: triggers: chat: session: triggers.-1.threadId connection: support-widget examples: - Where is my order? mcp: description: Answer one question about an order. requires: - question connection: partner-agents instructions: Answer the question directly. This state is terminal.The id is authored: adding, reordering or removing one declaration leaves every other id, and so
every other deployment, as it was. In the editor, a state’s Trigger section adds triggers
through one picker (Manual, Chat, MCP, Schedule, Webhook and Completion under the platform, then
each collection’s triggers) and expands each into its settings. manual, chat and mcp are held by
at most one state each, so assigning one to a state moves it there. See the harness’s
triggers guide for what the runtime reads.
The trigger kinds
Section titled “The trigger kinds”| Trigger | Declared as | Starts a session when | Deployed |
|---|---|---|---|
manual |
manual: |
you start it from the editor or the Sessions page, an evaluation runs a case, or another workflow calls it | never: nothing to deploy |
chat |
chat: |
a message arrives: from the Chat page, the editor’s chat surface, or the endpoint of the AG-UI incoming connection it names | only when it names a connection |
mcp |
mcp: |
an MCP client calls the workflow’s tool at the endpoint of the MCP incoming connection it names | only when it names a connection |
| schedule | type: schedule, cron, timezone |
the cron expression matches, read in timezone (UTC when unset) |
yes |
| webhook | type: webhook, connection |
an HTTP POST reaches the endpoint of the webhook incoming connection it names |
only when it names a connection |
| piece trigger | type: ap, piece, trigger, connection, props |
the piece reports a new item, by polling or by calling back | yes |
| completion | type: completion, workflow |
a turn of a production session of the named workflow succeeds or fails | yes, with no scheduler or address |
The editor lists a piece trigger’s properties under its connection. Each one the piece requires carries a Required flag, which turns into a warning while the property holds no value. A property whose options come from the connection (a spreadsheet, a folder, a channel) opens a picker. The picker also takes a value it does not list: type it into the search and choose Use this value.
The editor authors a signature on manual and mcp: requires lists the variables a start must
supply, each a name or { name, type, description }, and returns the variables the session
guarantees when it completes. A start missing one, or supplying a value of the wrong type, is
refused before anything executes.
A type: file entry’s value is a path from the workspace root that names one file.
- Starting by hand: you upload the file. The platform places it in the new session’s
attachments/and sets the variable to its path. Uploads take at most 20 MiB in one start. - Through the API: a start may name a path instead. It can be a file in the session, such as
attachments/invoice.pdf, or one in the agent’s workspace, such asskills/billing/assets/template.pdf. - A path that is not well-formed is refused like any other value of the wrong type.
- A path that names no file the session may read is refused by the runtime when the session opens, before the agent runs. The turn fails with a message naming the variable.
An mcp trigger declares no type: file entry, in either list. An MCP call can neither hand a
session a file nor receive one, so validation reports the entry as an error, and the editor
offers File on manual only.
chat takes up to six examples, the prompts the Chat page
offers before a chat’s first message, and mcp takes trace, whether a call’s result carries the
agent’s messages and tool calls. Endpoint triggers are covered in Chat, AG-UI and MCP endpoints.
Firings
Section titled “Firings”A firing first resolves its session (see Sessions and decisions). A firing
that starts one opens a session at the trigger’s start state; a firing for a parked session is
delivered into it. Either way the firing’s payload is appended to the turn’s triggers variable,
oldest first, so the firing that just arrived is always triggers.-1 and its fields sit directly
on it (triggers.-1.subject). A manual start and an MCP call carry variables instead of a payload
and seed no triggers variable.
A session opens with the firing’s words when it carries any, decided in this order:
- the trigger’s message path, a dotted path such as
triggers.-1.body.content, orfalsefor a trigger whose firings carry no message; - without one, the payload’s own top-level
message,textorcontent, the first that is a non-empty string; - otherwise a notice naming the trigger.
The trigger’s session path decides which session a firing belongs to: firings that resolve the
same value continue one session. Both paths are fields of an event trigger’s row in the
inspector. A chat trigger’s session path is the platform’s own and is shown read-only.
A payload too large to seed becomes a marker naming its size and its top-level keys; the full payload stays readable in the trigger’s past firings.
Deployments
Section titled “Deployments”Deployments are computed from the environment’s current published version alone, never from the draft. A trigger you have saved but not published is not deployed, and publishing is what deploys it. The platform reconciles an environment’s deployments after:
- a publish, a version restore or a promotion into it;
- a credential change in it, or in an environment it inherits credentials from;
- a member’s Retry now on a failing deployment;
- an automatic retry of a deployment in
errorthat has fallen due.
A pass activates what is missing, re-activates what changed, and deactivates what the version
does not declare. A deployment that is active and unchanged is left alone, keeping its polling
cursor, and one failing activation never stops the others. A deployment is active, inactive,
or error with its message. Two triggers configured identically are two deployments, each opening
its own sessions.
chat, mcp and webhook are endpoint triggers: they deploy only when their declaration
names an incoming connection of the matching
protocol, whose endpoint is their address. The address belongs to the connection and is never
rotated by a publish. One that names none is still startable from inside the product: chat from
the Chat page, mcp from the editor’s ▶, and webhook through a listen window.
Deleting an environment or an agent takes its deployments down first, unregistering any callback address from its service. Reconciling every environment at once is an operator action (see Operating a deployment).
Schedule, webhook and piece triggers
Section titled “Schedule, webhook and piece triggers”A schedule fires on its five-field cron expression, each firing opening one session whose
payload records when it fired (scheduledAt, firedAt). The Sessions board lists every active
schedule’s next firing at the top of its Planned column.
A webhook is reached at /api/webhooks/<token>, the endpoint of the webhook incoming
connection it names, which admits a delivery by its authentication mode and rate limit. An
admitted POST becomes the payload { method, headers, query, body }: the body parsed when it
is JSON, and only the content-type, user-agent and x-request-id headers. The endpoint answers
202 with a delivery id. A sender’s X-Delivery-Id header, or failing that a digest of the body,
makes a retried delivery fire once. An address that serves no active deployment answers 404 and
reveals nothing more.
A piece trigger is one of the triggers an Activepieces collection offers. It authenticates
through its connection, or through the collection’s only connection when it names none; with
several and none named, its deployment fails rather than guessing. A missing connection is a
warning in the editor and error on the deployment, never a reason the workflow cannot be saved.
- A polling trigger is polled once a minute. Each poll opens one session per new item and
moves the cursor past them, so no item fires twice. A failed poll is recorded and polling goes
on; five failures in a row put the deployment in
error. - A callback trigger has the platform
register an address of its own,
/api/callbacks/<token>, with the piece’s service when it is activated, and unregister it when it is deactivated. The address is kept for the life of the deployment. Each request the service sends opens one session per item it carries; a request that carries none, such as a ping, opens nothing.
A piece trigger’s code runs in a worker, never in the platform’s API or dispatcher processes. Its activation, every poll, each request a callback trigger’s service sends, each renewal of its registration, a test in a listen window and its deactivation each run in a worker of their own. That worker holds only the credential of the trigger’s connection, and reads and writes the deployment’s own store, such as its polling cursor or its registration’s id, through the platform. When a service checks a callback address with a handshake before it accepts it, the piece’s answer is computed the same way while the service waits.
Completion triggers
Section titled “Completion triggers”A completion trigger lets a workflow look back at
another workflow’s sessions, to rate how helpful a chat was, classify what a session was about or
follow up on it. It names the other workflow under workflow:
states: rate: triggers: rate-support: type: completion workflow: support-chat guards: trigger: chat tools: allow: - sessions__read_subject - tool: sessions__set_attributes args: session: "${{triggers.-1.session}}" instructions: >- Read the chat with sessions__read_subject, rate how helpful the last reply was from 1 to 5, and record it with sessions__set_attributes as helpfulness, passing session "${{triggers.-1.session}}".-
When it fires. Each turn of a production session of
support-chatthat ends fires it once:- a turn that succeeded;
- a turn that failed after it started, through
archmax_raise, a tool’s error or a refused return.
It never fires for a turn a member stopped, for a turn that failed before it started (a firing a spend cap refused), or for a parked turn. A parked turn fires once it is resumed and ends. Testing sessions and evaluation cases fire nothing. Neither does a session that a completion trigger opened, so a chain or a loop of completion firings cannot form. Guard on
statusto look back at only successes or only failures. -
One session per firing. Every firing opens a session of its own about the finished session, its subject session. A completion trigger takes no session path. The session it opens belongs to the member the subject belongs to, so a rating of a member’s personal chat is personal too.
-
The payload.
triggers.-1describes the subject session:session,workflow,turn,status(succeededorfailed),trigger(what that turn was taken through),origin,turnCountandfinishedAt, plustitle,state,tags,attributes,returns,startedAtand, for a failed turn,error(its first 2,000 characters) when they are set. It carries no message, so the session opens with a notice naming the trigger unless you declare a message path. -
Reading and recording. The payload does not include the transcript. The Sessions tools read and record it (see Session attributes):
sessions__read_subjectreads the subject’s transcript, turn by turn;sessions__set_attributeswithsession: "${{triggers.-1.session}}"writes the verdict onto the subject, where the Sessions table can show it as a column. The guard in the example binds the argument to that session.
-
Validation and deployment. The trigger must name a workflow other than its own that the environment holds; validation reports anything else as an error. Its deployment is
activewith no scheduler or address. It is inerrorwhile the published version does not hold the named workflow, and the next publish that does activates it.
Trigger guards
Section titled “Trigger guards”A webhook, piece or completion trigger may declare guards: payload field paths, each with one glob pattern
or a list of them, the same shape a tool’s argument guards take. A firing reaches a session only
when every guarded field matches one of its patterns. * matches within one
/-separated segment and ** across segments, a list value is matched as its comma-joined
elements, a missing or null field matches nothing, and matching is case-sensitive. A pattern
cannot read a variable, since no session exists yet.
A firing that fails a guard is declined: it starts nothing, is delivered into nothing, and is logged naming the field, while the deployment stays healthy. Editing a guard does not re-activate the deployment or reset its cursor. In the editor, the trigger’s shield control offers the fields recent firings carried (and a piece’s sample payload, or a completion trigger’s payload fields) or any path you type, and the guard’s editor offers the values those firings carried.
Testing a trigger
Section titled “Testing a trigger”The ▶ beside a start state starts a session through its trigger; on a state with several
triggers it first lists them. For manual and mcp it first asks for the declared variables when
the entry declares any, typed and prefilled from the latest turn (a File input is chosen again),
then starts. For chat it opens the chat surface over the graph.
In the session view, a manual start takes the next turn on the selected session rather than
opening a new one. For an event trigger it opens a
listen window for 120 seconds:
- when the trigger’s deployment is active and deploys what the draft declares, the window watches it, and the next firing it receives opens the session;
- otherwise the window listens on the draft and changes no deployment. A webhook gets a test address that accepts deliveries only while the window waits. A schedule fires once, immediately. A polling trigger runs a test poll and fires the first item that passes the guards. A callback trigger whose piece can read recent events from its service fires the first of them; one whose piece cannot is tested once it is published.
- A completion trigger fires once, immediately, whether its window watches the deployment or the draft. It fires about the newest finished turn of the named workflow, succeeded or failed, among its 20 newest, that passes the guards. Testing sessions count, so you can run the named workflow from the editor and then listen. With nothing to look back at, the window fails and says why.
A session a listen window opens is a testing session and executes the draft. Listen again re-arms a spent window. The same row offers the trigger’s past firings: choosing one replays its payload as a new testing session. A replay is refused when the current definition does not bind the trigger, or when the payload fails its guards.
Retries
Section titled “Retries”A deployment that enters error is retried on its own: 15 minutes after the first failure in a
row, then 30 minutes, 1, 2 and 4 hours. The sixth failure in a row exhausts its
retries: it stays in error and only a publish,
a credential change or Retry now tries it again. Those make a failing deployment due at once
without resetting its count. The count returns to zero when one of its polls, renewals or callback
requests succeeds, or, for a deployment that polls nothing, when it activates. Endpoint triggers
fail only on their connection, or an mcp trigger on a type: file entry, which no retry fixes;
every reconciliation pass, such as the next publish, evaluates them again.
In the inspector, the row of a trigger the published version deploys shows its deployment’s status: Active, or Failing with the message and when it is retried, or that it stopped retrying, together with Retry now. A trigger only the draft declares shows no status.
A workflow that is out of service
Section titled “A workflow that is out of service”A firing that would start a session of a workflow declaring disabled: true is declined: no
session opens, and the deployment stays active with its cursor and its address. A firing for one
of its parked sessions is still delivered.