@@ -575,6 +575,90 @@ def _is_gemini_agent_resource(agent: str) -> bool:
575575 )
576576
577577
578+ def _get_resolved_location (api_client : Any ) -> Optional [str ]:
579+ """Returns the location configured on the API client."""
580+ return getattr (api_client , "location" , None )
581+
582+
583+ def _normalize_interaction_resource (
584+ interaction : str , agent : str , location : Optional [str ]
585+ ) -> str :
586+ """Normalizes an interaction id into a full resource name.
587+
588+ A bare interaction id is expanded to
589+ `projects/{project}/locations/{location}/interactions/{id}` using the
590+ project and location parsed from the agent resource name. Fully-qualified
591+ interaction resource names are returned unchanged.
592+ """
593+ if interaction .startswith ("projects/" ):
594+ return interaction
595+ parts = agent .split ("/" )
596+ project = parts [1 ]
597+ agent_location = parts [3 ] if len (parts ) > 3 else (location or "global" )
598+ return f"projects/{ project } /locations/{ agent_location } /interactions/{ interaction } "
599+
600+
601+ def _build_interaction_id_dataset (
602+ loaded_data : list [dict [str , Any ]],
603+ agent : Optional [str ],
604+ location : Optional [str ],
605+ ) -> Optional [types .EvaluationDataset ]:
606+ """Builds an EvaluationDataset from rows that carry an `interaction_id`.
607+
608+ When the dataset contains an `interaction_id` column, each row is turned
609+ into an EvalCase whose `interactions_data_source` references the interaction
610+ and the Gemini agent. The backend resolves the interaction trace and agent
611+ config; no client-side prompt/response is required. Returns None if the
612+ data does not contain interaction ids.
613+ """
614+ has_interaction_id = bool (loaded_data ) and any (
615+ _evals_constant .INTERACTION_ID in row for row in loaded_data
616+ )
617+ if not has_interaction_id :
618+ if agent :
619+ raise ValueError (
620+ "An `agent` was provided but the dataset does not contain an"
621+ " `interaction_id` column. The `agent` argument is only used to"
622+ " resolve an `interaction_id` dataset column (so the backend can"
623+ " fetch the interaction trace and Agent config). To evaluate"
624+ " with an agent, provide a dataset with an `interaction_id`"
625+ " column; otherwise omit `agent`."
626+ )
627+ return None
628+
629+ if not agent :
630+ raise ValueError (
631+ "An `agent` resource name is required when the dataset contains an"
632+ " `interaction_id` column, so the backend can resolve the Agent"
633+ " config for each interaction."
634+ )
635+ if not _is_gemini_agent_resource (agent ):
636+ raise ValueError (
637+ "`agent` must be a Gemini Agents API resource name of the form"
638+ " projects/{project}/locations/{location}/agents/{agent} when"
639+ " evaluating interaction ids. Got: %s" % agent
640+ )
641+
642+ gemini_agent_config = types .GeminiAgentConfig (gemini_agent = agent )
643+ eval_cases = []
644+ for i , row in enumerate (loaded_data ):
645+ interaction = row .get (_evals_constant .INTERACTION_ID )
646+ if not interaction :
647+ raise ValueError ("Missing `interaction_id` value for row %d." % i )
648+ eval_cases .append (
649+ types .EvalCase (
650+ eval_case_id = "eval_case_%s" % i ,
651+ interactions_data_source = types .InteractionsDataSource (
652+ interaction = _normalize_interaction_resource (
653+ str (interaction ), agent , location
654+ ),
655+ gemini_agent_config = gemini_agent_config ,
656+ ),
657+ )
658+ )
659+ return types .EvaluationDataset (eval_cases = eval_cases )
660+
661+
578662def _add_evaluation_run_labels (
579663 labels : Optional [dict [str , str ]] = None ,
580664 agent : Optional [str ] = None ,
@@ -1591,6 +1675,8 @@ def _resolve_dataset_inputs(
15911675 dataset_schema : Optional [Literal ["GEMINI" , "FLATTEN" , "OPENAI" ]],
15921676 loader : "_evals_utils.EvalDatasetLoader" ,
15931677 agent_info : Optional [types .evals .AgentInfo ] = None ,
1678+ agent : Optional [str ] = None ,
1679+ api_client : Any = None ,
15941680) -> tuple [types .EvaluationDataset , int ]:
15951681 """Loads and processes single or multiple datasets for evaluation.
15961682
@@ -1640,6 +1726,13 @@ def _resolve_dataset_inputs(
16401726 ds_source_for_loader = _get_dataset_source (ds_item )
16411727 current_loaded_data = loader .load (ds_source_for_loader )
16421728
1729+ interaction_dataset = _build_interaction_id_dataset (
1730+ current_loaded_data , agent , _get_resolved_location (api_client )
1731+ )
1732+ if interaction_dataset is not None :
1733+ parsed_evaluation_datasets .append (interaction_dataset )
1734+ continue
1735+
16431736 if dataset_schema :
16441737 current_schema = _evals_data_converters .EvalDatasetSchema (dataset_schema )
16451738 else :
@@ -1797,6 +1890,7 @@ def _execute_evaluation( # type: ignore[no-untyped-def]
17971890 api_client : Any ,
17981891 dataset : Union [types .EvaluationDataset , list [types .EvaluationDataset ]],
17991892 metrics : list [types .Metric ],
1893+ agent : Optional [str ] = None ,
18001894 dataset_schema : Optional [Literal ["GEMINI" , "FLATTEN" , "OPENAI" ]] = None ,
18011895 dest : Optional [str ] = None ,
18021896 location : Optional [str ] = None ,
@@ -1877,6 +1971,8 @@ def _execute_evaluation( # type: ignore[no-untyped-def]
18771971 dataset_schema = dataset_schema ,
18781972 loader = loader ,
18791973 agent_info = validated_agent_info ,
1974+ agent = agent ,
1975+ api_client = api_client ,
18801976 )
18811977
18821978 resolved_metrics = _resolve_metrics (metrics , api_client )
0 commit comments