Codex Desktop list_threads needs project-scoped cursor pagination for safe automations

Open 💬 0 comments Opened Aug 21, 2026 by TharpTravis

Environment

  • ChatGPT/Codex Desktop: 26.818.21641 (build 6849)
  • macOS 26.6.2 (build 25G83)
  • Process architecture: x86_64
  • Naturally scheduled local automation
  • Observed: 2026-08-20

Private project IDs, conversation IDs, account details, and local paths are intentionally omitted.

Summary

The app-facing list_threads tool cannot support correctness-sensitive project reconciliation because its surfaced schema exposes only a fixed result limit:

declare const tools: {
  codex_app__list_threads(args: {
    limit?: number;
  }): Promise<unknown>;
};

It has no exact-project filter, page cursor, terminal completeness signal, or durable incremental checkpoint.

This is independently blocked by the scheduled-run hang in #35030, but even after that hang is fixed, a successful fixed-limit response cannot establish that all conversations in one ChatGPT Project were enumerated.

Reproduction

  1. Create a naturally scheduled automation that needs to inspect conversations belonging to one ChatGPT Project.
  2. Inspect the exposed list_threads schema. Only limit is available.
  3. Attempt a bounded call. In the latest run, list_threads({limit: 50}) remained pending through four bounded waits and had to be terminated.
  4. Reduce the limit or run interactively. A returned recent-task window still cannot be paged, filtered server-side to the exact project, or proven complete.
  5. Try to resume later from a durable cursor. No cursor or changed-since checkpoint is exposed.

Expected behavior

Provide a bounded, project-scoped enumeration contract suitable for scheduled automation. One possible shape is:

list_threads({
  projectId?: string,
  limit?: number,
  cursor?: string,
  changedSinceCursor?: string
}) => {
  threads: ThreadSummary[],
  nextCursor?: string,
  complete: boolean,
  checkpointCursor?: string
}

Required semantics:

  • Prefer server-side filtering by exact ChatGPT Project ID.
  • Support small bounded pages with an opaque continuation cursor.
  • Return an explicit terminal/completeness indicator.
  • Preserve stable conversation IDs, exact project ID, kind, and update timestamp.
  • After a complete bootstrap, expose a durable cursor/checkpoint that returns only new or changed conversations.
  • On timeout or partial failure, return a structured error without implying an empty or complete result.

Names are illustrative; equivalent semantics would solve the problem.

Actual behavior

  • The tool schema exposes only limit.
  • Results are a recency-bounded mixed inventory rather than a provably complete project inventory.
  • There is no cursor for older pages.
  • There is no durable incremental cursor.
  • In natural scheduled runs, the call can also remain pending, as tracked in #35030.

Impact

A safety-conscious automation must fail closed:

  • It cannot infer “no new conversations” from a timeout or partial recent window.
  • It cannot advance a source checkpoint.
  • It cannot claim source parity or completeness.
  • It must remain paused even when repository identity and read/write capability are independently verified.

This blocks reliable, low-noise scheduled reconciliation of ChatGPT Project conversations without resorting to unsupported local database access or UI scraping.

Related issues

  • #35030 — scheduled list_threads calls hang while interactive calls succeed.
  • #35377 — surfaced query support can disagree with the runtime validator.
  • #25500 — project views can incorrectly imply no chats when older conversations fall outside the recent set.

View original on GitHub ↗