Skip to content

fix(acp): deliver final_response after streaming — plugin hooks now visible#29074

Closed
kenyonxu wants to merge 6 commits into
NousResearch:mainfrom
kenyonxu:fix/acp-streamed-final-response
Closed

fix(acp): deliver final_response after streaming — plugin hooks now visible#29074
kenyonxu wants to merge 6 commits into
NousResearch:mainfrom
kenyonxu:fix/acp-streamed-final-response

Conversation

@kenyonxu

Copy link
Copy Markdown
Contributor

Problem

When streaming is active (streamed_message=True), the ACP adapter skips delivering final_response to the client because of the not streamed_message guard:

if final_response and conn and not streamed_message:
    update = acp.update_agent_message_text(final_response)
    await conn.session_update(session_id, update)

This means any plugin registered on the transform_llm_output hook (which fires AFTER streaming completes) has its transformations silently discarded — the modified final_response never reaches the ACP client.

Fix

Remove the not streamed_message guard. The final response (possibly transformed by plugins) should always be delivered:

if final_response and conn:
    update = acp.update_agent_message_text(final_response)
    await conn.session_update(session_id, update)

Test plan

  1. Enable debug mode in a transform_llm_output plugin
  2. Start an ACP streamed conversation
  3. Verify the plugin's appended content appears at the end of the agent response in the client

…ut hook now visible

When streaming is active, streamed_message=True skipped the final_response
update, causing plugin hooks like transform_llm_output to be silently
invisible. Remove the `not streamed_message` guard so the final response
(possibly transformed by plugins) is always delivered to the ACP client.
@alt-glitch alt-glitch added type/bug Something isn't working comp/acp Agent Communication Protocol adapter comp/plugins Plugin system and bundled plugins P2 Medium — degraded but workaround exists labels May 20, 2026
kenyonxu added 5 commits May 20, 2026 12:08
…s streaming suppression

When a transform_llm_output hook modifies final_response after streaming,
the gateway was silently discarding the transformed content because
streamed=True / content_delivered=True triggered the final-send
suppression. Three changes:

1. conversation_loop: set `_response_transformed=True` when a
   transform_llm_output hook returns a non-empty string, and expose it
   as `response_transformed` in the result dict.

2. gateway/run: skip the final-send suppression when
   `response_transformed` is True — the transformed response must
   reach the client even if streaming already sent the original text.

3. acp_adapter/server: remove `not streamed_message` guard so
   final_response is always delivered (ACP path fixed separately).
…turn dict

run_sync() cherry-picks fields from the run_conversation result dict into
a new response dict for the gateway. response_transformed was missing from
the cherry-pick list, so the gateway always saw it as False and suppressed
the final send even though a transform_llm_output hook had modified the content.
… response_transformed

When a transform_llm_output hook appends content after streaming, the previous
fix skipped the final-send suppression which caused the full response to be
sent as a NEW message (duplicate). Instead, edit the existing streamed message
in-place to append the transformed content, then set already_sent=True.

Added stream_consumer.message_id and .accumulated_text public properties.
@kenyonxu

Copy link
Copy Markdown
Contributor Author

Closing in favor of a complete fix that covers all three suppression layers (ACP adapter, gateway suppression check, and run_sync field propagation).

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

Labels

comp/acp Agent Communication Protocol adapter comp/plugins Plugin system and bundled plugins P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants