Skip to main content
triggers.wait is the consumption half of a webhook-to-agent trigger. This is its precise contract — read it once and the agent loop on agent triggers stops being magic.

Input

Output

nextCursor is the position past every event scanned this call — pass it back on the next call. caughtUp is true once the page reaches the watermark head (nothing more, right now).

Scope: one endpoint, everything it captures

A trigger binds to a single endpoint and yields every event that endpoint captures (minus failed-verification ones, below). There is no event-type filter on triggers.create — it takes endpointId and an optional name label, nothing else.
eventTypes belongs to subscriptions.create, which routes events to a destination. Passing it to triggers.create does not error — unknown fields are stripped — so a filter sent here is silently dropped and you receive the endpoint’s full stream. Filter in your agent, or give the agent its own endpoint.

Short-poll pull, not push

triggers.wait returns immediately with whatever sits past cursor, up to the gapless watermark. It does not block waiting for the next event. The caller re-invokes with nextCursor — promptly while caughtUp is false to drain a backlog, then on its own cadence once caught up. The durable event log is the queue; you set the pace.

At-least-once, ack-by-cursor

The event log is the queue and the cursor is the acknowledgement. Persist nextCursor only after the work for a page succeeds. Crash before persisting it and the next call re-reads those events — never loses them. That makes delivery at-least-once, so dedup on the event id: an event may arrive twice, never zero times.
Advance your stored cursor only after the side effects for a page are durable. Persisting nextCursor before the work turns a crash into silent event loss.

Filtered, but never re-scanned

Events whose verification state is failed are never surfaced — but the cursor still advances past them. They’re read exactly once and never re-scanned, so a stream of failed-verification noise can’t wedge your consumer. Every surfaced event carries its verification state and a vouched flag, so the agent can decide how much to trust each one.

Ordering

Per endpoint, by capture-completion time (received_at) — the order events were captured, not any send order. A trigger is scoped to one endpoint, so within a trigger the order is stable.

Body inlining

includeBody defaults to true: each event carries its payload inlined, read via the engine’s org-scoped payload reader and clamped to maxBodyBytes (≤ 64 KiB). Set includeBody: false when you only need to be woken and will fetch the content elsewhere — it skips the payload fetch entirely.

Errors

The API mirror

Everything here is reachable over HTTP too. triggers.wait mirrors to GET /v1/triggers/{triggerId}/wait, and full CRUD lives at /v1/triggers. Same contract, same cursors — pick the surface that fits your runtime.

Back to agent triggers

The end-to-end flow and a working agent loop.