Skip to content

Bug Report: get_last_k_turns() returns messages in reversed order within each turn #253

@ecoonomykim

Description

@ecoonomykim

Bug Report: get_last_k_turns() returns messages in reversed order within each turn

Reporter: Amazon Employee (not a team member of AgentCore SDK, reporting issue only)

Description

get_last_k_turns() returns turns with messages in reversed order (ASSISTANT before USER) instead of chronological order (USER before ASSISTANT). This contradicts the docstring which states "A turn typically consists of a user message followed by assistant response(s)."

Environment

  • OS: macOS
  • Python version: 3.12
  • SDK version: 1.2.0, 1.2.1 (tested both - bug persists)
  • AWS Region: ap-northeast-2

Steps to Reproduce

from bedrock_agentcore.memory import MemoryClient, MemorySessionManager

memory_client = MemoryClient(region_name="ap-northeast-2")
session_manager = MemorySessionManager(
    memory_id="mem-xxxxxxxx",
    region_name="ap-northeast-2",
)

# Create events in chronological order
# Event 1: USER "Hello"
# Event 2: ASSISTANT "Hi there!"
# Event 3: USER "What's the weather?"
# Event 4: ASSISTANT [toolUse: get_weather]
# Event 5: USER [toolResult: sunny]
# Event 6: ASSISTANT "It's sunny today"

# Get last k turns
turns = session_manager.get_last_k_turns(
    actor_id="user_001",
    session_id="session_001",
    k=10
)

print(turns)

Expected Behavior

Each turn should have messages in chronological order (USER first, then ASSISTANT):

[
    [{'role': 'USER', 'content': ...}, {'role': 'ASSISTANT', 'content': ...}],
    [{'role': 'USER', 'content': ...}, {'role': 'ASSISTANT', 'content': ...}],
    ...
]

Actual Behavior

Each turn has messages in reversed order (ASSISTANT first, then USER):

[
    [{'role': 'ASSISTANT', 'content': "서울역[1호선]으로 안내를..."}],  # Turn with only ASSISTANT
    [{'role': 'USER', 'content': ...toolResult...}, {'role': 'ASSISTANT', 'content': ...toolUse...}],  # Reversed!
    [{'role': 'USER', 'content': "2번"}, {'role': 'ASSISTANT', 'content': "서울역 5곳이에요..."}],  # Looks correct but paired with PREVIOUS assistant response
    ...
]

Root Cause Analysis

Looking at the SDK source code in client.py:

def get_last_k_turns(self, ...):
    # ...
    response = self.gmdp_client.list_events(**params)  # Returns events in reverse chronological order (newest first)
    events = response.get("events", [])
    
    for event in events:  # Iterates in reverse order without sorting
        # ...
        if role == Role.USER.value and current_turn:
            turns.append(current_turn)
            current_turn = []
        current_turn.append(payload_item["conversational"])

The issue is that list_events API returns events in reverse chronological order (newest first), but the SDK processes them without sorting to chronological order first.

Suggested Fix

Sort events by eventTimestamp before processing:

def get_last_k_turns(self, ...):
    # ... fetch events ...
    
    # Sort events chronologically before processing
    all_events = sorted(all_events, key=lambda e: e.get('eventTimestamp', ''))
    
    # Then process turns...

Or reverse the events list before iteration:

for event in reversed(events):  # Process oldest to newest

Impact

This bug affects any application that relies on get_last_k_turns() to retrieve conversation history for:

  • Passing to LLM as context (messages appear in wrong order)
  • Displaying conversation history to users
  • Analyzing conversation flow

Workaround

Currently using list_events() and manually sorting/grouping:

events = session_manager.list_events(actor_id, session_id)
events_sorted = sorted(events, key=lambda e: e['eventTimestamp'])
# Manual turn grouping...

Related

Update Log

2026-02-05: Tested with SDK 1.2.1

Bug still persists in version 1.2.1. Test results:

SDK Version: 1.2.1

============================================================
각 턴의 메시지 순서 확인:
============================================================
Turn 1: ['ASSISTANT']           # ← Only ASSISTANT, no USER
Turn 2: ['USER', 'ASSISTANT']   # ← Looks correct but actually misaligned
Turn 3: ['USER', 'ASSISTANT']
Turn 4: ['USER', 'ASSISTANT']
Turn 5: ['USER', 'ASSISTANT']

The issue is that Turn 1 contains only ASSISTANT (orphaned from its USER), and subsequent turns pair the PREVIOUS assistant response with the CURRENT user message - the entire conversation is shifted by one position.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions