-
Notifications
You must be signed in to change notification settings - Fork 80
Description
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 newestImpact
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
- PR fix(memory): Improve pagination behavior in get_last_k_turns() and list_messages() #209 improved pagination but did not address the ordering issue
- The docstring says "user message followed by assistant response(s)" but actual behavior is reversed
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.