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 wake an agent stops being magic.

Input

FieldTypeNotes
triggerIduuidThe trigger to consume from.
cursorstring | nullOpaque resume position. Omit or pass null to start from the oldest retained event.
limitint ≤ 200Max events this page.
includeBodybool, default trueInline the bounded payload body on each event.
maxBodyBytesint ≤ 64 KiBClamp for the inlined body.

Output

{
  "events": [/* AgentTriggerEvent[], each with its verification state + vouched flag */],
  "nextCursor": "…",
  "caughtUp": true
}
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).

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

CodeMeaning
NOT_FOUNDUnknown, revoked, or cross-org trigger.
VALIDATION_ERRORMalformed cursor, or a cursor below the retained window — restart from the beginning by omitting cursor.
UNAUTHORIZEDMissing or invalid bearer.
RATE_LIMITEDBack off and retry.

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 waking an agent

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