Skip to content

Gateway transcript loses 1 message per turn due to session_meta offset mismatch #394

@PercyDikec

Description

@PercyDikec

GatewayRunner._handle_message() loses messages from the transcript on every conversation turn after the first.

Root cause

The raw transcript history includes session_meta entries (tool definitions, model info, etc.) that are written on the first turn. When _run_agent builds agent_history, it filters these out (lines 1978-1981) before passing the conversation to the agent. The agent returns messages built from this filtered list plus new messages from the current turn.

The bug is on line 949-950:

history_len = len(history)  # includes session_meta
new_messages = agent_messages[history_len:] if len(agent_messages) > history_len else agent_messages

len(history) counts session_meta entries, but agent_messages was built from agent_history which has no session_meta. So the slice offset is too high by the number of session_meta entries, and the extraction skips that many valid new messages.

Example

Turn 2 of a conversation:

  • history = [session_meta, user_msg1, assistant_msg1] - length 3
  • agent_history = [user_msg1, assistant_msg1] - length 2 (session_meta filtered)
  • Agent returns [user_msg1, assistant_msg1, user_msg2, assistant_msg2] - length 4
  • agent_messages[3:] = [assistant_msg2] - user_msg2 is lost
  • agent_messages[2:] = [user_msg2, assistant_msg2] - correct

Second bug (else branch)

The else branch else agent_messages treats ALL messages as new when the count comparison fails. With multiple session_meta entries, len(history) can equal len(agent_messages), causing the entire conversation to be duplicated into the transcript. The else branch should return [] to fall through to the simple user/assistant fallback.

Impact

From turn 2 onwards, every turn loses 1 message from the persistent transcript. Over a long conversation this accumulates - the transcript becomes increasingly incomplete, missing user messages and tool interactions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions