Skip to content

Commit 7b356dd

Browse files
GWealecopybara-github
authored andcommitted
feat: Add add_session_to_memory to CallbackContext and ToolContext
This change introduces an add_session_to_memory method to both CallbackContext and ToolContext, allowing agents and tools to explicitly trigger the saving of the current session to the memory service. This enables more fine-grained control over when session data is persisted for memory generation. A ValueError is raised if the memory service is not configured. Co-authored-by: George Weale <gweale@google.com> PiperOrigin-RevId: 843021899
1 parent 4111f85 commit 7b356dd

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

src/google/adk/agents/callback_context.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,27 @@ async def load_credential(
176176
return await self._invocation_context.credential_service.load_credential(
177177
auth_config, self
178178
)
179+
180+
async def add_session_to_memory(self) -> None:
181+
"""Triggers memory generation for the current session.
182+
183+
This method saves the current session's events to the memory service,
184+
enabling the agent to recall information from past interactions.
185+
186+
Raises:
187+
ValueError: If memory service is not available.
188+
189+
Example:
190+
```python
191+
async def my_after_agent_callback(callback_context: CallbackContext):
192+
# Save conversation to memory at the end of each interaction
193+
await callback_context.add_session_to_memory()
194+
```
195+
"""
196+
if self._invocation_context.memory_service is None:
197+
raise ValueError(
198+
"Cannot add session to memory: memory service is not available."
199+
)
200+
await self._invocation_context.memory_service.add_session_to_memory(
201+
self._invocation_context.session
202+
)

tests/unittests/agents/test_callback_context.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,87 @@ async def test_load_artifact_integration(self, mock_invocation_context):
321321
version=None,
322322
)
323323
assert result == test_artifact
324+
325+
326+
class TestCallbackContextAddSessionToMemory:
327+
"""Test the add_session_to_memory method in CallbackContext."""
328+
329+
@pytest.mark.asyncio
330+
async def test_add_session_to_memory_success(self, mock_invocation_context):
331+
"""Test that add_session_to_memory calls the memory service correctly."""
332+
memory_service = AsyncMock()
333+
mock_invocation_context.memory_service = memory_service
334+
335+
context = CallbackContext(mock_invocation_context)
336+
await context.add_session_to_memory()
337+
338+
memory_service.add_session_to_memory.assert_called_once_with(
339+
mock_invocation_context.session
340+
)
341+
342+
@pytest.mark.asyncio
343+
async def test_add_session_to_memory_no_service_raises(
344+
self, mock_invocation_context
345+
):
346+
"""Test that add_session_to_memory raises ValueError when memory service is None."""
347+
mock_invocation_context.memory_service = None
348+
349+
context = CallbackContext(mock_invocation_context)
350+
351+
with pytest.raises(
352+
ValueError,
353+
match=(
354+
r"Cannot add session to memory: memory service is not available\."
355+
),
356+
):
357+
await context.add_session_to_memory()
358+
359+
@pytest.mark.asyncio
360+
async def test_add_session_to_memory_passes_through_service_exceptions(
361+
self, mock_invocation_context
362+
):
363+
"""Test that add_session_to_memory passes through exceptions from the memory service."""
364+
memory_service = AsyncMock()
365+
memory_service.add_session_to_memory.side_effect = Exception(
366+
"Memory service error"
367+
)
368+
mock_invocation_context.memory_service = memory_service
369+
370+
context = CallbackContext(mock_invocation_context)
371+
372+
with pytest.raises(Exception, match="Memory service error"):
373+
await context.add_session_to_memory()
374+
375+
376+
class TestToolContextAddSessionToMemory:
377+
"""Test the add_session_to_memory method in ToolContext."""
378+
379+
@pytest.mark.asyncio
380+
async def test_add_session_to_memory_success(self, mock_invocation_context):
381+
"""Test that ToolContext.add_session_to_memory calls the memory service correctly."""
382+
memory_service = AsyncMock()
383+
mock_invocation_context.memory_service = memory_service
384+
385+
tool_context = ToolContext(mock_invocation_context)
386+
await tool_context.add_session_to_memory()
387+
388+
memory_service.add_session_to_memory.assert_called_once_with(
389+
mock_invocation_context.session
390+
)
391+
392+
@pytest.mark.asyncio
393+
async def test_add_session_to_memory_no_service_raises(
394+
self, mock_invocation_context
395+
):
396+
"""Test that ToolContext.add_session_to_memory raises ValueError when memory service is None."""
397+
mock_invocation_context.memory_service = None
398+
399+
tool_context = ToolContext(mock_invocation_context)
400+
401+
with pytest.raises(
402+
ValueError,
403+
match=(
404+
r"Cannot add session to memory: memory service is not available\."
405+
),
406+
):
407+
await tool_context.add_session_to_memory()

0 commit comments

Comments
 (0)