Bug: Gemini Context Caching Conflicts with systemInstruction and tools
Problem
When cacheRetention: "long" is configured for a Gemini model with tools, the OpenClaw gateway sends cachedContent, systemInstruction, AND tools/toolConfig in the same request. The Google Gemini API rejects this combination with error 400:
Google Generative AI API error (400): CachedContent can not be used with GenerateContent request setting system_instruction, tools or tool_config.
Root Cause
The code in transport-stream-DyvRcab3.js (function buildGoogleGenerativeAiParams) sends all fields unconditionally:
if (typeof options?.cachedContent === "string" && options.cachedContent.trim())
params.cachedContent = options.cachedContent.trim();
if (context.systemPrompt)
params.systemInstruction = { parts: [{ text: sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt)) }] };
if (context.tools?.length) {
params.tools = convertGoogleTools(context.tools);
const toolChoice = mapToolChoice(options?.toolChoice);
if (toolChoice) params.toolConfig = { functionCallingConfig: toolChoice };
}
According to Google's API documentation, when cachedContent is used, the systemInstruction, tools, and toolConfig must NOT be sent separately — they should already be embedded in the cached content.
Previous Work
PR #71441 implemented the correct fix:
This means the fix exists but was never applied to the codebase.
Impact
Workaround: Remove cacheRetention from all Gemini model configs:
{
"google/gemini-3.5-flash": {} // no cacheRetention
}
Cost Impact: Without context caching, users pay 100% of input token costs instead of ~25% (cache read rate). For agents with large system prompts (~35KB), this represents significant cost overhead.
Reproduction
- Configure a Gemini model with
cacheRetention: "long" and tools
- Create an agent with a large system prompt (SOUL.md, TOOLS.md, etc.)
- Send a message to the agent
- Observe error 400 from Google API
Environment
- OpenClaw version: 2026.5.19 (a185ca2)
- Model: google/gemini-3.5-flash (also affects gemini-3.1-flash-lite, gemini-2.5-flash-lite, gemini-2.0-flash)
- Config:
cacheRetention: "long" + agent with tools
Related
Suggested Fix
Re-open and merge PR #71441, or apply equivalent fix:
const usesCachedContent = typeof options?.cachedContent === "string" && options.cachedContent.trim();
if (usesCachedContent) params.cachedContent = options.cachedContent.trim();
if (!usesCachedContent && context.systemPrompt)
params.systemInstruction = { parts: [{ text: sanitizeTransportPayloadText(stripSystemPromptCacheBoundary(context.systemPrompt)) }] };
if (!usesCachedContent && context.tools?.length) {
params.tools = convertGoogleTools(context.tools);
const toolChoice = mapToolChoice(options?.toolChoice);
if (toolChoice) params.toolConfig = { functionCallingConfig: toolChoice };
}
Bug: Gemini Context Caching Conflicts with systemInstruction and tools
Problem
When
cacheRetention: "long"is configured for a Gemini model with tools, the OpenClaw gateway sendscachedContent,systemInstruction, ANDtools/toolConfigin the same request. The Google Gemini API rejects this combination with error 400:Root Cause
The code in
transport-stream-DyvRcab3.js(functionbuildGoogleGenerativeAiParams) sends all fields unconditionally:According to Google's API documentation, when
cachedContentis used, thesystemInstruction,tools, andtoolConfigmust NOT be sent separately — they should already be embedded in the cached content.Previous Work
PR #71441 implemented the correct fix:
usesCachedContentguard before settingsystemInstructionandtools/toolConfigThis means the fix exists but was never applied to the codebase.
Impact
Workaround: Remove
cacheRetentionfrom all Gemini model configs:Cost Impact: Without context caching, users pay 100% of input token costs instead of ~25% (cache read rate). For agents with large system prompts (~35KB), this represents significant cost overhead.
Reproduction
cacheRetention: "long"and toolsEnvironment
cacheRetention: "long"+ agent with toolsRelated
Suggested Fix
Re-open and merge PR #71441, or apply equivalent fix: