ash-project / ash-project/ash_ai
Gemini API compatibility issue: Function calling JSON schema generation fails with 400 INVALID_ARGUMENT (Proto field is not repeating)
- Dominant language
- Elixir
- Stars
- 189
- Forks
- 89
- Avg merge
- 8h 32m
- Merged PRs (30d)
- 3
Description
### Code of Conduct
- [x] I agree to follow this project's Code of Conduct
### AI Policy
- [x] I agree to follow this project's AI Policy, or I agree that AI was not used while creating this issue.
### Versions
* Elixir version: 1.19.5
* Erlang/OTP version: 28 [erts-16.1]
* ash_ai version: 0.7.2
* req_llm version: 1.17.0
* LLM Model: Gemini (e.g., gemini-3.1-flash-lite / gemini-2.5-flash)
### Operating system
macOS
### Current Behavior
When the AI attempts to use a registered tool mapped to a typical Ash Read action (e.g., listing resources or fetching history), the API returns a 400 INVALID_ARGUMENT error due to invalid JSON schema structure.
When using ash_ai with the Gemini adapter (via req_llm), the automatic tool generation for Ash Read Actions fails. Gemini's API rejects the generated JSON schema because it contains nested structures or array-wrapped types for properties that Gemini expects to be flat scalar types or objects.
This happens because Gemini enforces a strict subset of OpenAPI 3.0 for its function calling parameters, and the translation from Ash Action arguments/metadata to JSON schema produces schemas that OpenAI accepts but Gemini strictly rejects.
### Error Logs:
```text
[warning] Metadata collection failed: %ReqLLM.Error.API.Request{
reason: "Invalid JSON payload received. Unknown name \"type\" at 'tools[0].function_declarations[0].parameters.properties[0].value': Proto field is not repeating, cannot start list.",
status: 400,
response_body: %{
"code" => 400,
"details" => [
%{
"@type" => "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations" => [
%{"description" => "Invalid JSON payload received. Unknown name \"type\" at 'tools[0].function_declarations[0].parameters.properties[0].value': Proto field is not repeating, cannot start list.", "field" => "tools[0].function_declarations[0].parameters.properties[0].value"}
]
}
],
"message" => "Invalid JSON payload received. Unknown name \"type\" at 'tools[0].function_declarations[0].parameters.properties[0].value': Proto field is not repeating, cannot start list.",
"status" => "INVALID_ARGUMENT"
}
}
** (Ash.Error.Unknown)
Bread Crumbs:
> Exception raised in: Draco.Chat.Message.respond
Api Error
* Stream failed: %ReqLLM.Error.API.Request{...}
(ash_ai 0.7.2) lib/ash_ai/tool_loop.ex:143: AshAi.ToolLoop.stream_iteration/1
(ash_ai 0.7.2) lib/ash_ai/tool_loop.ex:104: AshAi.ToolLoop.next_stream_chunk/1
```
### Reproduction
_No response_
### Expected Behavior
`ash_ai` should detect the adapter type or generate a Gemini-compatible strict OpenAPI 3.0 schema for registered tools, allowing the AI to successfully invoke standard Ash Read actions without payload validation errors.
Contributor guide
Research direction
Start at lib/ash_ai/tool_loop.ex:104 and :143, then trace how registered Ash Read actions become tool schemas through the Gemini adapter. Reproduce with the listed Elixir, ash_ai, req_llm, and Gemini versions and inspect the generated schema against the reported API error. Done means standard Ash Read tools are accepted by Gemini, with coverage for the failing schema case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- elixir
- Domain
- ai, api
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100