Gemini connector joins plugin and function names with "__", which is legal in both, so two functions can share one tool name and the wrong one runs
Los mantenedores suelen responder en 2 días
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 58/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Activo
- Stack tecnológico
- google-cloud, python
- Área
- backend-api-design
Línea de trabajo
Comienza en python/semantic_kernel/connectors/ai/google/shared_utils.py y luego sigue los constructores de declaraciones de Gemini y Vertex en google_ai/services/utils.py y vertex_ai/services/utils.py. Lee la prueba del separador relacionada y las reglas de validación para entender las suposiciones existentes sobre el round-trip. La tarea estará terminada cuando los nombres de plugins/funciones que son válidos según la validación no puedan producir silenciosamente nombres de herramientas duplicados ni dirigir una llamada a la función incorrecta, con cobertura de regresión para la colisión notificada.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
The Gemini/Vertex connector joins plugin and function names with "__", but "__" is legal inside both halves. Two distinct kernel functions can therefore be emitted to the model under one identical tool name, and the reverse mapping routes the call to whichever wins the first-occurrence split — silently.
The comment above the constant already identifies this class
python/semantic_kernel/connectors/ai/google/shared_utils.py:
Using double underscore to avoid situations where the function name already contains a single underscore. For example, we may incorrect split a function name with a single score when the function doesn't have a plugin name.
The ambiguity was seen and "__" was chosen as the remedy. It closes the case where the function name contains a single underscore. It leaves open the case where the plugin name contains "__".
Where
GEMINI_FUNCTION_NAME_SEPARATOR = "__"
def format_gemini_function_name_to_kernel_function_fully_qualified_name(gemini_function_name: str) -> str:
if GEMINI_FUNCTION_NAME_SEPARATOR in gemini_function_name:
plugin_name, function_name = gemini_function_name.split(GEMINI_FUNCTION_NAME_SEPARATOR, 1)
return f"{plugin_name}{DEFAULT_FULLY_QUALIFIED_NAME_SEPARATOR}{function_name}"
return gemini_function_name
python/semantic_kernel/utils/validation.py permits _ in both:
PLUGIN_NAME_REGEX = ^[0-9A-Za-z_]+$
FUNCTION_NAME_REGEX = ^[0-9A-Za-z_-]+$
so plugin + "__" + function is not injective. Declarations are emitted without a duplicate-name check (google_ai/services/utils.py, vertex_ai/services/utils.py), so the model is handed two tools with the same name.
Reproduction
k = Kernel()
k.add_plugin(Utils(), plugin_name="utils") # function name: get__time
k.add_plugin(UtilsGet(), plugin_name="utils__get") # function name: time
=== tool declarations as the Gemini connector emits them ===
kernel fqn 'utils-get__time' -> gemini name 'utils__get__time'
kernel fqn 'utils__get-time' -> gemini name 'utils__get__time'
COLLISION: True
=== model calls 'utils__get__time' (meaning plugin utils__get / time) ===
converted kernel name: 'utils-get__time'
routed to plugin='utils' function='get__time'
python warnings raised: []
ACTUALLY EXECUTED: ['utils.get__time']
result returned to the model: 12:00 (from plugin 'utils', function 'get__time')
The model asked for one function, another ran, and the model was told it got what it asked for.
Negative controls
A — the default separator cannot collide, by construction. PLUGIN_NAME_REGEX forbids -, so split("-", maxsplit=1) always recovers the true plugin, and registering the colliding plugin name fails loudly:
LOUD: FunctionInitializationError: KernelFunction failed to initialize ...
'utils-get__time' -> plugin='utils' function='get__time' (correct)
B — a genuinely unknown name errors loudly:
The tool call with name `nosuch-func` is not part of the provided tools, please try again ...
Control A is the point: the same design applied to "__" would require forbidding __ in plugin names, and nothing does.
The silence
With logging at DEBUG and warnings.simplefilter("always"), the mis-routed call produced no warning and no error — only ordinary success logs:
INFO semantic_kernel.kernel: Calling utils-get__time function with args: {}
INFO semantic_kernel.functions.kernel_function: Function utils-get__time succeeded.
Three things compound it: the declaration list has no duplicate check; the allow-list in kernel.py compares against the post-split name, which is a genuinely allowed function, so validation passes; and the loud path that logs an error for a name resolving to nothing is never reached.
Scope
Reachability requires a plugin name containing __ in a kernel that also serves a Gemini/Vertex model. A function name containing __ alone round-trips correctly — I verified that. Plugin names come from a class name, an explicit plugin_name=, a directory name, or an OpenAPI/MCP import, so __ is uncommon but entirely legal and undefended.
The only test touching this exercises just the unambiguous plugin{SEP}function case, so the collision is untested rather than accepted.
Not tested: a live Gemini/Vertex round trip — the wire-name emission and reverse mapping are pure functions and were exercised directly, but I did not observe what Google's service does when handed two declarations sharing a name. If it rejects them, this degrades to a loud failure for that configuration; the local mis-split stands regardless. The dotnet/ and java/ implementations were out of scope.
I have not checked whether this was raised before; a pointer to an existing issue is welcome and I will close this in favour of it.
Version
semantic-kernel 1.44.1, source at ebc2ef9bb2d5b61db3b5c71fb5805c4824b4ad90, Python 3.12.
- Lenguaje dominante
- C#
- Estrellas
- 28.6k
- Forks
- 4.8k
- Merge medio
- 13 h 24 min
- PR fusionados (30 d)
- 11
Preparar el entorno
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de microsoft/semantic-kernel
-
python triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
microsoft/semantic-kernel#14491 · 1 comentario ·
Los mantenedores suelen responder en 2 días
-
python triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
microsoft/semantic-kernel#14490 · 1 comentario ·
Los mantenedores suelen responder en 2 días
-
Python: [Python] structured_outputs_transform reuses ChatHistory across calls (prompt pollution)Abiertopython triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
microsoft/semantic-kernel#14483 · 2 comentarios ·
Los mantenedores suelen responder en 2 días
-
.NET python triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
microsoft/semantic-kernel#14482 · 3 comentarios ·
Los mantenedores suelen responder en 2 días
-
Python: [Python] as_agent_framework_tool drops parameter defaults (optionals become required)Abiertopython triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
microsoft/semantic-kernel#14481 ·
Los mantenedores suelen responder en 2 días
Todos los issues de microsoft/semantic-kernel
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
microsoft/fluentui-blazor#5364 ·
Los mantenedores suelen responder en 1 día
-
.NET triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
microsoft/agent-framework#8811 ·
Los mantenedores suelen responder en 1 día
-
.NET Docs
Dificultad 1/5 Menos de una hora Aptitud para principiantes 82/100
getsentry/sentry-dotnet#5637 · 1 comentario ·
Los mantenedores suelen responder en 2 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
QuantConnect/Lean#9842 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
NethermindEth/nethermind#14012 ·
Los mantenedores suelen responder en 1 día