@@ -508,6 +508,53 @@ async def test_metadata_field_mapping(
508508 assert retrieved_none.metadata == {}
509509
510510
511+ @pytest.mark.asyncio
512+ async def test_metadata_empty_transitions(
513+ vertex_store: VertexTaskStore,
514+ ) -> None:
515+ """Test that updating metadata between {} and None does not generate events."""
516+ task_id = 'task-metadata-empty-test'
517+
518+ # Step 1: Create task with metadata={}
519+ task = Task(
520+ id=task_id,
521+ context_id='session-meta-empty',
522+ status=TaskStatus(state=TaskState.submitted),
523+ kind='task',
524+ metadata={},
525+ )
526+ await vertex_store.save(task)
527+
528+ full_name = f'{vertex_store._agent_engine_resource_id}/a2aTasks/{task_id}'
529+
530+ # Get initial event sequence number
531+ stored_task_before = (
532+ await vertex_store._client.aio.agent_engines.a2a_tasks.get(full_name)
533+ )
534+ initial_seq = stored_task_before.next_event_sequence_number
535+
536+ # Step 2: Update metadata to None
537+ updated_task = task.model_copy(deep=True)
538+ updated_task.metadata = None
539+ await vertex_store.save(updated_task)
540+
541+ # Step 3: Update back to {}
542+ task_back = updated_task.model_copy(deep=True)
543+ task_back.metadata = {}
544+ await vertex_store.save(task_back)
545+
546+ # Verify that retrieved task still has {} (due to mapping)
547+ retrieved = await vertex_store.get(task_id)
548+ assert retrieved is not None
549+ assert retrieved.metadata == {}
550+
551+ # Verify that next_event_sequence_number did NOT increase (no events generated)
552+ stored_task_after = (
553+ await vertex_store._client.aio.agent_engines.a2a_tasks.get(full_name)
554+ )
555+ assert stored_task_after.next_event_sequence_number == initial_seq
556+
557+
511558@pytest.mark.asyncio
512559async def test_update_task_status_details(
513560 vertex_store: VertexTaskStore,
0 commit comments