[desktop] Tool-call provenance arrives after startup evidence expires
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
What version of the Codex App are you using (From “About Codex” dialog)?
Not available to this automated local task. Observed 2026-09-15 on Windows Codex Desktop.
What platform is your computer?
Windows 11, local Codex Desktop task.
What issue are you seeing?
A Codex app tool and a remote MCP read-only tool complete successfully, but the model-visible CallToolResult for each contains only content (the app tool also contains isError). Neither result exposes the executor-native tool-call ID or an equivalent per-call provenance receipt. codex_app.read_thread(includeOutputs=true) initially reports items=[] for the completed turn, even when the desktop task has reported completion.
For one affected turn, the same read later exposed real native exec-... tool-call IDs, proving those IDs existed. That recovery took longer than a local 15-minute startup evidence window. For a fresh short turn, repeated reads still returned items=[] after the window expired. The observable failure is that the supported retrieval path does not consistently provide call provenance while the successful read-only results are still fresh.
A local fail-closed workflow binding a fresh authenticated MCP status response and a saved-project list to their actual tool calls therefore returns CALL_ID_REQUIRED / CAPTURE_NOT_VERIFIED, despite successful read-only calls and healthy device authentication. Local labels or invented IDs would create a false pass.
The public Codex core handles a call_id in handle_mcp_tool_call and uses it as the McpToolCallItem.id in lifecycle events (codex-rs/core/src/mcp_tool_call.rs). This matches the later historical readback but does not establish why newer turns are delayed. The model-visible tool result still lacks a way to bind its content to that item ID when the cross-task projection is empty.
What steps can reproduce the bug?
- In one local Desktop turn, call the Codex app
list_projectstool and one configured remote MCP read-only tool. - Inspect the successful model-visible result objects. Neither provides a real per-call ID associated with its returned result.
- After the turn completes, use
codex_app.read_threadwith outputs for the exact task/turn. In the affected fresh turns, it returnsitems=[]for more than 15 minutes. - In a separate historical affected turn, retry later and observe native tool-call items eventually appear. Their late appearance cannot restore freshness to the original status result.
- A consumer requiring actual same-turn call provenance cannot construct a verified capture before its startup evidence expires.
What is the expected behavior?
Expose the executor-native per-call ID with the provider/tool, request, completion status, and matching result for both app tools and remote MCP tools, either directly in the model-visible result metadata or through a supported full turn-item read available promptly after completion. If a native ID is unavailable, report that explicitly. The full read should return actual tool-call items for a completed turn rather than silently returning an empty item list while those calls ran.
Additional information
The empty read_thread projection overlaps #43468; this report adds delayed historical recovery and the separate result-provenance/freshness impact. The underlying cause remains unconfirmed.
No private task IDs, saved-project IDs, local paths, credentials, OAuth URLs, device keys, short sessions, cookies, or raw transcripts are included here. Exact affected identifiers can be supplied privately through Codex feedback if maintainers need them.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with codex-rs/core/src/mcp_tool_call.rs and handle_mcp_tool_call, then trace the codex_app.read_thread(includeOutputs=true) path for completed turns. Reproduce the empty items=[] response and compare it with the later native exec-... tool-call items. Done means prompt, consistent provenance or explicit unavailability, and timely full-turn items for completed calls.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- api, desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100