diff --git a/src/google/adk/cli/cli_eval.py b/src/google/adk/cli/cli_eval.py index f191f5efba..88ca680ba3 100644 --- a/src/google/adk/cli/cli_eval.py +++ b/src/google/adk/cli/cli_eval.py @@ -53,7 +53,12 @@ # This is always optional unless explicitly specified. RESPONSE_EVALUATION_SCORE_KEY = "response_evaluation_score" -EVAL_SESSION_ID_PREFIX = "___eval___session___" +# Must stay in sync with google.adk.evaluation.local_eval_service. The prefix +# is only allowed to contain lowercase letters, digits and hyphens so the +# generated eval session IDs satisfy the custom-session-ID constraints of +# remote backends such as Vertex AI Agent Engine. See +# https://github.com/google/adk-python/issues/6683 +EVAL_SESSION_ID_PREFIX = "eval-session-" DEFAULT_CRITERIA = { TOOL_TRAJECTORY_SCORE_KEY: 1.0, # 1-point scale; 1.0 is perfect. RESPONSE_MATCH_SCORE_KEY: 0.8, diff --git a/src/google/adk/evaluation/local_eval_service.py b/src/google/adk/evaluation/local_eval_service.py index 16dcc514c8..065d7a7942 100644 --- a/src/google/adk/evaluation/local_eval_service.py +++ b/src/google/adk/evaluation/local_eval_service.py @@ -62,7 +62,13 @@ logger = logging.getLogger("google_adk." + __name__) -EVAL_SESSION_ID_PREFIX = "___eval___session___" +# Note: must only contain lowercase letters, digits and hyphens, and start +# and end with an alphanumeric character once the UUID is appended. Custom +# session IDs are passed to the configured SessionService (e.g. Vertex +# AiSessionService), which forwards them to remote backends such as Agent +# Engine that enforce this constraint. See +# https://github.com/google/adk-python/issues/6683 +EVAL_SESSION_ID_PREFIX = "eval-session-" def _get_session_id() -> str: diff --git a/tests/unittests/evaluation/test_eval_session_id.py b/tests/unittests/evaluation/test_eval_session_id.py new file mode 100644 index 0000000000..f544a208f8 --- /dev/null +++ b/tests/unittests/evaluation/test_eval_session_id.py @@ -0,0 +1,41 @@ +# Copyright 2026 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from __future__ import annotations + +import re + +from google.adk.evaluation.local_eval_service import _get_session_id + +# Vertex AI Agent Engine Sessions only accept custom session IDs that match +# `[a-z0-9-]`, with a letter or digit as the first and last character. +# See https://github.com/google/adk-python/issues/6683 +_AGENT_ENGINE_SESSION_ID_PATTERN = re.compile(r'^[a-z0-9-]+$') + + +def test_eval_session_id_matches_agent_engine_constraints(): + # Regression test for https://github.com/google/adk-python/issues/6683 + # The generated eval session ID is passed straight to the configured + # SessionService (e.g. VertexAiSessionService), which forwards it to remote + # backends such as Agent Engine as a custom session ID. IDs containing + # underscores or uppercase letters are rejected by the remote API, so the + # generated ID must match `[a-z0-9-]` and start/end with an alphanumeric + # character. + session_id = _get_session_id() + assert _AGENT_ENGINE_SESSION_ID_PATTERN.fullmatch(session_id), ( + f'Generated eval session id {session_id!r} must match' + f' {_AGENT_ENGINE_SESSION_ID_PATTERN.pattern}.' + ) + assert session_id[0].isalnum() + assert session_id[-1].isalnum()