Trigger payloads
What a run receives when it fires, which keys the platform reserves, and why a payload that would have to be guessed at is refused instead.
Whatever starts a run, the run receives one thing: a payload. It is a plain key and value structure, and it is the trigger's meaning.
That matters because a run reads the trigger twice. A learning run has an agent read it as text. A codified run selects values out of it by name. Both of those are views of the same payload, and neither is allowed to say something the payload does not. A view may show less. It may never disagree.
Where the payload comes from
| What started the run | What the payload holds |
|---|---|
| A schedule | fired_at, plus schedule_tz when the schedule names a zone |
| A webhook on an authored trigger | The delivery's JSON body, as sent |
| A webhook URL you pasted | The request envelope, below |
| A poll | The item the authored code fetched, or for a mailbox one message: sender, recipients, subject, date, the body text cut to a fixed length, and the name, type and size of each attachment |
| You, from the run button | Nothing |
| A test run | The pinned sample payload, plus anything you typed |
On an authored trigger, a webhook body that is valid JSON but not an object
arrives under the key data. A body that is not JSON at all arrives as text
under the key raw. Neither case is dropped, and neither is guessed at.
The webhook URL envelope
A URL you pasted into another service yourself gets a different shape, because these services put what matters in a query string or a header about as often as they put it in a body. The payload has five keys, always the same five:
| Key | What it holds |
|---|---|
method | The HTTP method the sender used, as a string |
query | The query string, as keys and values |
headers | The request headers, minus the ones consumed to authenticate |
content_type | The content type the sender declared |
body | The parsed JSON body, or the text as sent when it is not JSON |
Write an SOP against those names. A form-encoded body is not split into fields,
so body holds the raw string in that case and a step has to parse it.
Reserved keys
Two keys belong to the platform and win over anything a service sends:
fired_atis stamped on every scheduled occurrence, as a UTC timestamp. It is what lets a step select the occurrence's own time.schedule_tzrides alongside it, and only when the schedule names a timezone.
One more key is reserved by construction. When a trigger carries free text, for
instance the note you type into a test run, that text lands under text.
A payload that would have to be guessed at is refused
The platform will not quietly assemble a payload it cannot vouch for. Three things are errors rather than silent fixes:
- Colliding keys. Two parts of one trigger that both define the same key are refused, rather than one silently overwriting the other. A payload the service did not send must never be presented as what the service sent.
- A part claiming
textwhile the trigger also carries text. Refused for the same reason: something would have to be dropped, and neither choice is defensible. - File attachments. Inbound attachments are not ingested yet, and a trigger carrying one is refused rather than delivered with the attachment missing. This is a real limit, not a warning you can dismiss. An email trigger never carries the files themselves; a message with attachments is delivered with each attachment's name, type and size.
A test run is checked against exactly these rules at the moment you click, using the same code the live path uses. So a payload that would break a run fails at the button with a readable message, instead of dying quietly a few minutes later.
What the agent sees
An agent step is never handed the payload as authority. It is shown a rendering of it, in a message whose provenance is marked, so the agent can tell the difference between the event that started the run and an instruction from you.
That is why the payload is the thing to reason about when you are designing a workflow. The text an agent reads can be reshaped without changing what the run means. The payload cannot.