Skip to content

fix: prevent consecutive same-role messages in ephemeral injections#10

Open
ramparte wants to merge 1 commit intomicrosoft:mainfrom
ramparte:fix/prevent-consecutive-same-role-messages
Open

fix: prevent consecutive same-role messages in ephemeral injections#10
ramparte wants to merge 1 commit intomicrosoft:mainfrom
ramparte:fix/prevent-consecutive-same-role-messages

Conversation

@ramparte
Copy link

Problem

The orchestrator blindly appends ephemeral injections as new messages with whatever role the hook requests. When a hook uses context_injection_role="user" and the last message is already user role, this creates consecutive user messages that violate role alternation and confuse models about message attribution.

The loop-limit reminder had the same bug - it always appended a hardcoded user role message without checking what the last message was.

Fix

Structural prevention across all injection paths: before appending any ephemeral injection, check if the last message has the same role. If so, merge the content into the existing message with a \n\n separator. This prevents ANY hook from accidentally creating role alternation violations, regardless of its configuration.

Paths fixed:

  1. provider:request default injection path - merge if same role
  2. provider:request append_to_last_tool_result fallback (when last msg isn't tool) - merge if same role
  3. tool:post pending injection default path - merge if same role
  4. tool:post pending injection fallback (when last msg isn't tool) - merge if same role
  5. Loop-limit reminder - merge into last user message instead of always appending new one

Related

Companion PR in amplifier-module-hooks-status-context fixes the hook itself to use append_to_last_tool_result=True.

Testing

  • Existing tests have a pre-existing import error (amplifier_core.llm_errors not yet published) unrelated to this change
  • Both files pass syntax validation
  • Changes are purely defensive guards around existing append logic

🤖 Generated with Amplifier

All injection paths in the orchestrator now check if the last message
has the same role before appending. If so, they merge the content into
the existing message instead of creating a consecutive duplicate.

This is structural prevention - regardless of what role a hook requests,
the orchestrator will never create consecutive messages with the same
role. This fixes model confusion about user vs. system messages.

Affected paths:
- provider:request ephemeral injection (default path)
- provider:request append_to_last_tool_result fallback
- tool:post pending ephemeral injection (both paths)
- orchestrator loop-limit reminder

🤖 Generated with [Amplifier](https://github.com/microsoft/amplifier)

Co-Authored-By: Amplifier <240397093+microsoft-amplifier@users.noreply.github.com>
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