aws / aws/bedrock-agentcore-sdk-python
AgentCoreMemorySessionManager: retrieval_config context accumulates O(turns × records) across multi-turn conversations
まだ誰も着手していません。
- 主要言語
- Python
- スター
- 764
- フォーク
- 148
- 平均マージ
- 1日 23時間
- マージ済み PR(30日)
- 7
説明
Summary
When using AgentCoreMemorySessionManager with retrieval_config, the <user_context> XML injected by retrieve_customer_context() persists in agent.messages and repeats on every turn, growing O(turns × records).
Observed with 5 turns and 3 preferences: 3,655 chars of repeated context (83% of total message content).
Turn 1: [user+XML, assistant]
Turn 2: [user+XML, assistant, user+XML, assistant] ← XML appears twice
Turn 3: [user+XML, assistant, user+XML, assistant, user+XML, assistant] ← 3×
Strands Integration Affected
from bedrock_agentcore.memory.integrations.strands.config import AgentCoreMemoryConfig
from bedrock_agentcore.memory.integrations.strands.session_manager import AgentCoreMemorySessionManager
Root Cause
In session_manager.py, retrieve_customer_context() (lines 754–829) is registered as a MessageAddedEvent callback (line 840). On each turn it unconditionally inserts XML context at event.agent.messages[-1]["content"][0] (line 823):
event.agent.messages[-1]["content"].insert(
0, {"text": f"<{self.config.context_tag}>{context_text}</{self.config.context_tag}>"}
)
Three missing controls cause the accumulation:
- No deduplication check —
retrieve_customer_context()does not check if context is already present before injecting. - No filtering on message restore —
list_messages()(lines 688–707) reloads messages with previously-injected context intact. The existing_filter_restored_tool_context()(lines 709–734) stripstoolUse/toolResultblocks but has no equivalent for<user_context>tags. - Mutable in-place modification — The injected context is saved as part of the message content, so it reappears when the message history is reloaded on the next turn.
Impact
- Token waste: Grows linearly per turn. 10 turns × 5 records × 500 chars/record = ~25KB of duplicate context.
- Context window pressure: In long-running sessions this can consume a significant portion of the model's context window.
- Cost: Unnecessary input token charges scale with conversation length.
Reproduction
from bedrock_agentcore.memory.integrations.strands.config import AgentCoreMemoryConfig, RetrievalConfig
from bedrock_agentcore.memory.integrations.strands.session_manager import AgentCoreMemorySessionManager
from strands import Agent
config = AgentCoreMemoryConfig(
memory_id=MEMORY_ID,
session_id=session_id,
actor_id=actor_id,
retrieval_config=RetrievalConfig(
memory_id=MEMORY_ID,
namespace="preferences",
),
)
with AgentCoreMemorySessionManager(config, region_name=REGION) as sm:
agent = Agent(model=model, session_manager=sm)
# After 3+ turns, inspect agent.messages — <user_context> XML appears N times
# where N = number of completed turns
Suggested Fix Directions
Option A (Deduplication before injection):
Before line 823, check if the last message already contains the context tag and skip injection if present.
Option B (Filter on restore — analogous to existing tool context filtering):
Add a _filter_restored_user_context() method that strips previously-injected <user_context> tags from restored messages, similar to how _filter_restored_tool_context() already handles toolUse/toolResult.
Option C (Both):
Strip on restore (Option B) for correctness + deduplicate on inject (Option A) as a safety net.
Current Workaround
Skip retrieval_config and use the memory tool directly for LTM access:
config = AgentCoreMemoryConfig(
memory_id=MEMORY_ID, session_id=sid, actor_id=aid,
# no retrieval_config → no auto-injection
)
memory_tool = AgentCoreMemoryToolProvider(
memory_id=MEMORY_ID, actor_id=aid, session_id=sid, namespace=ns, region=REGION,
)
with AgentCoreMemorySessionManager(config, region_name=REGION) as sm:
agent = Agent(model=model, session_manager=sm, tools=memory_tool.tools)
Test Gap
The existing integration test test_session_manager_with_retrieval_config_adds_context (line ~140) only verifies context exists after 2 turns but does not assert that context does not accumulate across turns.
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
session_manager.py の list_messages()、_filter_restored_tool_context()、retrieve_customer_context()、および MessageAddedEvent の登録から始めます。統合テスト test_session_manager_with_retrieval_config_adds_context を読み、複数ターンにわたってカバレッジを拡張し、retrieval context が蓄積して agent.messages に入るのではなく、1 回だけ現れることを検証します。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- aws, python
- 領域
- ai, backend
- issue の種類
- バグ
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 活発さ
- 静か
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 68/100