Skip to content

Artifacts saved in before_agent_callback / after_agent_callback are never recorded in an event (artifact_delta dropped) #7478

Closed

Description

@AkshayShah03

🔴 Required Information

Describe the Bug:
An artifact saved with callback_context.save_artifact(...) inside a before_agent_callback or after_agent_callback is written to the artifact service, but its artifact_delta is never recorded in any session event.

BaseAgent._handle_agent_callbacks (src/google/adk/agents/base_agent.py) only emits an event when the callback returns content or when callback_context.state.has_delta() is true. A callback that only saves an artifact (and returns None) changes callback_context._event_actions.artifact_delta, but that is dropped because no event carries it.

Consequences: the session history has no record of the artifact, so Runner.rewind_async (which computes artifact changes from artifact_delta) will not revert it, and anything that surfaces artifacts from events (web UI, A2A) never sees it. The same artifact saved from a before_model_callback or a tool is recorded, and the workflow node runner already checks both state and artifact deltas.

Steps to Reproduce:

  1. pip install google-adk==2.11.0
  2. Run the snippet below.

Expected Behavior:

artifact keys: ['report.txt']
artifact_delta in session events: [{'report.txt': 0}]

Observed Behavior:

artifact keys: ['report.txt']
artifact_delta in session events: []

Environment Details:

  • ADK Library Version: 2.11.0 (also reproduced on main at 3d11f9f)
  • Desktop OS: macOS
  • Python Version: 3.12.13

Model Information:

  • Are you using LiteLLM: No
  • Which model is being used: N/A (no model call needed to reproduce)

🟡 Optional Information

Minimal Reproduction Code:

import asyncio
from google.adk.agents import BaseAgent
from google.adk.agents.callback_context import CallbackContext
from google.adk.artifacts import InMemoryArtifactService
from google.adk.events import Event
from google.adk.runners import Runner
from google.adk.sessions import InMemorySessionService
from google.genai import types


async def save_report(callback_context: CallbackContext):
  await callback_context.save_artifact(
      "report.txt", types.Part.from_text(text="hello")
  )


class EchoAgent(BaseAgent):
  async def _run_async_impl(self, ctx):
    yield Event(
        author=self.name,
        invocation_id=ctx.invocation_id,
        content=types.Content(role="model", parts=[types.Part(text="done")]),
    )


async def main():
  artifacts = InMemoryArtifactService()
  runner = Runner(
      app_name="app",
      agent=EchoAgent(name="agent", before_agent_callback=save_report),
      session_service=InMemorySessionService(),
      artifact_service=artifacts,
  )
  session = await runner.session_service.create_session(
      app_name="app", user_id="u"
  )
  async for _ in runner.run_async(
      user_id="u",
      session_id=session.id,
      new_message=types.Content(role="user", parts=[types.Part(text="hi")]),
  ):
    pass
  session = await runner.session_service.get_session(
      app_name="app", user_id="u", session_id=session.id
  )
  print("artifact keys:", await artifacts.list_artifact_keys(
      app_name="app", user_id="u", session_id=session.id))
  print("artifact_delta in session events:",
        [e.actions.artifact_delta for e in session.events
         if e.actions.artifact_delta])


asyncio.run(main())

How often has this issue occurred?:

  • Always (100%)

Proposed fix: In _handle_agent_callbacks, also emit the event when callback_context._event_actions.artifact_delta is non-empty, not only when state has a delta. I have a PR ready with unit tests for both callbacks.

Activity

  1. llalitkumarrr commented on Oct 13, 2026

    @llalitkumarrr
    Collaborator

    Hello @AkshayShah03,

    Thank you for the detailed report and your contribution. Your pull request is currently under review and will be merged once the reviewer approves the changes. We will reach out if we need any further details. Thank you for your patience in the meantime.

  2. added
    request clarification[Status] The maintainer need clarification or more information from the author
    core[Component] This issue is related to the core interface and implementation
    and removed
    tools[Component] This issue is related to tools
    request clarification[Status] The maintainer need clarification or more information from the author
    on Oct 13, 2026
  3. added a commit that references this issue on Oct 15, 2026
    019387c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

core[Component] This issue is related to the core interface and implementation

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions