codex - 💡(How to fix) Fix Cap legacy notify input-messages in turn-complete payloads [2 pull requests]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Legacy notify turn-complete payloads can become very large because Codex serializes input-messages into the final argv JSON. In local source inspection, the values appear to be collected from the prompt history used for the sampling request, not just the current user turn.

This makes hook execution fragile for long sessions/prompts:

  • consumers receive a very large argv JSON payload before they can decide whether they need it;
  • on Windows, this can exceed command-line/process invocation limits (related: #18309);
  • on Linux/macOS, consumers that parse the argv JSON can pay avoidable CPU/memory costs.

Root Cause

Legacy notify turn-complete payloads can become very large because Codex serializes input-messages into the final argv JSON. In local source inspection, the values appear to be collected from the prompt history used for the sampling request, not just the current user turn.

Fix Action

Fixed

Code Example

let sampling_request_input: Vec<ResponseItem> = {
    sess.clone_history()
        .await
        .for_prompt(&turn_context.model_info.input_modalities)
};

let sampling_request_input_messages = sampling_request_input
    .iter()
    .filter_map(|item| match parse_turn_item(item) {
        Some(TurnItem::UserMessage(user_message)) => Some(user_message),
        _ => None,
    })
    .map(|user_message| user_message.message())
    .collect::<Vec<String>>();

---

HookEventAfterAgent {
    input_messages: sampling_request_input_messages,
    last_assistant_message: last_agent_message.clone(),
}

---

input_messages: event.input_messages.clone(),
last_assistant_message: event.last_assistant_message.clone(),
RAW_BUFFERClick to expand / collapse

Summary

Legacy notify turn-complete payloads can become very large because Codex serializes input-messages into the final argv JSON. In local source inspection, the values appear to be collected from the prompt history used for the sampling request, not just the current user turn.

This makes hook execution fragile for long sessions/prompts:

  • consumers receive a very large argv JSON payload before they can decide whether they need it;
  • on Windows, this can exceed command-line/process invocation limits (related: #18309);
  • on Linux/macOS, consumers that parse the argv JSON can pay avoidable CPU/memory costs.

Evidence from source inspection

In codex-rs/core/src/session/turn.rs, sampling_request_input_messages is built from sampling_request_input, which comes from prompt history:

let sampling_request_input: Vec<ResponseItem> = {
    sess.clone_history()
        .await
        .for_prompt(&turn_context.model_info.input_modalities)
};

let sampling_request_input_messages = sampling_request_input
    .iter()
    .filter_map(|item| match parse_turn_item(item) {
        Some(TurnItem::UserMessage(user_message)) => Some(user_message),
        _ => None,
    })
    .map(|user_message| user_message.message())
    .collect::<Vec<String>>();

That vector is later passed to the legacy notify payload:

HookEventAfterAgent {
    input_messages: sampling_request_input_messages,
    last_assistant_message: last_agent_message.clone(),
}

codex-rs/hooks/src/legacy_notify.rs then serializes it into argv JSON:

input_messages: event.input_messages.clone(),
last_assistant_message: event.last_assistant_message.clone(),

Expected behavior

Legacy notify should avoid putting unbounded prompt history into argv.

Possible approaches:

  • send only current-turn user input in input-messages;
  • or cap input-messages / last-assistant-message with explicit flags such as:
    • input-messages-truncated: true
    • input-message-count: <n>
    • last-assistant-message-truncated: true
  • or keep full data in transcript and pass transcript_path / metadata in notify payload.

Related downstream impact

The oh-my-codex project hit the same class of problem in long sessions and added defensive bounded intake for hook consumers:

That consumer-side guard is useful, but the producer-side payload should still be compact/capped so notify hooks are reliable across platforms.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

Legacy notify should avoid putting unbounded prompt history into argv.

Possible approaches:

  • send only current-turn user input in input-messages;
  • or cap input-messages / last-assistant-message with explicit flags such as:
    • input-messages-truncated: true
    • input-message-count: <n>
    • last-assistant-message-truncated: true
  • or keep full data in transcript and pass transcript_path / metadata in notify payload.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

codex - 💡(How to fix) Fix Cap legacy notify input-messages in turn-complete payloads [2 pull requests]