Skip to content

Commit 0247636

Browse files
author
Jonathan James
committed
feat: override the timestamp serializer of the _data_plane_client to support millisecond granularity
1 parent 7513523 commit 0247636

File tree

2 files changed

+541
-85
lines changed

2 files changed

+541
-85
lines changed

src/bedrock_agentcore/memory/session.py

Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -110,47 +110,98 @@ def __init__(
110110
Raises:
111111
ValueError: If region_name parameter conflicts with boto3_session region.
112112
"""
113+
# Initialize core attributes
114+
self._memory_id = memory_id
115+
116+
# Setup session and validate region consistency
113117
session = boto3_session if boto3_session else boto3.Session()
118+
self.region_name = self._validate_and_resolve_region(region_name, session)
119+
120+
# Configure and create boto3 client
121+
client_config = self._build_client_config(boto_client_config)
122+
self._data_plane_client = session.client(
123+
"bedrock-agentcore", region_name=self.region_name, config=client_config
124+
)
125+
126+
# Configure timestamp serialization for microsecond precision
127+
self._configure_timestamp_serialization()
128+
129+
# Define allowed data plane methods
130+
self._ALLOWED_DATA_PLANE_METHODS = {
131+
"retrieve_memory_records",
132+
"get_memory_record",
133+
"delete_memory_record",
134+
"list_memory_records",
135+
"create_event",
136+
"get_event",
137+
"delete_event",
138+
"list_events",
139+
}
140+
141+
def _validate_and_resolve_region(self, region_name: Optional[str], session: boto3.Session) -> str:
142+
"""Validate region consistency and resolve the final region to use.
143+
144+
Args:
145+
region_name: Explicitly provided region name
146+
session: Boto3 session instance
147+
148+
Returns:
149+
The resolved region name to use
150+
151+
Raises:
152+
ValueError: If region_name conflicts with session region
153+
"""
114154
session_region = session.region_name
115155

116156
# Validate region consistency if both are provided
117-
if region_name and boto3_session and session_region and region_name != session_region:
157+
if region_name and session_region and isinstance(session_region, str) and region_name != session_region:
118158
raise ValueError(
119159
f"Region mismatch: provided region_name '{region_name}' does not match "
120160
f"boto3_session region '{session_region}'. Please ensure both "
121161
f"parameters specify the same region or omit the region_name parameter "
122162
f"to use the session's region."
123163
)
124164

125-
# Configure boto3 client with merged configuration
165+
return region_name or session_region
166+
167+
def _build_client_config(self, boto_client_config: Optional[BotocoreConfig]) -> BotocoreConfig:
168+
"""Build the final boto3 client configuration with SDK user agent.
169+
170+
Args:
171+
boto_client_config: Optional user-provided client configuration
172+
173+
Returns:
174+
Final client configuration with SDK user agent
175+
"""
176+
sdk_user_agent = "bedrock-agentcore-sdk"
177+
126178
if boto_client_config:
127179
existing_user_agent = getattr(boto_client_config, "user_agent_extra", None)
128180
if existing_user_agent:
129-
new_user_agent = f"{existing_user_agent} bedrock-agentcore-sdk"
181+
new_user_agent = f"{existing_user_agent} {sdk_user_agent}"
130182
else:
131-
new_user_agent = "bedrock-agentcore-sdk"
132-
client_config = boto_client_config.merge(BotocoreConfig(user_agent_extra=new_user_agent))
183+
new_user_agent = sdk_user_agent
184+
return boto_client_config.merge(BotocoreConfig(user_agent_extra=new_user_agent))
133185
else:
134-
client_config = BotocoreConfig(user_agent_extra="bedrock-agentcore-sdk")
186+
return BotocoreConfig(user_agent_extra=sdk_user_agent)
135187

136-
# Use provided region_name or fall back to session region
137-
self.region_name = region_name or session_region
138-
self._memory_id = memory_id
139-
self._data_plane_client = session.client(
140-
"bedrock-agentcore", region_name=self.region_name, config=client_config
141-
)
188+
def _configure_timestamp_serialization(self) -> None:
189+
"""Configure the boto3 client to serialize timestamps with microsecond precision.
142190
143-
# AgentCore Memory data plane methods
144-
self._ALLOWED_DATA_PLANE_METHODS = {
145-
"retrieve_memory_records",
146-
"get_memory_record",
147-
"delete_memory_record",
148-
"list_memory_records",
149-
"create_event",
150-
"get_event",
151-
"delete_event",
152-
"list_events",
153-
}
191+
This method overrides the default timestamp serialization to preserve microsecond
192+
precision when sending datetime objects to the AgentCore Memory service.
193+
"""
194+
original_serialize_timestamp = self._data_plane_client._serializer._serializer._serialize_type_timestamp
195+
196+
def serialize_timestamp_with_microseconds(serialized, value, shape, name):
197+
if isinstance(value, datetime):
198+
serialized[name] = value.timestamp() # Float with microseconds
199+
else:
200+
original_serialize_timestamp(serialized, value, shape, name)
201+
202+
self._data_plane_client._serializer._serializer._serialize_type_timestamp = (
203+
serialize_timestamp_with_microseconds
204+
)
154205

155206
def __getattr__(self, name: str):
156207
"""Dynamically forward method calls to the appropriate boto3 client.

0 commit comments

Comments
 (0)