# Next user prompt suggestions

A next user prompt suggestion is a proposed message the user might send after an agent finishes. After “The parser fix passes its tests,” the interface might offer “Explain why the old parser failed.” The user can accept, edit, or ignore it. Generating that text is a separate inference task from answering the original request.

The interesting engineering problem is ownership: the model may predict an instruction, but only the user can adopt it. A suggestion must not silently enter the conversation as something the user said.

## Separate prediction from nearby features

| Feature | Example | What the harness does |
| --- | --- | --- |
| Next user prompt prediction | “Add a regression test for empty input.” | Generates a candidate user message from conversation context. |
| Command or path autocomplete | Completing `/skill:review` or `src/parser.ts` | Matches known entries against text being typed. |
| Assistant follow-up question | “Which input format should I support?” | Emits an assistant message asking the user for information. |
| Queued follow-up or automatic continuation | Processing an instruction already queued by the user | Schedules another agent turn. |

These features can share an editor or event system, but their contracts differ. See [steering and cancellation](steering.md) for input that has already been submitted.

## What the pinned sources establish

| Harness | Evidence in this snapshot | Scope of the conclusion |
| --- | --- | --- |
| Codex | Prediction request/result types and an experimental prediction fork exist. The dedicated prediction request handler returns “not implemented yet.” | Infrastructure is visible; an end-to-end next-prompt generator is not established by this code. |
| pi | Interactive autocomplete combines commands, prompt templates, extensions, and skills. An example adds GitHub issue completion. | Extensible input assistance is implemented; model-generated next-message prediction was not found in the inspected surfaces. |
| Goose | Desktop autocomplete maps available commands and agent mentions into selectable entries. | Command and mention completion is implemented; model-generated next-message prediction was not found in the inspected surfaces. |

Codex's request carries `thread_id` and `source_turn_id`. Its notification repeats those identifiers and distinguishes `Completed { text: Option<String> }` from `Failed`. That contract can represent both a successful prediction and a successful decision to suggest nothing. The handler's explicit rejection prevents treating the types alone as a working feature. [Prediction types][c-types], [request handler][c-handler].

Codex also supports `experimentalPredictionMode` on thread forks. It requires an ephemeral fork of a loaded parent, inherits parent state, disables automatic compaction, and enables reasoning-effort override. The protocol comment identifies prompt-cache reuse as the purpose of inheriting configuration, tools, environments, and history. This is useful supporting infrastructure, but it does not establish the prediction prompt, trigger, filtering rules, or acceptance UI. [Fork contract][c-fork-contract], [fork implementation][c-fork].

pi's built-in completion catalog and optional GitHub issue example have concrete data sources; the latter fetches open issues and filters them locally. Goose's desktop adapter obtains commands and mentions through its ACP client. These are useful extension points, not evidence that either harness predicts a new user message. [Pi catalog][p-catalog], [issue example][p-issues], [Goose adapter][g-autocomplete].

**Search boundary:** this review checked Codex core, app-server, protocol, and TUI sources; pi agent, coding-agent, TUI, web-UI sources and extension examples; and Goose agent/server and desktop sources. Searches covered prompt suggestions, predictions, autocomplete, and follow-up paths at the registered commits. Codex rendering fixtures contain references to `next_prompt_suggestion.rs`; those fixture strings do not establish an implementation. The conclusions concern these source snapshots, not every client, external extension, or subsequent release.

## A design for an optional suggestion worker

The following is a proposed design, not a claim that the compared harnesses implement it.

1. **Wait for the run to settle.** Start after the final response and after queued work is exhausted. A low-level completion event may be too early: pi's notification example uses `agent_settled` because `agent_end` can precede retry, compaction, or queued follow-up work. [Pi settled event example][p-settled].
2. **Capture a bounded context snapshot.** Include recent user intent, the final answer, and relevant outcomes. Attach the session, completed-turn identifier, and composer revision. Exclude pending tool calls and unrelated private material.
3. **Request text or abstention.** Use a separate instruction such as “Suggest one concise message this user is likely to send next; return no suggestion when uncertain.” Require a small validated output, with no tool execution. Keep this synthetic instruction outside normal conversation history.
4. **Reject stale results.** Give inference a short time budget. Cancel when typing, a new turn, a branch switch, or a session change invalidates the snapshot. Recheck identifiers when the result arrives: cancellation alone may lose a race.
5. **Present an editable draft.** Acceptance can fill the composer; submission follows the ordinary user-message path. A displayed or accepted draft grants no permission to execute its contents.

For example, turn 12 ends and prediction starts. The user immediately types “Actually, revert that fix.” A late prediction saying “Commit the fix” belongs to turn 12's old composer state and must be discarded. It must never overwrite the user's correction or queue a commit.

pi's autocomplete editor demonstrates a reusable part of this design: it passes an abort signal, snapshots text and cursor position, and checks request identity plus the unchanged editor state before applying a result. This is evidence for handling asynchronous editor results, not a prediction-model implementation. [Editor freshness checks][p-freshness].

## Cost, privacy, and evaluation

**Design implications:** prediction adds model calls even when nobody accepts the result. Budget tokens and latency separately from the main agent, permit abstention, and avoid delaying the final response. Reusing full conversation context can improve relevance while exposing more data to the selected provider; use deliberate context selection and make any provider change explicit.

Evaluate acceptance together with edits, dismissals, stale-result rejection, and whether suggestions remain within the user's intent. Acceptance alone can reward intrusive suggestions. Include cases with a completed task, unanswered clarification, sensitive tool output, a newly typed correction, and multiple clients. The essential invariant is that prediction produces optional text; execution still requires a submitted user instruction and the harness's normal policy checks.

## Sidekick: clarification is not prediction

No dedicated next-user-message prediction path was located in the inspected backend, frontend conversation state, or chat composer. The native `AskUserQuestion` tool asks clarifying questions and suspends execution until answers resume it. That is an assistant requesting missing input, not a model proposing the user’s next message. This is a bounded finding about the reviewed sources, not a claim that an external client or wrapped agent cannot provide suggestions. [Question contract][s-question] (private source).

[c-types]: https://github.com/openai/codex/blob/8c076942cb70fba8e5c4732c23f1faabc4aed484/codex-rs/app-server-protocol/src/protocol/v2/thread_prediction.rs#L8-L35
[c-handler]: https://github.com/openai/codex/blob/8c076942cb70fba8e5c4732c23f1faabc4aed484/codex-rs/app-server/src/message_processor.rs#L1460-L1462
[c-fork-contract]: https://github.com/openai/codex/blob/8c076942cb70fba8e5c4732c23f1faabc4aed484/codex-rs/app-server-protocol/src/protocol/v2/thread.rs#L544-L554
[c-fork]: https://github.com/openai/codex/blob/8c076942cb70fba8e5c4732c23f1faabc4aed484/codex-rs/app-server/src/request_processors/thread_processor.rs#L5109-L5186
[p-catalog]: https://github.com/earendil-works/pi/blob/482c1381a00d8d00bc81697e4a980c593db6803e/packages/coding-agent/src/modes/interactive/interactive-mode.ts#L786-L822
[p-issues]: https://github.com/earendil-works/pi/blob/482c1381a00d8d00bc81697e4a980c593db6803e/packages/coding-agent/examples/extensions/github-issue-autocomplete.ts#L71-L184
[p-settled]: https://github.com/earendil-works/pi/blob/482c1381a00d8d00bc81697e4a980c593db6803e/packages/coding-agent/examples/extensions/notify.ts#L51-L57
[p-freshness]: https://github.com/earendil-works/pi/blob/482c1381a00d8d00bc81697e4a980c593db6803e/packages/tui/src/components/editor.ts#L2318-L2429
[g-autocomplete]: https://github.com/aaif-goose/goose/blob/34a222e3f2b95d8b4a43482b53c2cc957ecce26d/ui/desktop/src/acp/autocomplete.ts#L27-L76

[s-question]: https://github.com/datex/sidekick/blob/463d653124e1c2cda46a3f14f01f3d6f384326b1/backend/src/sidekick_worker/tools/ask_user_question_tools.py#L1-L27
