Google's Gemma 4 family just dropped — and it's a big deal. Open weights, Apache 2.0 license, multimodal, reasoning-capable, and free to use via the Gemini API. But if you're running OpenClaw as your AI assistant gateway, you'll hit a wall: OpenClaw doesn't have Gemma 4 in its built-in model catalog yet.
Here's how I fixed it in under 5 minutes — for both the 31B Dense and the 26B MoE (A4B) variants.
The Problem
After setting google/gemma-4-31b-it as my default model in OpenClaw, running openclaw models list showed:
Model Input Ctx Auth Tags
google/gemma-4-31b-it - - - default,configured,missing
That missing tag means OpenClaw has the model name in config but no metadata — no input types, no context window size, no API protocol. It doesn't know how to talk to it.
Meanwhile, the raw API works fine:
#!/bin/bash
MODEL_ID="gemma-4-31b-it"
curl -X POST \
-H "Content-Type: application/json" \
"https://generativelanguage.googleapis.com/v1beta/models/${MODEL_ID}:streamGenerateContent?key=${GEMINI_API_KEY}" \
-d '{
"contents": [{
"role": "user",
"parts": [{"text": "Hello, what model are you?"}]
}],
"generationConfig": {
"thinkingConfig": { "thinkingLevel": "HIGH" }
},
"tools": [{ "googleSearch": {} }]
}'
Works perfectly. The problem is purely on OpenClaw's side.
The Fix: Register Custom Model Metadata
OpenClaw's config schema supports a top-level models block where you can inject model definitions that the built-in catalog doesn't have. You need to tell OpenClaw the API protocol, capabilities, and context window for each model.
Step 1: Edit your OpenClaw config
Open ~/.openclaw/openclaw.json and add a models block at the top level:
{
"models": {
"mode": "merge",
"providers": {
"google": {
"baseUrl": "https://generativelanguage.googleapis.com/v1beta",
"models": [
{
"id": "gemma-4-31b-it",
"name": "Gemma 4 31B IT",
"api": "google-generative-ai",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 262144,
"maxTokens": 131072
},
{
"id": "gemma-4-26b-a4b-it",
"name": "Gemma 4 26B A4B IT (MoE)",
"api": "google-generative-ai",
"reasoning": true,
"input": ["text", "image"],
"contextWindow": 262144,
"maxTokens": 262144
}
]
}
}
}
}
What each field does
| Field | Value | Why |
|---|---|---|
mode |
"merge" |
Adds to the existing catalog instead of replacing it |
baseUrl |
Google's v1beta endpoint | Required by schema, even for the built-in Google provider |
api |
"google-generative-ai" |
Tells OpenClaw to use Google's native API protocol (not OpenAI-compatible) |
reasoning |
true |
Both models support configurable thinking modes |
input |
["text", "image"] |
Multimodal: text + image (variable aspect ratio & resolution) |
contextWindow |
262144 |
262K context window (256K usable + overhead) |
maxTokens |
131072 / 262144
|
Max output tokens (31B: 131K, 26B MoE: 262K) |
Step 2: Set up Google API auth
Make sure you have a Google auth profile in OpenClaw. If you don't:
openclaw models auth login
# Select "google" provider, "api_key" mode
# Paste your Gemini API key
Or set it via environment variable:
export GEMINI_API_KEY="your-key-here"
Step 3: Validate, restart, verify
# Validate config
openclaw config validate
# Restart the gateway
openclaw gateway restart
# Check models
openclaw models list
You should now see:
Model Input Ctx Auth Tags
google/gemma-4-31b-it text+image 256k yes default,configured
google/gemma-4-26b-a4b-it text+image 256k yes configured
No more missing tag!
Step 4: Set your default and test
# Set default model
openclaw models set google/gemma-4-31b-it
# Test it
openclaw agent -m "Hello! What model are you?" --local --session-id test
Response:
"I am Gemma 4, a large language model developed by Google DeepMind."
Auto-Patch Script: One Command to Fix Everything
Don't want to edit JSON by hand? Save this script and run it — it patches your OpenClaw config automatically:
#!/bin/bash
# openclaw-gemma4-patch.sh
# Auto-patches OpenClaw config to add Gemma 4 models (31B Dense + 26B MoE)
# Usage: chmod +x openclaw-gemma4-patch.sh && ./openclaw-gemma4-patch.sh
set -euo pipefail
CONFIG="${OPENCLAW_CONFIG_PATH:-$HOME/.openclaw/openclaw.json}"
BACKUP="${CONFIG}.bak.$(date +%s)"
# --- Preflight checks ---
if ! command -v openclaw &>/dev/null; then
echo "Error: openclaw not found in PATH" >&2
exit 1
fi
if ! command -v python3 &>/dev/null; then
echo "Error: python3 required for JSON patching" >&2
exit 1
fi
if [ ! -f "$CONFIG" ]; then
echo "Error: OpenClaw config not found at $CONFIG" >&2
echo "Run 'openclaw configure' first or set OPENCLAW_CONFIG_PATH" >&2
exit 1
fi
echo "Backing up config to $BACKUP"
cp "$CONFIG" "$BACKUP"
# --- Patch the config ---
python3 << 'PYEOF'
import json, sys, os
config_path = os.environ.get("OPENCLAW_CONFIG_PATH",
os.path.expanduser("~/.openclaw/openclaw.json"))
with open(config_path, "r") as f:
config = json.load(f)
gemma4_models = [
{
"id": "gemma-4-31b-it",
"name": "Gemma 4 31B IT",
"api": "google-generative-ai",
"reasoning": True,
"input": ["text", "image"],
"contextWindow": 262144,
"maxTokens": 131072
},
{
"id": "gemma-4-26b-a4b-it",
"name": "Gemma 4 26B A4B IT (MoE)",
"api": "google-generative-ai",
"reasoning": True,
"input": ["text", "image"],
"contextWindow": 262144,
"maxTokens": 262144
}
]
if "models" not in config:
config["models"] = {"mode": "merge", "providers": {}}
if "providers" not in config["models"]:
config["models"]["providers"] = {}
if "google" not in config["models"]["providers"]:
config["models"]["providers"]["google"] = {
"baseUrl": "https://generativelanguage.googleapis.com/v1beta",
"models": []
}
google = config["models"]["providers"]["google"]
if "baseUrl" not in google:
google["baseUrl"] = "https://generativelanguage.googleapis.com/v1beta"
if "models" not in google:
google["models"] = []
existing_ids = {m["id"] for m in google["models"]}
added = []
for model in gemma4_models:
if model["id"] not in existing_ids:
google["models"].append(model)
added.append(model["id"])
if "agents" in config and "defaults" in config["agents"]:
defaults = config["agents"]["defaults"]
if "models" not in defaults:
defaults["models"] = {}
for model in gemma4_models:
key = f"google/{model['id']}"
if key not in defaults["models"]:
defaults["models"][key] = {}
ordered = {"models": config.pop("models")}
ordered.update(config)
with open(config_path, "w") as f:
json.dump(ordered, f, indent=2)
f.write("\n")
if added:
print(f"Added models: {', '.join(added)}")
else:
print("Models already present, no changes needed")
PYEOF
# --- Validate ---
echo ""
echo "Validating config..."
if ! openclaw config validate; then
echo "Validation failed! Restoring backup..."
cp "$BACKUP" "$CONFIG"
echo "Restored. Please check your config manually."
exit 1
fi
# --- Restart gateway ---
echo ""
echo "Restarting gateway..."
openclaw gateway restart
# --- Verify ---
echo ""
echo "Verifying models..."
openclaw models list
echo ""
echo "Done! Gemma 4 models are ready."
echo "Set your default with: openclaw models set google/gemma-4-31b-it"
echo "Test with: openclaw agent -m 'Hello!' --local --session-id test-gemma"
Save it and run:
chmod +x openclaw-gemma4-patch.sh
./openclaw-gemma4-patch.sh
The script is idempotent — running it twice won't duplicate models. It backs up your config before patching and auto-rolls back if validation fails.
Testing Both Models
Once patched, verify both variants respond:
# Test the 31B Dense model
openclaw models set google/gemma-4-31b-it
openclaw agent -m "What model are you? One sentence." \
--local --session-id test-31b --json | python3 -c "
import json,sys
r = json.load(sys.stdin)
print(f'Model: {r[\"meta\"][\"agentMeta\"][\"model\"]}')
print(f'Response: {r[\"payloads\"][0][\"text\"]}')
print(f'Time: {r[\"meta\"][\"durationMs\"]}ms')
"
# Test the 26B MoE model
openclaw models set google/gemma-4-26b-a4b-it
openclaw agent -m "What model are you? One sentence." \
--local --session-id test-26b --json | python3 -c "
import json,sys
r = json.load(sys.stdin)
print(f'Model: {r[\"meta\"][\"agentMeta\"][\"model\"]}')
print(f'Response: {r[\"payloads\"][0][\"text\"]}')
print(f'Time: {r[\"meta\"][\"durationMs\"]}ms')
"
# Switch back to your preferred default
openclaw models set google/gemma-4-31b-it
Test via Raw curl (No OpenClaw)
Verify your API key works before patching:
#!/bin/bash
# test-gemma4-api.sh — Quick API smoke test for both Gemma 4 models
set -e -E
if [ -z "$GEMINI_API_KEY" ]; then
echo "Error: Set GEMINI_API_KEY first" >&2
exit 1
fi
for MODEL in gemma-4-31b-it gemma-4-26b-a4b-it; do
echo "--- Testing $MODEL ---"
curl -s -X POST \
-H "Content-Type: application/json" \
"https://generativelanguage.googleapis.com/v1beta/models/${MODEL}:generateContent?key=${GEMINI_API_KEY}" \
-d '{
"contents": [{
"role": "user",
"parts": [{"text": "What model are you? Reply in one sentence."}]
}],
"generationConfig": {
"thinkingConfig": { "thinkingLevel": "HIGH" }
}
}' | python3 -c "
import json,sys
r = json.load(sys.stdin)
for part in r.get('candidates',[{}])[0].get('content',{}).get('parts',[]):
if 'text' in part:
print(part['text'])
break
" 2>/dev/null || echo "FAILED"
echo ""
done
How I Diagnosed This
-
openclaw models list— showed model asmissing(no metadata) -
openclaw config schema— extracted the full JSON schema to find the exact format for custom model definitions -
Found the supported
apiprotocols:google-generative-ai,openai-completions,anthropic-messages,ollama, and others -
Added the config block, validated with
openclaw config validate - Restarted gateway and confirmed with a test message
About Gemma 4
Gemma 4 is Google's latest open model family with three architectures:
| Model | Type | Parameters | Active Params | Context | Memory (BF16) |
|---|---|---|---|---|---|
| Gemma 4 E2B | Efficient | 2B effective | — | 128K | 9.6 GB |
| Gemma 4 E4B | Efficient | 4B effective | — | 128K | 15 GB |
| Gemma 4 31B | Dense | 31B | 31B | 256K | 58.3 GB |
| Gemma 4 26B A4B | MoE | 26B | 4B | 256K | 48 GB |
Key capabilities:
- Reasoning with configurable thinking modes (OFF/LOW/MEDIUM/HIGH)
- Multimodal: text, image (all models), video & audio (E2B/E4B)
- Function calling for agentic workflows
- Native system prompt support
- Apache 2.0 license — fully open for commercial use
Free Tier Rate Limits (Gemini API)
| Model | RPM (Requests/min) | TPM (Tokens/min) |
|---|---|---|
| Gemma 4 26B | 3 / 15 | 77 / Unlimited |
| Gemma 4 31B | 3 / 15 | 15.04K / Unlimited |
The 31B gets significantly more token throughput on free tier. Both work for experimentation and personal assistant use cases.
The General Pattern: Adding Any Unsupported Model
This same approach works for any model from any provider that OpenClaw doesn't ship in its catalog:
- Verify the API key works outside OpenClaw (use curl)
-
Find the right
apiprotocol fromopenclaw config schema— options include:google-generative-aiopenai-completionsopenai-responsesanthropic-messagesollamabedrock-converse-streamgithub-copilotazure-openai-responses
-
Add the
models.providers.<name>block withid,api,contextWindow,maxTokens -
Validate and restart:
openclaw config validate && openclaw gateway restart
That's it. Sixty seconds from "unknown model" to a working agent.
Links:
Top comments (0)