Skip to content

BeforeModel hook with llm_request modification destroys non-text parts, causing tool-call loops #25558

@mk-imagine

Description

@mk-imagine

What happened?

HookTranslatorGenAIv1.fromHookLLMRequest rebuilds the SDK request's contents as text-only from hookRequest.messages, discarding every non-text part (functionCall, functionResponse, inlineData, thought, etc.) from baseRequest.

Source location (v0.38.1 bundled install): bundle/chunk-ZTFHMKKJ.js:313774 — originally from packages/core/src/hooks/hookTranslator.ts.

This breaks any BeforeModel hook that modifies text in conversations containing tool calls. The symptom is an infinite tool-call loop: the hook strips tool call/response history, the model loses its prior tool context, and it re-invokes the same tool.

Root cause: toHookLLMRequest intentionally filters to text-only for a simplified hook API (by design — documented in the source). fromHookLLMRequest does not reverse that mapping — it replaces all contents wholesale instead of merging text changes back into the original structure.

Reproduction (confirmed against v0.38.1 on macOS):

  1. Register a BeforeModel hook that modifies text in llm_request.messages (e.g., PII redaction)
  2. Start a conversation that triggers at least one tool call
  3. In a follow-up turn, submit a prompt the hook modifies
  4. Observe the model repeatedly re-invoking the same tool — it never sees prior tool results

Queries where the hook returns {} (no modification) work correctly because the original SDK request is preserved unchanged.

What did you expect to happen?

A BeforeModel hook modifying text should update text-bearing contents in place while preserving all non-text parts (functionCall, functionResponse, etc.) and their positional ordering in the conversation history.

Client information

Client Information

Platform: macOS (Darwin 25.4.0), Node v24.14.0

> /about
About Gemini CLI

CLI Version      0.38.1
Git Commit       7f5580034
Model            Auto (Gemini 3)
Sandbox          no sandbox
OS               darwin
Auth Method      Signed in with Google (email redacted)
Tier             Gemini Code Assist in Google One AI Pro

Anything else we need to know?

A fix with passing tests was submitted as #23340 (auto-closed on 2026-04-05 under the 14-day no-help-wanted policy, not for code reasons — Gemini Code Assist's own review noted "The implementation is robust... I found no issues"). Happy to rebase and resubmit against the current bundled layout if this issue gets labeled help wanted.

Real-world impact: this bug blocks any hook-based PII blinding/redaction use case (FERPA, HIPAA, etc.) because those hooks must modify text, and production agent loops always contain tool calls.

Metadata

Metadata

Assignees

Labels

area/agentIssues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality

Type

No type
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