Skip to content

Commit 0206ae4

Browse files
abhu85claude
andauthored
fix(memory): handle SELF_MANAGED override type in _wrap_configuration (aws#290)
Bug #1 from issue aws#212: The _wrap_configuration method was crashing with ValueError when trying to modify CUSTOM strategies with SELF_MANAGED configuration type. Root cause: The code attempted to convert override_type string to OverrideType enum without handling the case where override_type is not a valid enum value (e.g., 'SELF_MANAGED' which is a valid configuration type but not in the OverrideType enum). Fix: Add _try_get_override_type() helper method that safely converts override_type to OverrideType enum, returning None for invalid values. Update _wrap_configuration to use this helper and fall through to pass-through behavior when override_enum is None or not in the wrapper key dictionaries. This allows CUSTOM strategies with SELF_MANAGED configuration to be modified without crashing, with their configuration passed through as-is (no special wrapping). Fixes aws#212 (Bug #1) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent eab90e9 commit 0206ae4

2 files changed

Lines changed: 94 additions & 6 deletions

File tree

src/bedrock_agentcore/memory/client.py

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,6 +1929,20 @@ def _validate_strategy_config(self, strategy: Dict[str, Any], strategy_type: str
19291929
for namespace in namespaces:
19301930
self._validate_namespace(namespace)
19311931

1932+
def _try_get_override_type(self, override_type: Optional[str]) -> Optional[OverrideType]:
1933+
"""Safely convert override_type string to OverrideType enum.
1934+
1935+
Returns None if override_type is None or not a valid OverrideType value
1936+
(e.g., 'SELF_MANAGED' which is a valid configuration type but not in the enum).
1937+
"""
1938+
if override_type is None:
1939+
return None
1940+
try:
1941+
return OverrideType(override_type)
1942+
except ValueError:
1943+
# Unknown override type (e.g., SELF_MANAGED), return None
1944+
return None
1945+
19321946
def _wrap_configuration(
19331947
self, config: Dict[str, Any], strategy_type: str, override_type: Optional[str] = None
19341948
) -> Dict[str, Any]:
@@ -1941,8 +1955,8 @@ def _wrap_configuration(
19411955
builtin_config_keys = ["triggerEveryNMessages", "historicalContextWindowSize"]
19421956

19431957
if strategy_type == "CUSTOM" and override_type:
1944-
override_enum = OverrideType(override_type)
1945-
if override_enum in CUSTOM_EXTRACTION_WRAPPER_KEYS:
1958+
override_enum = self._try_get_override_type(override_type)
1959+
if override_enum and override_enum in CUSTOM_EXTRACTION_WRAPPER_KEYS:
19461960
wrapped_config["extraction"] = {
19471961
"customExtractionConfiguration": {CUSTOM_EXTRACTION_WRAPPER_KEYS[override_enum]: extraction}
19481962
}
@@ -1970,25 +1984,31 @@ def _wrap_configuration(
19701984
}
19711985
}
19721986
elif strategy_type == "CUSTOM" and override_type:
1973-
override_enum = OverrideType(override_type)
1974-
if override_enum in CUSTOM_CONSOLIDATION_WRAPPER_KEYS:
1987+
override_enum = self._try_get_override_type(override_type)
1988+
if override_enum and override_enum in CUSTOM_CONSOLIDATION_WRAPPER_KEYS:
19751989
wrapped_config["consolidation"] = {
19761990
"customConsolidationConfiguration": {
19771991
CUSTOM_CONSOLIDATION_WRAPPER_KEYS[override_enum]: consolidation
19781992
}
19791993
}
1994+
else:
1995+
# Unknown override type (e.g., SELF_MANAGED), pass through as-is
1996+
wrapped_config["consolidation"] = consolidation
19801997
else:
19811998
wrapped_config["consolidation"] = consolidation
19821999

19832000
if "reflection" in config:
19842001
reflection = config["reflection"]
19852002

19862003
if strategy_type == "CUSTOM" and override_type:
1987-
override_enum = OverrideType(override_type)
1988-
if override_enum in CUSTOM_REFLECTION_WRAPPER_KEYS:
2004+
override_enum = self._try_get_override_type(override_type)
2005+
if override_enum and override_enum in CUSTOM_REFLECTION_WRAPPER_KEYS:
19892006
wrapped_config["reflection"] = {
19902007
"customReflectionConfiguration": {CUSTOM_REFLECTION_WRAPPER_KEYS[override_enum]: reflection}
19912008
}
2009+
else:
2010+
# Unknown override type (e.g., SELF_MANAGED), pass through as-is
2011+
wrapped_config["reflection"] = reflection
19922012
else:
19932013
wrapped_config["reflection"] = reflection
19942014

tests/bedrock_agentcore/memory/test_client.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3283,6 +3283,74 @@ def test_wrap_configuration_custom_episodic_override():
32833283
)
32843284

32853285

3286+
def test_wrap_configuration_custom_self_managed():
3287+
"""Test _wrap_configuration with CUSTOM strategy and SELF_MANAGED type.
3288+
3289+
SELF_MANAGED is a valid configuration type but not in the OverrideType enum.
3290+
The method should handle this gracefully by passing configuration through as-is.
3291+
See: https://github.com/aws/bedrock-agentcore-sdk-python/issues/212
3292+
"""
3293+
with patch("boto3.client"):
3294+
client = MemoryClient()
3295+
3296+
config = {
3297+
"extraction": {
3298+
"historicalContextWindowSize": 10,
3299+
"triggerEveryNMessages": 5,
3300+
},
3301+
"consolidation": {
3302+
"appendToPrompt": "Consolidate data",
3303+
"modelId": "consolidation-model",
3304+
},
3305+
"reflection": {
3306+
"appendToPrompt": "Reflect on data",
3307+
"modelId": "reflection-model",
3308+
},
3309+
}
3310+
3311+
# Should NOT raise ValueError for SELF_MANAGED
3312+
wrapped = client._wrap_configuration(config, "CUSTOM", "SELF_MANAGED")
3313+
3314+
# Configuration should be passed through as-is (no special wrapping)
3315+
assert "extraction" in wrapped
3316+
assert wrapped["extraction"]["historicalContextWindowSize"] == 10
3317+
assert wrapped["extraction"]["triggerEveryNMessages"] == 5
3318+
3319+
# Consolidation should also be passed through (no wrapping for unknown override types)
3320+
assert "consolidation" in wrapped
3321+
assert wrapped["consolidation"]["appendToPrompt"] == "Consolidate data"
3322+
assert wrapped["consolidation"]["modelId"] == "consolidation-model"
3323+
3324+
# Reflection should also be passed through
3325+
assert "reflection" in wrapped
3326+
assert wrapped["reflection"]["appendToPrompt"] == "Reflect on data"
3327+
assert wrapped["reflection"]["modelId"] == "reflection-model"
3328+
3329+
3330+
def test_try_get_override_type_valid():
3331+
"""Test _try_get_override_type returns enum for valid override types."""
3332+
with patch("boto3.client"):
3333+
from bedrock_agentcore.memory.constants import OverrideType
3334+
3335+
client = MemoryClient()
3336+
3337+
assert client._try_get_override_type("SEMANTIC_OVERRIDE") == OverrideType.SEMANTIC_OVERRIDE
3338+
assert client._try_get_override_type("EPISODIC_OVERRIDE") == OverrideType.EPISODIC_OVERRIDE
3339+
assert client._try_get_override_type("SUMMARY_OVERRIDE") == OverrideType.SUMMARY_OVERRIDE
3340+
assert client._try_get_override_type("USER_PREFERENCE_OVERRIDE") == OverrideType.USER_PREFERENCE_OVERRIDE
3341+
3342+
3343+
def test_try_get_override_type_invalid():
3344+
"""Test _try_get_override_type returns None for invalid override types."""
3345+
with patch("boto3.client"):
3346+
client = MemoryClient()
3347+
3348+
assert client._try_get_override_type(None) is None
3349+
assert client._try_get_override_type("SELF_MANAGED") is None
3350+
assert client._try_get_override_type("UNKNOWN_TYPE") is None
3351+
assert client._try_get_override_type("") is None
3352+
3353+
32863354
def test_get_last_k_turns_auto_pagination():
32873355
"""Test get_last_k_turns automatically paginates until k turns are found."""
32883356
with patch("boto3.client"):

0 commit comments

Comments
 (0)