Skip to content

fix(agents): record artifact_delta from before/after agent callbacks - #7479

Closed
AkshayShah03 wants to merge 1 commit into
google:mainfrom
AkshayShah03:fix/agent-callback-artifact-delta
Closed

AkshayShah03 wants to merge 1 commit into
google:mainfrom
AkshayShah03:fix/agent-callback-artifact-delta

Conversation

@AkshayShah03

Copy link
Copy Markdown
Contributor

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

Problem:
BaseAgent._handle_agent_callbacks only returns an event when a callback returns content or callback_context.state.has_delta() is true. An artifact saved via callback_context.save_artifact() in a before_agent_callback / after_agent_callback that returns None is stored by the artifact service, but its artifact_delta is never put on any event. The session has no record of it, so Runner.rewind_async cannot revert it and event-based artifact surfacing (web UI, A2A) never sees it.

Solution:
Also emit the event when callback_context._event_actions.artifact_delta is non-empty. This matches the workflow node runner, which already checks both state and artifact deltas, and the model/tool callback paths, which already record artifacts saved there.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

Added to tests/unittests/agents/test_base_agent.py:

  • test_run_async_before_agent_callback_records_artifact_delta
  • test_run_async_after_agent_callback_records_artifact_delta

Each saves an artifact from the callback (returning None) and asserts an event carries artifact_delta == {'<name>': 0}. Both fail on main (only the agent's own response event is produced) and pass with this change.

$ pytest tests/unittests/agents tests/unittests/flows tests/unittests/runners
2215 passed, 1 skipped, 5 xfailed

$ pytest tests/unittests -n auto
18347 passed, 4 failed

The 4 failures are in tests/unittests/models/test_litellm.py log-level assertions; they pass when run alone or as their own file, and with this change stashed, so they are unrelated to this PR.

pyink and isort report no changes.

Manual End-to-End (E2E) Tests:

Ran the reproduction script from #7478 through a real Runner with InMemorySessionService and InMemoryArtifactService:

  • on main: artifact_delta in session events: []
  • with this change: artifact_delta in session events: [{'report.txt': 0}]

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

_handle_agent_callbacks only emitted an event when a callback returned
content or changed state, so an artifact saved via
callback_context.save_artifact() in before_agent_callback or
after_agent_callback was stored but never recorded in a session event.
Rewind and event-based artifact surfacing therefore missed it. Also emit
the event when the callback context carries an artifact_delta.

Fixes google#7478
copybara-service Bot pushed a commit that referenced this pull request Oct 15, 2026
@adk-bot

adk-bot commented Oct 15, 2026

Copy link
Copy Markdown
Collaborator

Thank you @AkshayShah03 for your contribution! 🎉

Your changes have been successfully imported and merged via Copybara in commit 019387c.

Closing this PR as the changes are now in the main branch.

@adk-bot adk-bot added the merged [Status] This PR is merged label Oct 15, 2026
@adk-bot adk-bot closed this Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merged [Status] This PR is merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

3 participants