Skip to content

🤖 fix: skip agent_report reminder when follow-up message is incoming#2200

Open
ethanndickson wants to merge 5 commits intomainfrom
fix/skip-agent-report-reminder-on-followup
Open

🤖 fix: skip agent_report reminder when follow-up message is incoming#2200
ethanndickson wants to merge 5 commits intomainfrom
fix/skip-agent-report-reminder-on-followup

Conversation

@ethanndickson
Copy link
Member

Summary

Skip the "call agent_report" reminder in TaskService.handleStreamEnd() when a follow-up message is about to be sent — either from compaction with a pending follow-up, or from a queued user message.

Background

When a sub-agent task's stream ends without calling agent_report, TaskService sends a reminder forcing the agent to report. However, there are two legitimate cases where the stream ends without agent_report and a follow-up is about to be dispatched automatically:

  1. Compaction with follow-up: The stream was a compaction stream with a pending follow-up. After compaction completes, agentSession.dispatchPendingFollowUp() re-sends the original user message. The reminder interferes with this.
  2. Queued user message: A user message was queued while the sub-agent was streaming. After the stream ends, agentSession.sendQueuedMessages() dispatches it. The reminder races with this.

In both cases, the agent_report reminder is incorrect — the conversation will continue naturally.

Implementation

  • AgentSession.hasQueuedMessages() — new public method exposing whether the message queue is non-empty.
  • WorkspaceService.hasQueuedMessages(workspaceId) — delegates to the session (uses sessions.get() to avoid side effects from getOrCreateSession).
  • TaskService.isCompactionStreamWithFollowUp() — reads history and checks if the last user message is a compaction request with followUpContent (reuses getCompactionFollowUpContent from message.ts, same pattern as CompactionHandler).
  • Guards in handleStreamEnd() — inserted before the reminder logic, returning early if either condition is true.

Note: compactions without follow-ups (e.g. idle compaction) still trigger the reminder as expected.

Risks

Low. The guards add two early-return paths before existing reminder logic. False positives (incorrectly skipping the reminder) would only occur if the queue or compaction state is stale, but both are checked synchronously/within the same event loop tick as the stream-end handler.


Generated with mux • Model: anthropic:claude-opus-4-6 • Thinking: medium • Cost: $11.05

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a3a0ac877a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

AgentSession's stream-end handler drains the queue synchronously
while TaskService's isCompactionStreamWithFollowUp() yields. Capture
hasQueuedMessages() before the await so the guard sees the true state.
@ethanndickson ethanndickson force-pushed the fix/skip-agent-report-reminder-on-followup branch from 6e1bcb8 to 249c499 Compare February 6, 2026 06:56
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6e1bcb8c43

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

After compaction, history is cleared and replaced with a single
assistant summary message. The old code searched for the last user
message (which no longer exists) and called getCompactionFollowUpContent
on it, always returning undefined. Now checks the last message for
compaction-summary + pendingFollowUp, mirroring dispatchPendingFollowUp.
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3e73e0009e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

dispatchPendingFollowUp() may append a follow-up user message before
TaskService reads history, making the summary no longer the last
message. Scan all messages (at most 2 after compaction) instead of
only the last. pendingFollowUp is never cleared from the summary,
so this check is stable regardless of ordering.
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e849bff07e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Addressed P1: isCompactionStreamWithFollowUp() no longer treats historical compaction summaries as active. It now finds the most recent compaction-summary with pendingFollowUp and only suppresses the agent_report reminder until an assistant message after the summary has output parts (i.e. the follow-up response is written to history).

Added regression tests covering:

  • historical summary should NOT suppress reminders
  • pending follow-up (summary + follow-up user + empty assistant placeholder) should suppress

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b3cdaa4056

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// the summary with output parts.
for (let i = summaryIndex + 1; i < historyResult.data.length; i++) {
const msg = historyResult.data[i];
if (msg.role === "assistant" && msg.parts.length > 0) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Treat empty follow-up completion as no longer pending

The compaction guard only stops suppressing reminders once it finds an assistant message after the summary with parts.length > 0, but a follow-up stream can legitimately end with zero parts; in that case StreamManager does not rewrite the placeholder in history, so this check keeps returning true and handleStreamEnd() keeps exiting early. When that happens, the task never reaches the agent_report reminder/fallback path and can remain stuck in a non-reported state, which can block parent waits for that subtask.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant