Skip to content

Gemma4 tool-calling emits declaration-format echoes instead of <|tool_call> (function_calls always empty) #693

Description

@ncylich

Summary

For tool prompts, Gemma4 (via cactus) emits the declaration format that cactus injects for tool definitions (<|tool>declaration:NAME{...}, see gemma_tools.h:69/330) instead of the call format the parser expects (<|tool_call>...<tool_call|>, gemma_tools.h:527-530). As a result function_calls is always empty — cactus never parses a valid call.

This is systemic, not specific to multi-tool prompts.

Reproduce

cactus test --suite llm

All three tool cases show "function_calls": [] and a <|tool>declaration:... response:

Test Response (truncated) function_calls suite verdict
TOOL CALL (1 tool) <|tool>declaration:get_weather{...} [] PASS*
MULTIPLE (2 tools) <|tool>declaration:send_message{...schema echo...} [] FAIL
TRIPLE (3 tools) <|tool>declaration:send_message<|"|> ... [] PASS*

* The suite's pass/fail only checks whether the right tool name appears in the text — it does not require a parsed call. So the 1- and 3-tool cases "pass" despite producing no usable call; the 2-tool case fails that loose check because the echo is more garbled. The actual behavior (declaration echo, no parsed call) is the same in all three.

Likely root cause (cactus side)

The model is continuing in the <|tool>declaration: definition syntax cactus injected, rather than switching to the <|tool_call> call syntax cactus's parser requires. That points to the tool-call prompt/template/instruction in gemma_tools.h (how tools are framed and how the model is told to emit calls), not a Gemma model limitation — the model is producing the wrong kind of artifact, not a malformed call.

Not verified

Reference HF Gemma4 with its native tool-call format was not run, so a model/format-fit contribution isn't fully excluded. But the consistent declaration-echo against cactus's custom declaration: format is the strong signal.

Scope

Pre-existing; reproduces on main/baseline. Unrelated to the KV-compaction / growable-cache work on kv-compress-keydiff (found incidentally while running cactus test --suite llm during that PR's validation).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions