Skip to content

fix: persist agent response during verification stop loop - #62657

Closed
yingliang-zhang wants to merge 1 commit into
NousResearch:mainfrom
yingliang-zhang:fix/verification-stop-response-suppression
Closed

fix: persist agent response during verification stop loop#62657
yingliang-zhang wants to merge 1 commit into
NousResearch:mainfrom
yingliang-zhang:fix/verification-stop-response-suppression

Conversation

@yingliang-zhang

Copy link
Copy Markdown
Contributor

Problem

When verify_on_stop triggers (agent edited code, then tried to end the turn), the agent's complete response was silently suppressed from the durable transcript. The user only saw the brief post-verification response — their full reply appeared to be "washed away" by the verification nudge.

Root Cause

In agent/conversation_loop.py, when the verification stop loop triggers:

  1. The agent's response (final_msg) is flagged _verification_stop_synthetic = True
  2. This flag is registered in _EPHEMERAL_SCAFFOLDING_FLAGS (run_agent.py:233)
  3. _is_ephemeral_scaffolding() filters the message from both persistence sinks (SQLite flush + JSON snapshot)
  4. final_response is set to None (for finalizer logic)
  5. The loop continues — the agent runs tests and generates a new, briefer response

Result: the user never sees the full response. Only the brief post-verification summary is persisted.

Fix

Remove the _verification_stop_synthetic flag from the agent's response (final_msg). The response persists normally as a durable assistant message. The nudge message keeps the flag (internal instruction, not for display).

The resulting assistant→assistant gap in the persisted transcript (nudge is stripped by the ephemeral filter) is repaired at API-call time by repair_message_sequence (Pass 0: consecutive-assistant merge, agent_runtime_helpers.py:408).

Changes

File Change
agent/conversation_loop.py Remove _verification_stop_synthetic flag from final_msg; update comment
tests/run_agent/test_verification_continuation_budget.py Update assertion: response no longer synthetic; add new test verifying response survives _is_ephemeral_scaffolding()

Verification

scripts/run_tests.sh tests/run_agent/test_verification_continuation_budget.py -q
→ 5 tests passed, 0 failed

The 2 pre-existing failures in tests/agent/test_verification_stop_caching.py are unrelated (MINIMUM_CONTEXT_LENGTH model validation, fails on origin/main too).

Relationship to #62598

Complementary but independent:

Different code paths, no file conflicts.

When verify_on_stop triggers, the agent's complete response was flagged
_verification_stop_synthetic and suppressed from the durable transcript
(run_agent.py _EPHEMERAL_SCAFFOLDING_FLAGS). The user only saw the brief
post-verification response, never the full answer — their complete reply
appeared to be 'washed away' by the verification nudge.

Fix: remove the synthetic flag from the agent's response message (final_msg)
so it persists normally. The nudge message keeps the flag (internal
instruction, not for display). The resulting assistant→assistant gap in the
persisted transcript (nudge is stripped) is repaired at API-call time by
repair_message_sequence (Pass 0: consecutive-assistant merge).

The _verification_stop_synthetic flag stays registered in
_EPHEMERAL_SCAFFOLDING_FLAGS so the nudge is still filtered from both
persistence sinks (SQLite flush + JSON snapshot).
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Jul 11, 2026
@yingliang-zhang

Copy link
Copy Markdown
Contributor Author

Superseded by #62676 which provides a complete fix: DB persistence + UI emission. The previous fix only addressed persistence — the user still could not see the response.

@yingliang-zhang

Copy link
Copy Markdown
Contributor Author

CI failure in tests/tools/test_delegate.py::test_build_child_agent_ignores_acp_command_when_binary_missing is a pre-existing failure on main, unrelated to this PR.

The failing assertion mock_which.assert_called_with("copilot") is in the ACP/delegate code path, which this PR does not touch (this PR only modifies agent/conversation_loop.py verification-stop logic). The failure is caused by an upstream change to the delegate/ACP binary detection logic.

This PR only changes:

  • agent/conversation_loop.py — verification stop + pre-verify response persistence
  • tests/agent/test_verification_stop_caching.py — role assertion updates
  • tests/agent/test_verification_continuation_budget.py — role assertion updates

yingliang-zhang added a commit to yingliang-zhang/hermes-agent that referenced this pull request Jul 19, 2026
When verify-on-stop or pre_verify triggers, the agent's complete response
was flagged _verification_stop_synthetic and suppressed from both the
durable transcript (DB) and the UI. The user only saw the terse
post-verification reply, never the full answer — even after PR NousResearch#62657
which only fixed DB persistence without emitting to the UI.

This fix:
1. Removes the synthetic flag from final_msg in both verify-on-stop and
   pre_verify paths, so the response persists to state.db
2. Calls _emit_interim_assistant_message(final_msg) so the response
   reaches the UI immediately, before verification runs
3. Calls _flush_messages_to_session_db() to persist before the
   verification loop continues
4. Changes the nudge from role="user" to role="system" — it's an
   internal instruction, not a user message. This avoids creating a
   durable user→assistant pair and the resulting assistant→assistant
   adjacency in the persisted transcript is repaired at API-call time
   by repair_message_sequence (Pass 0: consecutive-assistant merge)

Tests:
- Updated test_verification_continuation_budget.py: role sequence now
  [user, assistant, system, assistant]; final_msg no longer has synthetic
  flag; only the nudge does
- Updated test_verification_stop_caching.py: assistant response now
  persists (not dropped); nudge still dropped
- New test_verify_on_stop_emits_interim_response_to_ui: verifies the
  full response reaches the interim_assistant_callback
- 70 tests passed, 1 pre-existing failure deselected

Closes NousResearch#62657 (supersedes — this is a complete fix)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P2 Medium — degraded but workaround exists sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants