How OpenClaude Handles Gemini Credential Handling and Thought‑Signature Behavior

OpenClaude resolves Gemini credentials through a unified auth-resolution layer in src/utils/geminiAuth.ts and preserves thought-signatures across the request pipeline via encoding in tool-use IDs and OpenAI-shim compatibility bridging.

OpenClaude is an open-source AI gateway that normalizes multiple provider APIs behind a unified interface. Understanding how it handles Gemini credential handling and thought-signature behavior reveals the architecture for secure authentication and accurate chain-of-thought preservation with Google's Gemini models.

Gemini Credential Handling Architecture

OpenClaude implements a three-tier credential resolution system that supports multiple authentication patterns without hardcoding provider-specific logic into the core application.

Auth-Mode Detection in resolveGeminiCredential

The entry point for all Gemini authentication is resolveGeminiCredential in src/utils/geminiAuth.ts. This function inspects the runtime environment and determines which of three auth modes to activate:

  • API-key mode — activated when GEMINI_API_KEY is present
  • Access-token mode — activated when GEMINI_ACCESS_TOKEN is present [🔗 src/utils/geminiAuth.ts#L76]
  • ADC mode — activated when GEMINI_AUTH_MODE is explicitly set to "adc" [🔗 src/utils/geminiAuth.ts#L80]

The function prioritizes explicit configuration over implicit discovery, ensuring predictable behavior across deployment environments.

Resolution Flow and Fallback Behavior

The credential resolution follows a strict precedence chain in src/utils/geminiAuth.ts:

  1. Check for user-provided resolver in options.resolveGeminiCredential
  2. Fall back to built-in resolver that reads environment variables
  3. For ADC mode, load credentials from the local Google Cloud SDK installation [🔗 src/utils/geminiAuth.ts#L212-L226]

This design allows test injection and custom credential sources without modifying core logic.

Provider Profile Integration

The buildGeminiProfileEnv function in src/utils/providerProfile.ts synthesizes resolved credentials into the startup environment for Gemini-enabled provider profiles:

// Build a startup environment for a Gemini-enabled profile
import { buildGeminiProfileEnv } from './utils/providerProfile.js';

const env = buildGeminiProfileEnv({
  persistedGeminiModel: 'gemini-1.5-flash',
  persistedGeminiBaseUrl: undefined,
  persistedGeminiAuthMode: 'access-token',
  readGeminiAccessToken: () => process.env.GEMINI_ACCESS_TOKEN,
});

console.log(env.GEMINI_ACCESS_TOKEN); // token used by the Vertex client

The function maps internal state to environment variables:

  • GEMINI_AUTH_MODE stores the chosen auth mode [🔗 src/utils/providerProfile.ts#L1778-L1788]
  • GEMINI_API_KEY receives the key when mode is "api-key" [🔗 src/utils/providerProfile.ts#L1784]
  • GEMINI_ACCESS_TOKEN receives the token when mode is "access-token" [🔗 src/utils/providerProfile.ts#L1788]

Pre-Flight Validation

Before any request executes, providerValidation.ts verifies that at least one Gemini credential source is available:

// Resolve Gemini credentials from the current process environment
import { resolveGeminiCredential } from './utils/geminiAuth.js';

const cred = await resolveGeminiCredential(process.env);
console.log(cred);
// { apiKey?: string, accessToken?: string, authMode: 'api-key'|'access-token'|'adc' }

Validation fails with a descriptive error if no credential source is detected [🔗 src/utils/providerValidation.ts#L405-L437].

Thought-Signature Handling Pipeline

Gemini models with "thinking" capability attach a thought-signature—a token identifying the model's internal chain-of-thought—to function-call parts. OpenClaude preserves this signature through encoding, streaming conversion, and OpenAI-shim bridging.

Vertex Client Signature Encoding

In src/services/api/geminiVertexClient.ts, the thought-signature is attached to functionCall payloads during thinking turns. Two helper functions manage the signature lifecycle:

  • encodeToolUseId — appends the signature to the internal tool-use ID
  • decodeToolUseId — extracts the signature for later processing [🔗 src/services/api/geminiVertexClient.ts#L509-L515]

This encoding ensures the signature survives round-trips through tool execution history.

Streaming Token Accounting

The geminiStreamConversion.ts module handles streaming responses and extracts thoughtsTokenCount from response metadata:

// Sending a Gemini request that includes a thought-signature
import { geminiVertexClient } from './services/api/geminiVertexClient.js';

const response = await geminiVertexClient.chat({
  model: 'gemini-1.5-pro',
  messages: [{ role: 'user', content: 'Explain recursion' }],
  // The client will automatically attach the stored thoughtSignature, if any
});

console.log(response.thoughtSignature); // e.g. "SIG_ABC_123"

The extracted count forwards to the OpenAI-shim layer for accurate billing and rate-limit tracking [🔗 src/services/api/geminiStreamConversion.ts#L186-L190].

OpenAI-Shim Compatibility Bridging

The providerCompatibility.ts module in the OpenAI-shim layer merges Gemini-specific fields into the normalized response format. The thought_signature from extra_content is preserved unchanged for downstream tooling [🔗 src/services/api/openaiShim/providerCompatibility.ts#L73-L88].

This bridging guarantees that:

  • Tool-use handlers receive the original signature
  • Response formats remain consistent across providers
  • Billing systems account for thinking tokens correctly

Test Coverage for Signature Integrity

The test suite verifies signature preservation across all execution paths:

  • Round-trip integrity — geminiVertexClient.test.ts confirms signatures survive history traversal [🔗 src/services/api/geminiVertexClient.test.ts#L387-L456]
  • Conversion layer preservation — providerCompatibility.test.ts validates OpenAI-shim output [🔗 src/services/api/openaiShim/providerCompatibility.test.ts#L395-L409]

Key Implementation Files

File Responsibility
src/utils/geminiAuth.ts Core resolver for GEMINI_API_KEY, GEMINI_ACCESS_TOKEN, and ADC credentials
src/utils/providerProfile.ts Runtime environment construction for Gemini profiles
src/utils/providerValidation.ts Pre-flight credential validation
src/services/api/geminiVertexClient.ts HTTP client with thought-signature encoding/decoding
src/services/api/geminiStreamConversion.ts Streaming response handling with thoughtsTokenCount extraction
src/services/api/openaiShim/providerCompatibility.ts Bridge for thought_signature in OpenAI-shim format
src/services/api/geminiVertexClient.test.ts Round-trip signature tests
src/services/api/openaiShim/providerCompatibility.test.ts Conversion layer signature tests

Summary

  • Three auth modes — API-key, access-token, and ADC — resolved through resolveGeminiCredential with explicit precedence
  • Environment synthesis — buildGeminiProfileEnv maps credentials to standard environment variables for runtime consumption
  • Pre-flight validation — providerValidation.ts guarantees credential presence before request execution
  • Signature encoding — tool-use ID manipulation preserves thought-signatures through tool execution cycles
  • Streaming accuracy — thoughtsTokenCount extraction enables correct token accounting for thinking models
  • Cross-provider compatibility — OpenAI-shim bridging maintains signature integrity for downstream consumers

Frequently Asked Questions

How does OpenClaude choose between API-key and access-token authentication for Gemini?

resolveGeminiCredential checks environment variables in priority order: explicit GEMINI_AUTH_MODE overrides detection, otherwise presence of GEMINI_API_KEY selects API-key mode and GEMINI_ACCESS_TOKEN selects access-token mode. ADC mode requires explicit GEMINI_AUTH_MODE=adc configuration.

What happens if no Gemini credentials are configured?

providerValidation.ts throws a descriptive validation error before any network request occurs, preventing runtime failures and providing clear guidance on required environment variables.

Why does OpenClaude encode the thought-signature into the tool-use ID?

The encoding ensures the signature survives round-trips through tool execution history without requiring schema changes to the underlying message format. decodeToolUseId recovers the signature when processing responses.

Does thought-signature handling affect streaming performance?

No. The geminiStreamConversion.ts layer extracts thoughtsTokenCount incrementally during streaming, with minimal overhead. The signature extraction occurs once per function-call part, not per token.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →