@@ -177,12 +177,23 @@ def _create_event(
177177 actions : Optional [EventActions ] = None ,
178178 long_running_function_ids : Optional [set [str ]] = None ,
179179 partial : bool = False ,
180+ custom_metadata : Optional [dict [str , Any ]] = None ,
181+ error_code : Optional [str ] = None ,
182+ usage_metadata : Optional [
183+ genai_types .GenerateContentResponseUsageMetadata
184+ ] = None ,
180185) -> Optional [Event ]:
181186 """Creates an ADK event from parts and metadata."""
182187 event_actions = actions or EventActions ()
183- if not output_parts and not event_actions .model_dump (
184- exclude_none = True , exclude_defaults = True
185- ):
188+ has_actions = bool (
189+ event_actions .model_dump (exclude_none = True , exclude_defaults = True )
190+ )
191+ has_event_metadata = (
192+ custom_metadata is not None
193+ or error_code is not None
194+ or usage_metadata is not None
195+ )
196+ if not output_parts and not has_actions and not has_event_metadata :
186197 return None
187198
188199 event = Event (
@@ -206,6 +217,9 @@ def _create_event(
206217 else None
207218 ),
208219 partial = partial ,
220+ custom_metadata = custom_metadata ,
221+ error_code = error_code ,
222+ usage_metadata = usage_metadata ,
209223 )
210224
211225 return event
@@ -248,6 +262,59 @@ def _extract_event_actions(
248262 return EventActions ()
249263
250264
265+ def _extract_event_metadata (
266+ metadata : Optional [dict [str , Any ]],
267+ ) -> dict [str , Any ]:
268+ """Extracts ADK event metadata fields from A2A metadata.
269+
270+ Restores custom_metadata, error_code, and usage_metadata that were
271+ serialized by the outbound converter.
272+
273+ Args:
274+ metadata: The A2A metadata dictionary.
275+
276+ Returns:
277+ A dict of keyword arguments suitable for passing to _create_event().
278+ """
279+ if not metadata :
280+ return {}
281+
282+ result : dict [str , Any ] = {}
283+
284+ raw_custom = metadata .get (_get_adk_metadata_key ("custom_metadata" ))
285+ if raw_custom is not None :
286+ parsed = _parse_adk_metadata_value (raw_custom )
287+ if isinstance (parsed , dict ):
288+ result ["custom_metadata" ] = parsed
289+ else :
290+ logger .warning (
291+ "Ignoring invalid ADK custom_metadata of type %s" ,
292+ type (parsed ).__name__ ,
293+ )
294+
295+ raw_error_code = metadata .get (_get_adk_metadata_key ("error_code" ))
296+ if raw_error_code is not None :
297+ result ["error_code" ] = str (raw_error_code )
298+
299+ raw_usage = metadata .get (_get_adk_metadata_key ("usage_metadata" ))
300+ if raw_usage is not None :
301+ parsed = _parse_adk_metadata_value (raw_usage )
302+ if isinstance (parsed , dict ):
303+ try :
304+ result ["usage_metadata" ] = (
305+ genai_types .GenerateContentResponseUsageMetadata (** parsed )
306+ )
307+ except Exception as e :
308+ logger .warning ("Ignoring invalid ADK usage_metadata: %s" , e )
309+ else :
310+ logger .warning (
311+ "Ignoring invalid ADK usage_metadata of type %s" ,
312+ type (parsed ).__name__ ,
313+ )
314+
315+ return result
316+
317+
251318def _merge_top_level_dicts (
252319 base : dict [str , Any ], new_values : dict [str , Any ]
253320) -> dict [str , Any ]:
@@ -304,6 +371,7 @@ def convert_a2a_task_to_event(
304371
305372 try :
306373 event_actions = EventActions ()
374+ event_metadata : dict [str , Any ] = {}
307375 output_parts = []
308376 long_running_function_ids = set ()
309377 if a2a_task .artifacts :
@@ -314,6 +382,7 @@ def convert_a2a_task_to_event(
314382 event_actions = _merge_event_actions (
315383 event_actions , _extract_event_actions (artifact .metadata )
316384 )
385+ event_metadata .update (_extract_event_metadata (artifact .metadata ))
317386 output_parts , _ = _convert_a2a_parts_to_adk_parts (
318387 artifact_parts , part_converter
319388 )
@@ -325,6 +394,9 @@ def convert_a2a_task_to_event(
325394 event_actions ,
326395 _extract_event_actions (a2a_task .status .message .metadata ),
327396 )
397+ event_metadata .update (
398+ _extract_event_metadata (a2a_task .status .message .metadata )
399+ )
328400 parts , ids = _convert_a2a_parts_to_adk_parts (
329401 a2a_task .status .message .parts , part_converter
330402 )
@@ -337,6 +409,7 @@ def convert_a2a_task_to_event(
337409 author ,
338410 event_actions ,
339411 long_running_function_ids ,
412+ ** event_metadata ,
340413 )
341414
342415 except Exception as e :
@@ -375,11 +448,13 @@ def convert_a2a_message_to_event(
375448 output_parts , _ = _convert_a2a_parts_to_adk_parts (
376449 a2a_message .parts , part_converter
377450 )
451+ event_metadata = _extract_event_metadata (a2a_message .metadata )
378452 return _create_event (
379453 output_parts ,
380454 invocation_context ,
381455 author ,
382456 _extract_event_actions (a2a_message .metadata ),
457+ ** event_metadata ,
383458 )
384459
385460 except Exception as e :
@@ -412,10 +487,14 @@ def convert_a2a_status_update_to_event(
412487 output_parts = []
413488 long_running_function_ids = set ()
414489 event_actions = EventActions ()
490+ event_metadata : dict [str , Any ] = {}
415491 if a2a_status_update .status .message :
416492 event_actions = _extract_event_actions (
417493 a2a_status_update .status .message .metadata
418494 )
495+ event_metadata = _extract_event_metadata (
496+ a2a_status_update .status .message .metadata
497+ )
419498 parts , ids = _convert_a2a_parts_to_adk_parts (
420499 a2a_status_update .status .message .parts , part_converter
421500 )
@@ -428,6 +507,7 @@ def convert_a2a_status_update_to_event(
428507 author ,
429508 event_actions ,
430509 long_running_function_ids ,
510+ ** event_metadata ,
431511 )
432512 except Exception as e :
433513 logger .error ("Failed to convert A2A status update to event: %s" , e )
@@ -460,12 +540,16 @@ def convert_a2a_artifact_update_to_event(
460540 output_parts , _ = _convert_a2a_parts_to_adk_parts (
461541 a2a_artifact_update .artifact .parts , part_converter
462542 )
543+ event_metadata = _extract_event_metadata (
544+ a2a_artifact_update .artifact .metadata
545+ )
463546 return _create_event (
464547 output_parts ,
465548 invocation_context ,
466549 author ,
467550 _extract_event_actions (a2a_artifact_update .artifact .metadata ),
468551 partial = not a2a_artifact_update .last_chunk ,
552+ ** event_metadata ,
469553 )
470554 except Exception as e :
471555 logger .error ("Failed to convert A2A artifact update to event: %s" , e )
0 commit comments