Skip to content

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

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions