Summary
include_artifacts_in_a2a_event_interceptor was added in commit e63d991 to allow artifact delivery on the A2A path. However it is opt-in only — A2aAgentExecutorConfig.execute_interceptors defaults to None, and fast_api.py constructs A2aAgentExecutor with no config.
As a result, agents that save artifacts during a run (via artifact_service.save_artifact) have no way to deliver them to A2A callers without patching internal ADK code. Issue #3630 was closed as resolved but the fix is incomplete.
Reproduction
- Build an agent that calls
artifact_service.save_artifact() during a run
- Call the agent via A2A
message/send or message/stream
- Observe: no
TaskArtifactUpdateEvent is emitted — event.actions.artifact_delta is silently dropped
Root cause
In fast_api.py:
agent_executor = A2aAgentExecutor(
runner=create_a2a_runner_loader(app_name),
# no config passed — execute_interceptors defaults to None
)
In config.py:
execute_interceptors: Optional[list[ExecuteInterceptor]] = None
# interceptor exists but never wired
Proposed fix
Default execute_interceptors to [include_artifacts_in_a2a_event_interceptor] in A2aAgentExecutorConfig:
from .interceptors.include_artifacts_in_a2a_event import include_artifacts_in_a2a_event_interceptor
execute_interceptors: list[ExecuteInterceptor] = dataclasses.field(
default_factory=lambda: [include_artifacts_in_a2a_event_interceptor]
)
This is a non-breaking change — the interceptor is a no-op when artifact_delta is empty or artifact_service is None. Users who want to opt out can pass execute_interceptors=[] explicitly.
Relates to
Closes #3630 (actually)
Summary
include_artifacts_in_a2a_event_interceptorwas added in commit e63d991 to allow artifact delivery on the A2A path. However it is opt-in only —A2aAgentExecutorConfig.execute_interceptorsdefaults toNone, andfast_api.pyconstructsA2aAgentExecutorwith no config.As a result, agents that save artifacts during a run (via
artifact_service.save_artifact) have no way to deliver them to A2A callers without patching internal ADK code. Issue #3630 was closed as resolved but the fix is incomplete.Reproduction
artifact_service.save_artifact()during a runmessage/sendormessage/streamTaskArtifactUpdateEventis emitted —event.actions.artifact_deltais silently droppedRoot cause
In
fast_api.py:In
config.py:Proposed fix
Default
execute_interceptorsto[include_artifacts_in_a2a_event_interceptor]inA2aAgentExecutorConfig:This is a non-breaking change — the interceptor is a no-op when
artifact_deltais empty orartifact_serviceisNone. Users who want to opt out can passexecute_interceptors=[]explicitly.Relates to
Closes #3630 (actually)