@@ -206,18 +206,18 @@ def _build_context_metadata(event: Event, ctx: InvocationContext) -> Dict[str, A
206206 return metadata
207207
208208
209- def _build_message_metadata (event : Event ) -> Dict [str , Any ]:
209+ def _build_message_metadata (event : Event , effective_id : str ) -> Dict [str , Any ]:
210210 """Build message/event metadata (object_type, tag, llm_response_id)."""
211211 return {
212212 MESSAGE_METADATA_OBJECT_TYPE_KEY : _infer_message_object_type (event ) or "" ,
213213 MESSAGE_METADATA_TAG_KEY : _infer_message_tag (event ),
214- MESSAGE_METADATA_RESPONSE_ID_KEY : event . response_id or "" ,
214+ MESSAGE_METADATA_RESPONSE_ID_KEY : effective_id ,
215215 }
216216
217217
218- def _build_event_metadata (event : Event , message : Message , ctx : InvocationContext ) -> Dict [str , Any ]:
218+ def _build_event_metadata (event : Event , message : Message , ctx : InvocationContext , effective_id : str ) -> Dict [str , Any ]:
219219 metadata = _build_context_metadata (event , ctx )
220- msg_meta = _build_message_metadata (event )
220+ msg_meta = _build_message_metadata (event , effective_id )
221221 set_metadata (metadata , MESSAGE_METADATA_OBJECT_TYPE_KEY , msg_meta .get (MESSAGE_METADATA_OBJECT_TYPE_KEY ) or "" )
222222 set_metadata (metadata , MESSAGE_METADATA_TAG_KEY , msg_meta .get (MESSAGE_METADATA_TAG_KEY ) or "" )
223223 set_metadata (metadata , MESSAGE_METADATA_RESPONSE_ID_KEY , msg_meta .get (MESSAGE_METADATA_RESPONSE_ID_KEY ) or "" )
@@ -240,13 +240,21 @@ def _mark_long_running_tools(a2a_parts: List[A2APart], event: Event) -> None:
240240 set_metadata (root .metadata , A2A_DATA_PART_METADATA_IS_LONG_RUNNING_KEY , True )
241241
242242
243- def _build_message (event : Event , a2a_parts : List [A2APart ], role : Role ) -> Optional [Message ]:
243+ def _effective_response_id (event : Event ) -> str :
244+ """Return ``response_id`` when present, otherwise a new UUID.
245+
246+ Callers that need the same id across multiple locations should invoke this
247+ once and pass the result explicitly.
248+ """
249+ return event .response_id or str (uuid .uuid4 ())
250+
251+
252+ def _build_message (event : Event , a2a_parts : List [A2APart ], role : Role , effective_id : str ) -> Optional [Message ]:
244253 """Assemble an A2A Message from converted parts, or return None if empty."""
245254 if not a2a_parts :
246255 return None
247- message_id = event .response_id or str (uuid .uuid4 ())
248- message = Message (message_id = message_id , role = role , parts = a2a_parts )
249- msg_meta = _build_message_metadata (event )
256+ message = Message (message_id = effective_id , role = role , parts = a2a_parts )
257+ msg_meta = _build_message_metadata (event , effective_id )
250258 if msg_meta :
251259 message .metadata = msg_meta
252260 return message
@@ -320,7 +328,8 @@ def convert_event_to_a2a_message(
320328 return None
321329
322330 a2a_parts = _collect_parts (event , ** rules )
323- return _build_message (event , a2a_parts , role )
331+ effective_id = _effective_response_id (event )
332+ return _build_message (event , a2a_parts , role , effective_id )
324333
325334
326335def convert_content_to_a2a_message (
@@ -596,6 +605,7 @@ def _create_status_update_event(
596605 event : Event ,
597606 task_id : Optional [str ],
598607 context_id : Optional [str ],
608+ effective_id : str = "" ,
599609) -> TaskStatusUpdateEvent :
600610 status = TaskStatus (state = TaskState .working , message = message , timestamp = _now_iso ())
601611
@@ -614,7 +624,7 @@ def _create_status_update_event(
614624 task_id = task_id ,
615625 context_id = context_id ,
616626 status = status ,
617- metadata = _build_event_metadata (event , message , ctx ),
627+ metadata = _build_event_metadata (event , message , ctx , effective_id ),
618628 final = False ,
619629 )
620630
@@ -626,8 +636,9 @@ def _create_artifact_update_event(
626636 task_id : Optional [str ] = None ,
627637 context_id : Optional [str ] = None ,
628638 last_chunk : bool = False ,
639+ effective_id : str = "" ,
629640) -> TaskArtifactUpdateEvent :
630- artifact_id = "" if last_chunk else ( event . response_id or "" )
641+ artifact_id = "" if last_chunk else effective_id
631642 return TaskArtifactUpdateEvent (
632643 task_id = task_id ,
633644 context_id = context_id ,
@@ -636,7 +647,7 @@ def _create_artifact_update_event(
636647 parts = [] if last_chunk else message .parts ,
637648 ),
638649 last_chunk = last_chunk ,
639- metadata = _build_event_metadata (event , message , ctx ),
650+ metadata = _build_event_metadata (event , message , ctx , effective_id ),
640651 )
641652
642653
@@ -674,12 +685,14 @@ def _notify(evt: A2AEvent) -> None:
674685
675686 message = convert_event_to_a2a_message (event , invocation_context )
676687 if message :
688+ effective_id = message .message_id
677689 status_event = _create_status_update_event (
678690 message ,
679691 invocation_context ,
680692 event ,
681693 task_id ,
682694 context_id ,
695+ effective_id = effective_id ,
683696 )
684697 _notify (status_event )
685698
@@ -691,6 +704,7 @@ def _notify(evt: A2AEvent) -> None:
691704 task_id = task_id ,
692705 context_id = context_id ,
693706 last_chunk = False ,
707+ effective_id = effective_id ,
694708 )
695709 a2a_events .append (artifact_event )
696710
0 commit comments