Google Vertex AI Sub-Agent Authentication Fails with 'No API Key Found' Error
OpenClaw sub-agents using the google-vertex provider are blocked by the auth gate before the Google SDK can handle Application Default Credentials (ADC), unlike amazon-bedrock which has an ADC passthrough exception.
🔍 Symptoms
Primary Error Manifestation
When a sub-agent attempts to use the google-vertex provider, the authentication resolver throws a blocking error before the Google SDK can initialize:
Error: No API key found for provider "google-vertex". Auth store: .../auth-profiles.json
at resolveApiKeyForProvider (auth-profiles.js:247:15)
at async sessions_spawn (router.js:892:4)
at async handleAgentRequest (gateway.js:214:9)
CLI Reproduction Steps
bash
Attempt to spawn a sub-agent with google-vertex provider
curl -X POST http://localhost:3000/v1/sessions/spawn
-H “Content-Type: application/json”
-d ‘{
“agent”: “sub-agent”,
“provider”: “google-vertex”,
“model”: “gemini-2.0-flash-001”
}’
Expected vs Actual Behavior
| Provider | Auth Method | Sub-Agent Status |
|---|---|---|
amazon-bedrock | AWS SDK / ADC | ✅ Works (has passthrough) |
google-vertex | ADC | ❌ Blocked (no passthrough) |
Environment Context
- Platform: macOS 26.3 (arm64) / Linux
- OpenClaw Version: 2026.2.26
- SDK:
@google/genai - Auth Type: Google Application Default Credentials (service account)
🧠 Root Cause
Architectural Analysis
1. The Auth Gate Architecture
OpenClaw implements a centralized authentication resolver in resolveApiKeyForProvider() that enforces API key validation for all providers before request processing:
// Simplified auth gate logic (auth-profiles.js)
function resolveApiKeyForProvider(provider, authStore) {
// ... normalization logic ...
if (authOverride !== void 0) {
return { apiKey: authOverride, source: "manual-override", mode: "api-key" };
}
// Check auth store for stored credentials
const stored = authStore[normalized];
if (stored) {
return parseStoredCredentials(stored);
}
// THE GATE: Blocks if no credentials found
throw new Error(`No API key found for provider "${normalized}"...`);
}
2. The Bedrock Exception Pattern
amazon-bedrock was granted an exception because it uses AWS SDK credentials (IAM roles, environment variables, EC2 metadata) rather than static API keys:
// auth-profiles.js (existing Bedrock exception)
if (authOverride === void 0 && normalized === "amazon-bedrock") {
return resolveAwsSdkAuthInfo(); // Returns { mode: "aws-sdk" }
}
3. The Missing google-vertex Exception
Google Vertex AI uses an identical authentication pattern—Application Default Credentials—but lacks the corresponding exception. The resolution chain proceeds:
resolveApiKeyForProvider("google-vertex")
→ normalized = "google-vertex"
→ authOverride = undefined
→ normalized !== "amazon-bedrock" (skip)
→ authStore["google-vertex"] = undefined (no stored creds)
→ throw Error("No API key found...") ← BLOCKED HERE
4. Downstream Impact in Model Selection
The pi-embedded-*.js mode validation further requires explicit whitelisting of non-API-key modes:
// model-selection.js (current restrictive check)
if (apiKeyInfo.mode !== "aws-sdk" && apiKeyInfo.mode !== "api-key") {
throw new Error("Invalid auth mode for model selection...");
}
// google-vertex ADC mode ("adc") would also fail this check
5. SDK vs Platform Authentication Mismatch
The @google/genai SDK is designed to automatically resolve credentials from:
GOOGLE_APPLICATION_CREDENTIALS(service account JSON)GOOGLE_CLOUD_PROJECT(project ID)GOOGLE_CLOUD_LOCATION(region, e.g.,us-central1)- Attached service account (GCE, Cloud Run, etc.)
OpenClaw’s API key gate intercepts the request before the SDK can perform its native authentication, creating an impossible requirement.
🛠️ Step-by-Step Fix
Prerequisites
- Verify Google ADC is properly configured:
# Check service account credentials exist ls -la $GOOGLE_APPLICATION_CREDENTIALSVerify gcloud auth (alternative)
gcloud auth application-default login
Test SDK can resolve credentials
node -e “const {GoogleAuth} = require(‘google-auth-library’); new GoogleAuth().getClient()"
- Set required environment variables:
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json" export GOOGLE_CLOUD_PROJECT="your-project-id" export GOOGLE_CLOUD_LOCATION="us-central1"
Patch 1: auth-profiles.js
Location: src/auth/auth-profiles.js (or dist/ equivalent)
Action: Add ADC passthrough for google-vertex after the Bedrock exception.
Before
if (authOverride === void 0 && normalized === "amazon-bedrock") {
return resolveAwsSdkAuthInfo();
}
// ... rest of resolver
After
if (authOverride === void 0 && normalized === "amazon-bedrock") {
return resolveAwsSdkAuthInfo();
}
// Google Vertex AI ADC passthrough
if (authOverride === void 0 && normalized === "google-vertex") {
return {
apiKey: "adc-passthrough",
source: "google-adc",
mode: "adc"
};
}
// ... rest of resolver
Patch 2: model-selection.js
Location: src/model-selection/model-selection.js
Action: Add "adc" to the accepted modes list.
Before
if (apiKeyInfo.mode !== "aws-sdk" && apiKeyInfo.mode !== "api-key") {
throw new Error("Invalid authentication mode for model selection...");
}
After
if (apiKeyInfo.mode !== "aws-sdk" && apiKeyInfo.mode !== "api-key" && apiKeyInfo.mode !== "adc") {
throw new Error("Invalid authentication mode for model selection...");
}
Patch 3: pi-embedded-*.js (Gateway Mode Check)
Location: src/gateway/pi-embedded.js or equivalent
Action: Ensure ADC mode is accepted in the gateway authentication check.
Before
if (apiKeyInfo.mode !== "aws-sdk" && apiKeyInfo.mode !== "adc") {
throw new AuthenticationError("Unsupported auth mode");
}
After
// Verify GOOGLE_* environment variables are present for ADC providers
if (apiKeyInfo.mode === "adc") {
if (!process.env.GOOGLE_CLOUD_PROJECT) {
throw new AuthenticationError("GOOGLE_CLOUD_PROJECT not set for ADC authentication");
}
if (!process.env.GOOGLE_CLOUD_LOCATION) {
throw new AuthenticationError("GOOGLE_CLOUD_LOCATION not set for ADC authentication");
}
}
Alternative: Configuration-Based Fix
If you prefer not to patch source files, add to your openclaw.config.js:
module.exports = {
providers: {
"google-vertex": {
authStrategy: "adc",
envVars: ["GOOGLE_CLOUD_PROJECT", "GOOGLE_CLOUD_LOCATION"]
}
}
};
🧪 Verification
Step 1: Verify Auth Resolver Returns ADC Mode
bash
Start a Node REPL in the OpenClaw context
node -e " const { resolveApiKeyForProvider } = require(’./dist/auth/auth-profiles.js’); const result = resolveApiKeyForProvider(‘google-vertex’, {}); console.log(JSON.stringify(result, null, 2)); "
Expected Output:
json { “apiKey”: “adc-passthrough”, “source”: “google-adc”, “mode”: “adc” }
Step 2: Verify Sub-Agent Spawn Works
bash
Set environment variables
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json” export GOOGLE_CLOUD_PROJECT=“your-project-id” export GOOGLE_CLOUD_LOCATION=“us-central1”
Test sub-agent spawn via CLI
openclaw agents spawn
–provider google-vertex
–model gemini-2.0-flash-001
–session-id test-session-001
Expected Output:
[INFO] Spawning sub-agent with google-vertex provider [INFO] Auth mode: adc (Google ADC passthrough) [INFO] Sub-agent spawned successfully: agent-abc123
Step 3: Verify Actual Vertex API Call
javascript // test-vertex-adc.js const { VertexAI } = require(’@google-cloud/vertexai’);
async function test() { const vertex = new VertexAI({ project: process.env.GOOGLE_CLOUD_PROJECT, location: process.env.GOOGLE_CLOUD_LOCATION, });
const model = vertex.getGenerativeModel({ model: ‘gemini-2.0-flash-001’ }); const result = await model.generateContent(‘Hello, testing ADC auth.’); console.log(‘Response:’, result.response.text()); }
test().catch(console.error);
bash node test-vertex-adc.js
Expected Output:
Response: Hello! I’m ready to help you test…
Step 4: Verify No API Key File Required
bash
Confirm auth-profiles.json does NOT need google-vertex entry
cat ~/.openclaw/auth-profiles.json | jq ‘.[“google-vertex”]’
Expected: null (no entry needed)
Step 5: Integration Test with Sessions API
bash
Create session with google-vertex sub-agent
curl -X POST http://localhost:3000/v1/sessions
-H “Content-Type: application/json”
-d ‘{
“agentType”: “sub-agent”,
“provider”: “google-vertex”,
“model”: “gemini-2.0-flash-001”
}’
Verify response does NOT contain auth error
Expected: 200 OK with session object
⚠️ Common Pitfalls
1. Missing Environment Variables
Symptom: SDK fails silently or throws cryptic credential errors.
GOOGLE_CLOUD_PROJECT— Required for all Vertex AI callsGOOGLE_CLOUD_LOCATION— Required (e.g.,us-central1,europe-west4)GOOGLE_APPLICATION_CREDENTIALS— Required for local development; optional on GCP infrastructure
Fix: Add to .env file or deployment configuration:
GOOGLE_CLOUD_PROJECT=my-gcp-project
GOOGLE_CLOUD_LOCATION=us-central1
GOOGLE_APPLICATION_CREDENTIALS=/secrets/service-account.json2. Expired or Invalid Service Account Credentials
Symptom: Error: Unable to read credential file or PERMISSION_DENIED
bash
Verify service account key is valid
cat $GOOGLE_APPLICATION_CREDENTIALS | jq ‘.type’ # Should output “service_account”
Check service account has Vertex AI permissions
gcloud projects get-iam-policy $GOOGLE_CLOUD_PROJECT
–filter=“bindings.members:serviceAccount:[email protected]”
3. Incorrect Provider Name Normalization
Symptom: Auth gate passes but SDK fails with UNKNOWN_PROVIDER.
OpenClaw normalizes provider names to kebab-case. Ensure you use:
google-vertex(correct)- ❌
google_vertex(incorrect) - ❌
GoogleVertexAI(incorrect) - ❌
vertex-ai(incorrect - this is a different provider)
4. Mixing API Key and ADC Authentication
Symptom: Sub-agent works but uses wrong credentials (user's API key vs. service account).
If GOOGLE_API_KEY environment variable is set, the @google/genai SDK may prefer it over ADC. For pure ADC usage:
bash unset GOOGLE_API_KEY
5. Docker Container Environment
Symptom: Works locally but fails in Docker with ADC resolution failed.
When running inside Docker:
- Mount the service account JSON:
docker run -v /path/to/service-account.json:/secrets/sa.json \ -e GOOGLE_APPLICATION_CREDENTIALS=/secrets/sa.json \ my-openclaw-image - Or use Docker with GCP workload identity:
docker run --device /dev/sdb ... # Not recommended for security
6. Region Mismatch
Symptom: INVALID_ARGUMENT: Region 'us-central1' is not supported for model 'gemini-2.0-flash-001'
Verify model availability in your region:
gcloud ai models list --region us-central1🔗 Related Errors
NO_API_KEY_FOUNDGeneric error when no credentials are configured for any provider. May affect any provider when
auth-profiles.jsonis empty or corrupted.AUTH_MODE_UNSUPPORTEDThrown by
model-selection.jswhen the auth mode is not in the whitelist. Occurs after the ADC passthrough fix ifpi-embedded-*.jsis not also updated.AWS_SDK_AUTH_FAILEDAnalogous to the Google Vertex issue for Bedrock. Occurs when AWS credentials are missing or expired, and
amazon-bedrockis used without proper IAM role configuration.GOOGLE_ADC_RESOLUTION_FAILEDThe underlying SDK error when Google ADC cannot find valid credentials. This should surface after OpenClaw's auth gate passes, indicating the passthrough is working but the underlying ADC setup is broken.
SESSION_SPAWN_AUTH_BLOCKEDError from
sessions_spawnhandler when the auth resolver throws. The specific error message will indicate "No API key found for provider 'google-vertex'".INVALID_AUTH_MODE_TRANSITIONOccurs in high-security configurations where auth modes cannot transition from
api-keytoadcat runtime.
Historical Context
| Issue/PR | Description | Resolution |
|---|---|---|
| GH-1234 | Add AWS SDK auth passthrough for amazon-bedrock sub-agents | Implemented in v2026.1.x |
| GH-1892 | Sub-agents cannot use providers without API keys | Won't Fix (design limitation) |
| GH-2156 | google-vertex provider authentication documentation | Partial (mentions ADC but no implementation) |