Pagination

Pagination uses cursors to traverse collections.

List and run results can be paginated. Use the cursor returned by a response as an opaque continuation value, process that response's items, and stop only when next_cursor is null.

Pagination belongs to the exact fetched output and input schema for a list operation. Read Envelope and errors before interpreting the enclosing result, and read Capability ids before using a list operation that has not been discovered in the current workspace.

Pagination fields

A paginated result returns the current items array and continuation fields. The request can accept a cursor and limit only when its fetched schema defines them. A caller must not add cursor to a capability that does not publish it, because the exact input schema is the authority for supported request fields and their accepted ranges.

next_cursor is opaque. It is a value issued by one response for one operation and workspace context. Do not calculate, parse, trim, append to, or replace it. Pass it unchanged as the next request cursor only after the current page is processed and only while the response says another page exists.

has_more and next_cursor agree in the response contract: has_more is true exactly when next_cursor is not null. Treat next_cursor as the continuation value and has_more as a convenient boolean for UI and loop control. A final page has null next_cursor and false has_more, even when the final page still has items to process.

The item shape is capability-specific. A run list can return run records, a run-events read can return event records, and another list capability can return its own workspace objects. Do not assume that all item arrays have an id field with the same meaning. Read the fetched output schema before persisting or displaying rows.

FieldTypeWhen presentMeaningDefault
limitintegerOptional when a capability supports itMaximum items to return, subject to the fetched schema range.Capability-specific
cursoropaque stringOptional after first pageContinuation returned by the preceding response for this operation.None
itemsarrayResult fieldThe current page of capability-specific result records.[] when no records
next_cursoropaque string or nullResult fieldPass it as cursor for the next page, or stop when null.null on final page
has_morebooleanResult fieldTrue exactly when next_cursor is not null.false on final page
Representative page shape
{
  "items": [],
  "next_cursor": "cursor_from_this_response",
  "has_more": true
}

Continue from the returned cursor

Start with a first request that omits cursor unless the fetched contract explicitly gives you a starting cursor. Process every item returned in that page. If next_cursor is a string, submit that same string in the next request. Repeat until the response returns next_cursor as null. This sequence is the only supported way to traverse a cursor result.

A limit is a request-size preference only when the contract supports it. Use the range in the current input schema, not a remembered default from another list. A smaller limit can make an interactive reader more responsive; a larger valid limit can reduce request count. Neither choice lets a caller skip cursor ordering or assume that the total result set is stable while other workspace changes occur.

Preserve the response that issued each cursor. It records the selected workspace, operation, current items, trace id, and continuation. A cursor copied from another operation or another workspace is not a generic page number. If client state loses the issuing response, restart discovery and list again rather than constructing a replacement cursor.

Architect can iterate a list page by page. It should report the current page's evidence, retain the returned continuation, and stop when it sees null. An agent should not claim that it processed every record after only seeing the first page, and it should not use a raw item count as proof that a later page does not exist.

List the current runs a page at a time. Process every item in each returned page, pass each next_cursor unchanged into the next read, and stop only when next_cursor is null. Report the final page count and run ids.

Controls that expose cursors

The shared run controls include a list of canonical runs needing attention and an events read for one run. The events control takes a run id and can take a cursor and limit. Read the run id from an earlier response, then use the returned event cursor only for that run's event stream. A run id and an event cursor have different meanings and cannot substitute for each other.

Capability-specific list operations define their own fields and limits. The catalog descriptor exposes the exact input schema for a selected operation, including whether cursor and limit exist. Search or get the capability before sending a paginated request, especially when a provider connection, workspace scope, or feature availability can affect the live contract.

The CLI supports dreamstate runs list, dreamstate runs events <run_id>, and other canonical run commands. Architect and MCP expose runs_list and runs_events. These are shared controls, not capability ids, but their argument schemas remain the authority for cursor use and result shape.

A result may be synchronous while its items describe asynchronous work. A runs list page is a read of known run state; a listed run can still be active. Read its status or events before deciding that a run succeeded, failed, or needs cancellation. Pagination reads evidence, it does not change the lifecycle of the listed run.

ControlArgumentsPage result
runs_listoptional cursor, optional limitCurrent run page with its continuation fields.
runs_eventsrun_id, optional cursor, optional limitEvent page for one run with its continuation fields.
Capability list readContract-specific cursor and limit where supportedThe schema-defined item page and continuation.

Use each response as the source of truth

Cursor pagination does not promise a hand-built snapshot across unrelated changes. Treat every returned page as the source of truth for that request. If records change while a client walks pages, retain the returned ids and trace data, then make a fresh read when the application needs a later view of the current workspace state.

Do not deduplicate, sort, or merge pages by an assumed identifier before you read the capability's output schema. A particular capability may expose a natural object id, an event id, a receipt id, or no universally named id at all. The output contract determines the safe merge key and the semantics of duplicate-looking records.

A paginated success still uses the canonical response envelope. Check ok before reading items. On failure, retain error.code, details, and trace id. A failed continuation does not authorize substituting a cursor from another operation, and a success page does not authorize a later mutation without its fetched contract.

When a response provides a web_url for a state-bearing object, use the URL for app navigation and preserve the JSON object id for later reads. Do not infer the next cursor from URL query text. Cursors are transport values produced by the API response, while web URLs are user-facing navigation destinations.

When it goes wrong

If a continuation returns invalid_request, read the current request schema and error details. Check that cursor is exactly the value from the preceding response and that limit is within the published range. Do not repair the failure by trimming, decoding, or inventing a cursor value.

If the operation returns capability_not_fetched, search or get the list capability in the current turn before running it. If the tool turn expired or the catalog changed, begin fresh discovery and use the new descriptor. A cursor does not make an unfetched or stale contract runnable.

If a run read reports an active or asynchronous result, keep its run id and continue reading status or events instead of starting another run. If events are paginated, use each returned cursor only with the same run id. A later event page is evidence about that run, not a retry instruction for the original capability.

If a network failure occurs after a page response is received, persist the page and its next_cursor before making the following request. If the response itself was lost, make a fresh read and compare returned evidence; do not assume a guessed continuation recreates the lost page.

If a client must mutate an item selected from a list, fetch the mutation capability and validate its current contract separately. Listing an item does not deliver a mutation contract, does not establish a quote, and does not bypass sender, provider, idempotency, mode, or owner-action requirements for the later effect.

A cursor is scoped to its response sequence. Save it with the operation name and the selected workspace so a later process does not accidentally apply a valid-looking continuation to a different list.

Process the current items before requesting another page. This preserves the evidence trail between each batch of records and the continuation that produced the next batch.

Treat null next_cursor as completion, not an error. The final item page can contain records, so completion means there is no additional page, not that the current page was empty.

Limit controls page size, not the total scope of the operation. Continue only according to the returned cursor and stop condition rather than assuming a selected limit retrieves the complete collection.

Preserve trace ids with pages that need later investigation. They identify the response while item identifiers identify the returned business records or runs.

Dreamstate documentation

Start

Guides

Surfaces

Workspace

Knowledge

Data

Execution

Providers

Plays and templates

Safety and cost

API reference