Skip to content

Gemini tool registration rejects integer-Choice constraints; use parametersJsonSchema instead of legacy parameters #262

@Kamilbenkirane

Description

@Kamilbenkirane

Summary

Registering any tool whose JSON schema has enum on a non-string property (e.g. {\"type\": \"integer\", \"enum\": [4, 6, 8]}) against Gemini's function-calling API fails with a 400. Celeste-AI passes the schema to the legacy functionDeclarations[].parameters field, which only permits enum on TYPE_STRING properties per Google's documented rule. This breaks tool-calling for every model whose parameter_constraints carry a non-string Choice.

Reproduction

Calling any Gemini text model with a tool fleet that includes one of these constraints fails:

  • Choice(options=[4, 6, 8])duration on all four Veo models
    • src/celeste/modalities/videos/providers/google/models.py:26 (veo-3.0-generate-001)
    • src/celeste/modalities/videos/providers/google/models.py:40 (veo-3.0-fast-generate-001)
    • src/celeste/modalities/videos/providers/google/models.py:54 (veo-3.1-generate-preview)
    • src/celeste/modalities/videos/providers/google/models.py:75 (veo-3.1-fast-generate-preview)
  • Choice(options=[768, 1536, 3072])dimensions on both Google embedding models
    • src/celeste/modalities/embeddings/providers/google/models.py:21 (gemini-embedding-001)
    • src/celeste/modalities/embeddings/providers/google/models.py:30 (gemini-embedding-2-preview)

Error

```
HTTPStatusError: google API error: Invalid value at
'tools[0].function_declarations[N].parameters.properties[M].value.enum[0]'
(TYPE_STRING), 4
```

Root cause

src/celeste/providers/google/generate_content/parameters.py:222 assigns the raw JSON schema to the legacy parameters field:

```python
result["parameters"] = schema
```

parameters is a narrow OpenAPI-2 subset where enum is valid only on TYPE_STRING properties (see https://ai.google.dev/api/caching#Schema: "Possible values of the element of Type.STRING with enum format"). _remove_titles is the only existing sanitization step; no coercion of non-string enums, no translation of composition keywords, no handling of $defs/$ref.

Proposed fix

Switch to the parametersJsonSchema field introduced in Gemini's November 2025 structured-outputs update (https://blog.google/technology/developers/gemini-api-structured-outputs/: "added support for JSON Schema to all actively supported Gemini models"). That field accepts native JSON Schema — integer enums, \$defs, \$ref, anyOf, oneOf, additionalProperties — with no sanitization.

```python

src/celeste/providers/google/generate_content/parameters.py:222

result["parametersJsonSchema"] = schema
```

parameters and parametersJsonSchema are mutually exclusive per Gemini's API reference (https://ai.google.dev/api/caching) — send one, not both.

Ecosystem precedent

  • pydantic-ai already uses parametersJsonSchema unconditionally in its Gemini provider: https://github.com/pydantic/pydantic-ai/blob/main/pydantic_ai_slim/pydantic_ai/models/google.py
  • Google's google-genai SDK Schema.from_json_schema(...) (the legacy-shape sanitizer) now emits deprecation warnings steering callers toward parametersJsonSchema.
  • LiteLLM still on legacy and silently drops integer enums. LangChain (langchain-google-genai) still on legacy and has the same bug (langchain-google/issues/409). Both are trailing indicators; celeste has no reason to follow.

Model compatibility

Every Gemini model currently registered in src/celeste/modalities/text/providers/google/models.py is 2.5+ or 3.x — all within Google's November 2025 "all actively supported Gemini models" set. No 1.0/1.5/2.0 entries to worry about.

Tests

  • New regression in tests/unit_tests/ (or the Google provider tests directory): build a tool with an integer Choice constraint, map it through ToolsMapper._map_user_tool, assert the emitted dict has parametersJsonSchema with the integer enum preserved (not coerced, not dropped).
  • Existing integration tests in tests/integration_tests/text/test_tools.py continue to pass — string-enum schemas flow through unchanged.

Scope

Single-line behavioral change + one new unit test. No API surface change for celeste-ai callers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions