Skip to content

feat: @langchain/google#10000

Merged
Hunter Lovell (hntrl) merged 19 commits intomainfrom
hunter/google
Feb 12, 2026
Merged

feat: @langchain/google#10000
Hunter Lovell (hntrl) merged 19 commits intomainfrom
hunter/google

Conversation

@hntrl
Copy link
Copy Markdown
Member

@hntrl Hunter Lovell (hntrl) commented Feb 11, 2026

Summary

Add new @langchain/google package -- a unified Google/Gemini integration that will replace @langchain/google-genai, @langchain/google-common, and the Vertex AI family of packages.

Huge huge huge shoutout to Allen Firstenberg (@afirstenberg) for driving a lot of this feature work

Why a new package?

The existing Google integration stack has accumulated significant technical debt:

  • @langchain/google-genai depends on a long-deprecated SDK from Google (@google/generative-ai). That SDK has been superseded by @google/genai, but migrating to it would be a breaking change with limited upside -- we'd still be coupling to Google's SDK release cycle and its opinionated abstractions.
  • @langchain/google-common / Vertex AI packages had to adopt an awkward multi-package split (google-common, google-gauth, google-webauth, google-vertexai, google-vertexai-web) to accommodate web and edge environments. This fragmentation makes it confusing for users to know which package to install, duplicates logic across packages, and creates a maintenance burden.
  • Hand-coded types in google-common drifted from the actual Gemini API surface over time, leading to broken fields, missing properties, and constant churn to keep them in sync with Google's rapid iteration.

Usage

The package exposes two entrypoints. The constructor takes the model name as the first positional argument, with an optional params object:

@langchain/google -- for web, edge, and serverless environments (Cloudflare Workers, Vercel Edge, Deno, browsers). Uses the Web Fetch API and authenticates via API key only.

import { ChatGoogle } from "@langchain/google";

const model = new ChatGoogle("gemini-2.5-flash", {
  apiKey: "...", // or set GOOGLE_API_KEY env var
});

@langchain/google/node -- for Node.js environments. Extends the base entrypoint with google-auth-library support, enabling Vertex AI via Application Default Credentials (ADC), service account JSON, and other Node-native auth flows.

import { ChatGoogle } from "@langchain/google/node";

// Google AI with API key (reads GOOGLE_API_KEY env var if not provided)
const aiStudio = new ChatGoogle("gemini-2.5-flash");

// Vertex AI with ADC (auto-detected)
const vertex = new ChatGoogle("gemini-2.5-flash", {
  vertexai: true,
  project: "my-gcp-project",
  location: "us-central1",
});

Both entrypoints export the same ChatGoogle class name, so switching between them is just an import path change.

Versioning and stability

This package is being published at 0.1.0 to signal that it is an early release. While we have confidence in the core functionality (chat, streaming, tool calling, reasoning, multimodal), the API surface may evolve as we gather feedback and close the remaining feature gaps relative to the existing packages. We intend to promote to 1.0 once we've validated the API through user feedback and reached feature parity with the existing packages.

Support policy for existing packages

The existing @langchain/google-genai, @langchain/google-vertexai, and related packages will continue to receive maintenance updates (bug fixes, security patches) for the foreseeable future. We are not deprecating them with this release. Once @langchain/google reaches feature parity, we will publish a migration guide and announce a deprecation timeline with adequate notice.


Changes

New package: libs/providers/langchain-google/

Area Files Description
Chat model base.ts, node.ts, index.ts, types.ts ChatGoogle extending BaseChatModel with tool calling, streaming, structured output, and multimodal support
API types api-types.ts, typegen.jsonc Auto-generated Gemini namespace from the OpenAPI spec, plus module augmentations for utility types and spec gaps
Converters converters/messages.ts, converters/params.ts, converters/tools.ts Bidirectional conversion between LangChain messages/tools and Gemini wire format
Clients clients/index.ts, clients/node.ts HTTP client with platform-specific auth (Google AI API key vs Vertex AI OAuth/ADC)
Utilities utils/errors.ts, utils/gcp-auth.ts, utils/handler.ts, utils/misc.ts, utils/stream.ts Error handling, GCP auth helpers, SSE stream parsing
Tests tests/index.test.ts, tests/index.int.test.ts 40 unit tests (reasoning config across model families), integration tests

@langchain/core changes

  • Added ChatGoogleTranslator block translator (block_translators/google.ts) and registered it under the "google" provider key.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Feb 11, 2026

🦋 Changeset detected

Latest commit: 77f1689

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 14 packages
Name Type
@langchain/google Minor
@langchain/core Patch
@langchain/community Patch
langchain Patch
@langchain/anthropic Patch
@langchain/google-cloud-sql-pg Patch
@langchain/google-common Patch
@langchain/google-genai Patch
@langchain/google-webauth Patch
@langchain/model-profiles Patch
@langchain/standard-tests Patch
@langchain/google-gauth Patch
@langchain/google-vertexai-web Patch
@langchain/google-vertexai Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

christian-bromann

This comment was marked as duplicate.

@github-actions github-actions bot added the ready label Feb 11, 2026
christian-bromann

This comment was marked as duplicate.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the contribution! This is an excellent and comprehensive implementation of a unified Google/Gemini integration. The code is well-structured with proper abstractions, thorough error handling, and extensive documentation. The approach of consolidating the fragmented package ecosystem is very valuable. A few edge case suggestions and improvements below.

}
return fetch(request);
}
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The authentication priority logic here could cause issues. When both apiKey and credentials are provided, the function only checks this.params.apiKey but should also check the resolved this.apiKey field:

Suggested change
}
fetch(request: Request): Promise<Response> {
if (this.apiKey) {
request.headers.set(GOOGLE_API_KEY_HEADER, this.apiKey);
} else if (this.credentials) {
request.headers.set(
GCP_API_KEY_HEADER,
`Bearer ${getGCPCredentialsAccessToken(this.credentials)}`
);
}
return fetch(request);
}

This ensures consistent behavior with the hasApiKey() method.

Comment on lines +17 to +24
isInstance(obj: unknown): obj is this {
return (
typeof obj === "object" &&
obj !== null &&
symbol in obj &&
obj[symbol as keyof typeof obj] === true
);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type guard implementation could be more robust. Consider strengthening the check:

Suggested change
isInstance(obj: unknown): obj is this {
return (
typeof obj === "object" &&
obj !== null &&
symbol in obj &&
obj[symbol as keyof typeof obj] === true
);
}
isInstance(obj: unknown): obj is this {
return (
typeof obj === "object" &&
obj !== null &&
symbol in obj &&
obj[symbol as keyof typeof obj] === true &&
obj instanceof Error
);
}

This ensures the object is actually an Error instance, not just any object with the symbol property.

statusText: response.statusText,
});

if (!response.ok) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The streaming response handling could benefit from better error recovery. When parsing chunks fails, the current implementation might not provide enough context:

Suggested change
if (!response.ok) {
} catch (parseError) {
// If parsing fails, still yield a chunk with error context
const errorMessage = parseError instanceof Error ? parseError.message : 'Unknown parsing error';
yield new ChatGenerationChunk({
message: new AIMessageChunk({
content: `[Parse Error: ${errorMessage}]`,
additional_kwargs: { parseError: true }
}),
text: `[Parse Error: ${errorMessage}]`,
});
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmm if we do this stream consumers cant catch errors

Object.hasOwn(config, "multiSpeakerVoiceConfig"))
);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The speech configuration conversion logic should validate the voice names against known prebuilt voices to catch configuration errors early:

Suggested change
// If this is already a SpeechConfig, validate it before returning
if (isSpeechConfig(config)) {
// Add validation for voice names if needed
return config;
}

Consider adding a list of valid prebuilt voice names for validation.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can treat this like a model string from google -- we can't know these without an extra network request locally


cache.set(cacheKey, { created: now, promise });
return await promise.then((data) => data.token);
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The token caching mechanism could lead to race conditions when multiple requests are made simultaneously. Consider using a more robust caching strategy or adding proper locking mechanisms to prevent duplicate token requests.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats fine

Comment on lines +48 to +53
return {
type: "tool_call",
id: message.id,
name: block.functionCall.name,
args: block.functionCall.args,
};
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tool_call conversion assumes message.id is available, but this might not always be the case. Add a fallback:

Suggested change
return {
type: "tool_call",
id: message.id,
name: block.functionCall.name,
args: block.functionCall.args,
};
return {
type: "tool_call",
id: message.id || `tool_call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
name: block.functionCall.name,
args: block.functionCall.args,
};

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we shouldn't do this

@hntrl Hunter Lovell (hntrl) merged commit 71d08c0 into main Feb 12, 2026
36 of 38 checks passed
@hntrl Hunter Lovell (hntrl) deleted the hunter/google branch February 12, 2026 01:29
Mia (miadisabelle) pushed a commit to avadisabelle/ava-langchainjs that referenced this pull request Feb 18, 2026
Co-authored-by: afirstenberg <github@addventure.com>
Nick Winder (nickwinder) pushed a commit to nickwinder/langchainjs that referenced this pull request Mar 24, 2026
Co-authored-by: afirstenberg <github@addventure.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants