-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Description
Describe the bug
I have noticed an inconsistency in how the ADK Web UI detects artifacts depending on the execution context.
When using save_artifact within a Tool context or Callback context, the ADK Web UI correctly detects the new artifact and displays the corresponding UI elements (e.g., artifact diffs or previews).
However, when implementing a custom agent (inheriting from BaseAgent) and manually saving an artifact using ctx.artifact_service.save_artifact within _run_async_impl (InvocationContext), the Web UI does not detect or display the artifact. Although the artifact is successfully saved to the backend service and the content is returned in the Event, the UI treats it as a standard message without the specific artifact UI features.
To Reproduce
Steps to reproduce the behavior:
- run adk web on file
- Type any text to test
- You should see the file is stored in artifact
All artifacts: ['test.jpg']import base64
import uuid
from typing import AsyncGenerator
from google.adk.agents import BaseAgent, InvocationContext
from google.adk.artifacts import InMemoryArtifactService
from google.adk.events.event import Event
from google.adk.apps import App
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types
from typing_extensions import override
class ImageAgent(BaseAgent):
name: str
def __init__(self, name: str):
super().__init__(name=name)
@override
async def _run_async_impl(
self, ctx: InvocationContext
) -> AsyncGenerator[Event, None]:
# assert ctx.artifact_service is not None
assert ctx.artifact_service is not None
# Save artifact if it doesn't exist
artifact_id = "test.jpg"
# Use a base64 encoded 1x1 pixel JPEG image for reproducibility without external files
image_b64 = (
"/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAP////////////////////////////////////"
"///////////////////////////////////////////////////wgALCAABAAEBAREA/8Q"
"AFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQABPxA="
)
image_data = base64.b64decode(image_b64)
part = types.Part(
inline_data=types.Blob(data=image_data, mime_type="image/jpeg")
)
if artifact_id not in await ctx.artifact_service.list_artifact_keys(
app_name=ctx.app_name, user_id=ctx.user_id, session_id=ctx.session.id
):
await ctx.artifact_service.save_artifact(
app_name=ctx.app_name,
user_id=ctx.user_id,
session_id=ctx.session.id,
filename=artifact_id,
artifact=part,
)
artifact = await ctx.artifact_service.load_artifact(
app_name=ctx.app_name,
user_id=ctx.user_id,
session_id=ctx.session.id,
filename=artifact_id,
)
processed_parts = [
types.Part(
text=f"[Retrieved Artifact] Below is the content of artifact ID : {artifact_id}"
),
artifact,
]
print(
"All artifacts:",
await ctx.artifact_service.list_artifact_keys(
app_name=ctx.app_name, user_id=ctx.user_id, session_id=ctx.session.id
),
)
yield Event(
id=str(uuid.uuid4()),
author=self.name,
partial=False,
content=types.Content(parts=processed_parts),
)
image_agent = ImageAgent(name="image_agent")
app = App(name="image_agent", root_agent=image_agent)Expected behavior
The ADK Web UI should recognize that an artifact has been generated/saved during the agent's execution and display it (e.g., in the artifact panel or as a recognized attachment), similar to how it behaves when a Tool returns an artifact.
Screenshots
Desktop (please complete the following information):
- OS: Linux
- Python version: 3.12.12
- ADK version: 1.22.1
Model Information:
- Are you using LiteLLM: No
Additional context
Is there a specific metadata field (e.g., artifact_ids) that should be attached to the Event object to notify the UI about the new artifact? Or is this a feature gap for custom agents?