Triggers
A trigger node is how a canvas graph declares the events that start it.
It’s the inbound side of a graph: emit nodes fire events out, trigger
nodes bring events in. On publish, a graph’s trigger nodes register the
graph as an event handler, so the same wiring you’d set up with
cryo handler set happens from the canvas.
Two transports: bus and webhook
Section titled “Two transports: bus and webhook”A trigger node has a transport that says how the world reaches it:
bus(the default) subscribes to the project event bus. The graph runs whenever a matching event fires - a finished run, acryo emit, a delivery another hook republished.webhookgives the graph its own inbound HTTP endpoint. Publishing the graph mints the URL and a signing secret; a POST to that URL starts the graph. Use it to catch a forge push, or any external system, directly.
A trigger with no transport is a bus trigger, so graphs authored
before webhook triggers existed keep working unchanged.
Bus triggers
Section titled “Bus triggers”A bus trigger names the event pattern that starts the run:
{ "id": "on_failure", "type": "trigger", "config": { "event": "run.failed" } }The event value is an event-type pattern, the same kind a handler’s
on list takes:
- an exact type -
run.failed,deploy-done - a prefix wildcard -
run.*matchesrun.succeeded,run.failed,run.cancelled *- every event
Webhook triggers
Section titled “Webhook triggers”A webhook trigger owns an endpoint the graph provisions on publish:
{ "id": "on_push", "type": "trigger", "config": { "transport": "webhook", "manifest": "github", "event": "push" } }manifest(optional) selects signed-delivery verification and payload shaping for a known sender.githubverifies theX-Hub-Signature-256HMAC and normalizes the push into fields likeshaandbranch. Leave it off for a plain token-secret webhook.event(optional) filters which delivery subtype starts the run (push,pull_request). Empty runs on any delivery.
The endpoint is an ordinary event hook
underneath, named graph.<graph>.<node>, and its deliveries reach the bus
like any other hook’s. What differs is who owns it:
that section has
the three things that decide which to reach for.
One consequence of the endpoint being keyed to the node: renaming the
trigger node re-mints it. Publishing after a rename drops
graph.<graph>.<old-id> and creates graph.<graph>.<new-id> with a new
URL and a new secret, so whatever was posting to the old one is now
posting nowhere. Re-register the sender, or leave a live trigger node’s id
alone.
Publishing the graph mints the endpoint; the trigger inspector shows the
ingest URL, a one-time secret, and a Register on forge control that
creates the webhook on the repo for you (GitHub, Gitea, or Forgejo) given
a repo and a forge admin credential - no manual paste. Or add it to your
repo’s webhook settings by hand with the shown URL + secret. The secret
is shown once - a re-publish keeps the same one. A token trigger’s secret
can be replaced from the Connections page (rotate secret) or with cryo event-hook rotate <name>; a manifest trigger signs with a key instead,
which is replaced by deleting the hook and publishing again.
CI from a repo walks through the whole push-to-build
path.
What the node outputs
Section titled “What the node outputs”The node’s output is the event, or shaped delivery, that started the
run. Downstream nodes read it through nodes.<trigger-id>.output, and
because a graph receives the triggering event as its run input, they
can read the same envelope through input. A run.failed bus trigger
reads input.payload.error, input.payload.run_id, and the rest of the
lifecycle payload; a github
webhook trigger reads input.sha, input.ref, and the other shaped
fields (repo, sender).
A webhook trigger with no manifest is not shaped, so it hands you the delivery as it arrived:
{ "body": { "sku": "TENT-2P", "qty": 12 }, "query": { "source": "shop" } }Read a posted field as input.payload.body.sku and a query-string one as
input.payload.query.source - not input.sku, which is the shaped
github case above and is the mistake this shape invites. Query values
are always strings; body values keep their JSON types. A POST with no body
at all arrives as an empty object, so input.payload.body.sku finds
nothing rather than failing; a body that is not JSON (form-encoded, plain
text) arrives verbatim as a string, so guard when you expect one.
The sender authenticates with the secret in the X-Cryo-Hook-Secret
header - see events and handlers
for a worked curl.
Publishing registers a handler
Section titled “Publishing registers a handler”When you publish a graph, its trigger nodes reconcile into an
event-handler registration named after the graph. The handler’s on
list is the union of every trigger node’s event. Publish a graph with
two bus trigger nodes (run.failed and deploy-done) and it registers
as a graph handler matching both.
This is the canvas-native equivalent of:
cryo handler set <graph> --graph <graph> --on run.failed,deploy-doneA webhook trigger also provisions its owned endpoint at this point and subscribes the graph to the event that endpoint emits, so there’s no separate hook or handler to set up - the trigger node is the whole ingress.
Remove all the trigger nodes and republish, and the registration (and any owned webhook) is dropped - the graph goes back to being a workflow you run by hand or spawn, with no event subscription.
Worked example: notify on failure
Section titled “Worked example: notify on failure”A notify graph wires one trigger to one connector node. The trigger starts the graph on any failed run; the connector posts the error to Matrix:
{ "version": "cryosleep-graph/v1", "nodes": [ { "id": "on_failure", "type": "trigger", "config": { "event": "run.failed" } }, { "id": "post", "type": "matrix.send_message", "config": { "with": { "homeserver": "https://matrix.example", "room_id": "!abc:example" }, "input": { "text": { "$template": "run failed: {{ input.payload.error }}" } }, "credential": "matrix" } } ], "edges": [ { "from": "on_failure", "to": "post" } ]}Publish it, and every run.failed on the project bus posts to the room.
No separate subscription to set up - the trigger node is the
subscription.
See also
Section titled “See also”- Connectors - the outbound API call the example uses.
- Events and handlers - what handlers are, what a graph handler receives, and how emit nodes fire events out.
- Event catalog - discovering which events you can put in a trigger node.