Summary
Follow-up from @astrogilda's review of #1191 / #1175.
Blocking DefaultRequestHandlerV2.on_message_send returns successfully when it sees a Task in any terminal state, including FAILED:
if isinstance(event, Task) and (
params.configuration.return_immediately
or event.status.state
in (TERMINAL_TASK_STATES | INTERRUPTED_TASK_STATES)
):
self._validate_task_id_match(task_id, event.id)
result = event
break
A producer crash that also emits TaskStatusUpdateEvent(FAILED) (with replace_status_update_with_task=True) therefore becomes a successful blocking message/send instead of an A2AClientError. Scenarios 9 and 12 encode the current contract: the producer exception must surface.
That is why #1191 persists FAILED + push on producer-failure but does not enqueue a FAILED status event on the subscriber stream. After #1191, a streaming client that survives the exception still cannot distinguish "the producer crashed" from "the connection dropped" without a get_task() poll.
Proposal
Treat a FAILED terminal Task as an error on the blocking path (or keep reading until the producer exception arrives), so a FAILED status event can be published to live streams without converting a crash into success. Until then, #1175's producer-failure half stays polling-dependent.
Related
Summary
Follow-up from @astrogilda's review of #1191 / #1175.
Blocking
DefaultRequestHandlerV2.on_message_sendreturns successfully when it sees aTaskin any terminal state, includingFAILED:A producer crash that also emits
TaskStatusUpdateEvent(FAILED)(withreplace_status_update_with_task=True) therefore becomes a successful blockingmessage/sendinstead of anA2AClientError. Scenarios 9 and 12 encode the current contract: the producer exception must surface.That is why #1191 persists
FAILED+ push on producer-failure but does not enqueue a FAILED status event on the subscriber stream. After #1191, a streaming client that survives the exception still cannot distinguish "the producer crashed" from "the connection dropped" without aget_task()poll.Proposal
Treat a
FAILEDterminalTaskas an error on the blocking path (or keep reading until the producer exception arrives), so a FAILED status event can be published to live streams without converting a crash into success. Until then, #1175's producer-failure half stays polling-dependent.Related