aws / aws/bedrock-agentcore-sdk-python

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

Aperta
#253 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub
memory
Lingua principale
Python
Stelle
761
Fork
147
Merge medio
1g 23h
PR unite (30g)
7

Descrizione

# 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

```python
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):

```python
[
[{'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):

```python
[
[{'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`:

```python
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:

```python
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:

```python
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:

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

## Related

- PR #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.

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Inizia in client.py, in get_last_k_turns, e riproduci la sequenza di eventi fornita usando list_events o l’esempio fornito di MemorySessionManager. Verifica che i turni restituiti mantengano l’ordine cronologico USER-before-ASSISTANT e che le risposte siano associate ai messaggi utente corretti.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
aws, python
Ambito
api, backend
Tipo di issue
Bug
Difficoltà
2/5
Tempo stimato
1-3 ore
Stato di attività
Ferma
Chiarezza
Specificata chiaramente
Idoneità per principianti
50/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.