Webhook payload
Agent sends JSON by HTTPS POST to each configured webhook channel. Authenticate the exact received bytes, check freshness and deduplicate before acting. A notification is not an execution report.
Envelope and firing body
Section titled “Envelope and firing body”All envelopes have type, UTC timestamp and data. data.schema is debyko.agent.event/1; data.event_id identifies the event. Fields differ by event type: do not assume every notice is a firing.
For watch.became_true, data contains:
| Field | Meaning |
|---|---|
event_id, firing_id |
The same stable firing identifier for this event; preserve data.firing_id with the position actually opened. |
destination_seq |
Monotonic sequence for this destination; retries do not create a new firing. |
watch |
Saved rule id, version, name, and rule_set (id, name). |
tag |
Configured channel action tag, or null. It is not authorization to execute an unknown action. |
instrument |
Canonical instrument the rule fired for. |
edge |
seq, false_seen_t, true_seen_t, blind_ms, rearm; optional kind for reminder/enabled events. These extra kinds are not sent to Runner channels. |
evaluation |
dql, parsed query, units, effective mode, t, nullable bar_end, evaluated_at, nullable as_of, settled; optional receipt_id. Live-series attempts also include nominal_t, data_as_of, started_at, finished_at, attempt. A retry may use a new data slice. |
fired_at, expires_at |
UTC event time and delivery/action expiry. Do not execute an expired signal. |
answer |
The emitted DQL answer; inspect its values, statuses and provenance. |
answer_truncated, answer_dropped |
Whether the bounded answer omitted detail, and which detail was removed. |
For Arena, debyko_firing_id is the firing_id from the webhook body, specifically data.firing_id, not a destination sequence or a new client-generated UUID. Arena signal verification checks the account/public rule, instrument and entry time; the link does not prove execution.
Event types
Section titled “Event types”watch.became_true: a recorded rule firing.firing.verified: later verification withdata.watch,t,verified_atandfirings[](firing_id,instrument,status, nullablereason); an optionalanswerdescribes contradictions. This event has its own event ID and refers back to original firing IDs.watch.paused,watch.resumed,watch.flapping,watch.blind,watch.recovered: rule status notices, not entry signals. They include the watch and reason/status-specific evidence (for example blindsince,reason,window_s, or recoveredblind_from/blind_to).agent.resumed: account-level recovery notice, without a watch.account.stop_all: the configured stop tag,pressed_at,pausedcounts,expires_atand nullfiring_id; handle separately from entries.watch.test: connectivity/preview test withtest: true, nullfiring_idandedge, optional watch, nullableinstrument/answerand optionalevaluated_at. Never trade a test.destination.verify: channel setup challenge, not a firing. Its data containschallenge,expires_atand nullablereport_token. After verifying the request, answer HTTP 200 with{"verify":"<base64 HMAC-SHA256 of UTF-8 verify.<challenge> under the decoded webhook key>"}. It has no ordinary retry loop; a failed verification must be requested again. It is not an ordinary successful test delivery.
Signature and timestamp headers
Section titled “Signature and timestamp headers”Agent uses Standard Webhooks v1:
webhook-id: stable delivery event ID.webhook-timestamp: Unix seconds for this delivery attempt.webhook-signature: one or more space-separatedv1,<base64 HMAC>signatures; rotation may send two.debyko-attempt: attempt number (informational, not part of the signed input).Content-Type: application/json; charset=utf-8,User-Agent: DEBYKO-Agent/1 (+https://debyko.com).
Decode the base64 secret after its whsec_ prefix. Compute HMAC-SHA256 over UTF-8 webhook-id + "." + webhook-timestamp + "." + raw_body, base64 the digest and compare a v1 signature in constant time. Use a Standard Webhooks library where possible. Require a timestamp within a bounded clock-skew window (for example five minutes), and persist processed event IDs. Do not parse and reserialize before verification; never log the secret or full credentials.
Delivery and retries
Section titled “Delivery and retries”Return a 2xx after safely recording the event for processing. Ordinary delivery retries transport failures, timeouts, HTTP 408/425/429 and 5xx. Other non-2xx statuses are not retried as transient failures. Redirects are not followed. The retry delays are approximately 1, 3, 10, 20 seconds, then 30 seconds, with ±20% jitter; a longer Retry-After on 429 wins. No attempt starts after expires_at.
Retries keep the same body and ID but carry a fresh timestamp/signature. A late verification/correction is a separate event, linked by its original firing IDs. Webhook absence is not a false result for a rule.
Use the existing channel/rule Send test action to verify delivery. Tests have their own IDs and cannot provide an Arena verified firing. Rules and channels · Public rules.