FlowDrop Workflow Specification 1.0-draft

The message poll has its own envelope, with the flags at the top level

The three flags beside the data are what a polling client reads to decide whether to fetch again and whether the turn is over. Folding them into the shared pagination block would break every such client.

The rule

Normative: this is the rule
  1. The message poll answers {success, data, hasMore, hasOlder, sessionStatus} in that order, with no pagination block and no has_more key: the three flags are siblings of data, not nested.
  2. hasMore reports page fullness (whether the page returned as many messages as were asked for) and is an inference.
  3. hasOlder is authoritative: it reports whether messages older than the page exist, so a client scrolling back never pays a speculative empty fetch at an exact page boundary.
  4. sessionStatus rides along so a poller needs no second request to learn the turn has finished.
  5. The forward and backward cursors are honoured only when they are strings of digits; a cursor that is not is ignored, not refused.

What it means

The message poll does not reuse the shared paginated envelope: hasMore, hasOlder and sessionStatus sit beside data, not nested inside a pagination block, and there is no has_more key alongside them. A reader used to the paginated shape elsewhere on this surface would look for the flags in the wrong place.

The two boolean flags answer different questions and are not interchangeable. hasMore only reports whether the page came back as full as it was asked to be — an inference from the count, not a lookup. hasOlder is a real lookup: it tells a client scrolling backward whether anything precedes the page it already has, so it never has to make a speculative fetch just to find out the history has run out. A cursor that is not a string of digits is silently ignored rather than refused, so a poller sending a stale or malformed cursor still gets a window back instead of an error.

Example

An empty session, polled with no cursor at all:

Polling a session with no messages yet200 — counted
GET /api/flowdrop/playground/sessions/{session_id}/messages

{"success": true, "data": [], "hasMore": false, "hasOlder": false, "sessionStatus": }

Sending junk instead of a real cursor (since=abc&before=xyz) does not refuse the request either — it falls back to the default window as if no cursor had been sent.

Rule identifiers are permanent and are never renumbered. Each implementation publishes its own standing against these rules; this specification does not.spec 1.0-draft · PLAY-3 · changed in spec 1.0