Skip to content

Commit 019387c

Browse files
AkshayShah03copybara-github
authored andcommitted
fix: record artifact_delta from before and after agent callbacks
Merge #7479 Fixes #7478 PiperOrigin-RevId: 1000226841
1 parent 456d2cb commit 019387c

2 files changed

Lines changed: 56 additions & 4 deletions

File tree

‎src/google/adk/agents/base_agent.py‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,8 @@ async def _handle_agent_callbacks(
569569
end_invocation_on_content: Whether returned content ends the invocation.
570570
571571
Returns:
572-
Optional[Event]: an event if a callback provides content or changed state.
572+
Optional[Event]: an event if a callback provides content or changed state
573+
or artifacts.
573574
"""
574575
callback_context = CallbackContext(ctx)
575576

@@ -601,7 +602,10 @@ async def _handle_agent_callbacks(
601602
ctx.end_invocation = True
602603
return ret_event
603604

604-
if callback_context.state.has_delta():
605+
if (
606+
callback_context.state.has_delta()
607+
or callback_context._event_actions.artifact_delta
608+
):
605609
return Event(
606610
invocation_id=ctx.invocation_id,
607611
author=self.name,
@@ -620,7 +624,8 @@ async def _handle_before_agent_callback(
620624
ctx: InvocationContext, the invocation context for this agent.
621625
622626
Returns:
623-
Optional[Event]: an event if callback provides content or changed state.
627+
Optional[Event]: an event if a callback provides content or changed state
628+
or artifacts.
624629
"""
625630
return await self._handle_agent_callbacks(
626631
ctx,
@@ -639,7 +644,8 @@ async def _handle_after_agent_callback(
639644
agent.
640645
641646
Returns:
642-
Optional[Event]: an event if callback provides content or changed state.
647+
Optional[Event]: an event if a callback provides content or changed state
648+
or artifacts.
643649
"""
644650
return await self._handle_agent_callbacks(
645651
invocation_context,

‎tests/unittests/agents/test_base_agent.py‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
from google.adk.agents.invocation_context import InvocationContext
3333
from google.adk.agents.llm_agent import LlmAgent
3434
from google.adk.apps.app import ResumabilityConfig
35+
from google.adk.artifacts.in_memory_artifact_service import InMemoryArtifactService
3536
from google.adk.events.event import Event
3637
from google.adk.plugins.base_plugin import BasePlugin
3738
from google.adk.plugins.plugin_manager import PluginManager
@@ -745,6 +746,51 @@ async def test_run_async_with_async_after_agent_callback_append_reply(
745746
)
746747

747748

749+
@pytest.mark.asyncio
750+
@pytest.mark.parametrize(
751+
('callback_field', 'filename', 'artifact_event_idx', 'reply_event_idx'),
752+
[
753+
('before_agent_callback', 'before_agent.txt', 0, 1),
754+
('after_agent_callback', 'after_agent.txt', 1, 0),
755+
],
756+
)
757+
async def test_run_async_agent_callback_records_artifact_delta(
758+
request: pytest.FixtureRequest,
759+
callback_field: str,
760+
filename: str,
761+
artifact_event_idx: int,
762+
reply_event_idx: int,
763+
) -> None:
764+
async def _save_artifact(callback_context: CallbackContext) -> None:
765+
await callback_context.save_artifact(
766+
filename, types.Part.from_text(text=f'saved in {callback_field}')
767+
)
768+
769+
agent = _TestingAgent(
770+
name=f'{request.function.__name__}_test_agent',
771+
before_agent_callback=(
772+
_save_artifact if callback_field == 'before_agent_callback' else None
773+
),
774+
after_agent_callback=(
775+
_save_artifact if callback_field == 'after_agent_callback' else None
776+
),
777+
)
778+
parent_ctx = await _create_parent_invocation_context(
779+
request.function.__name__, agent
780+
)
781+
parent_ctx.artifact_service = InMemoryArtifactService()
782+
783+
events = [e async for e in agent.run_async(parent_ctx)]
784+
785+
assert len(events) == 2
786+
assert events[artifact_event_idx].author == agent.name
787+
assert events[artifact_event_idx].content is None
788+
assert events[artifact_event_idx].actions.artifact_delta == {filename: 0}
789+
assert events[reply_event_idx].content == types.Content(
790+
parts=[types.Part(text='Hello, world!')]
791+
)
792+
793+
748794
@pytest.mark.asyncio
749795
@pytest.mark.parametrize('method_name', ['run_async', 'run_live'])
750796
@pytest.mark.parametrize('exit_type', ['cancelled', 'generator_exit'])

0 commit comments

Comments
 (0)