[GH-ISSUE #443] 1.9.0: hard import of @langchain/anthropic forces unused dependency on OpenAI-only users #260

Closed
opened 2026-06-05 17:21:19 -04:00 by yindo · 4 comments
Owner

Originally created by @anouar-bm on GitHub (Apr 8, 2026).
Original GitHub issue: https://github.com/langchain-ai/deepagentsjs/issues/443

Bug

deepagents@1.9.0 unconditionally imports @langchain/anthropic at the top of dist/index.js:

import { ChatAnthropic } from "@langchain/anthropic";

This means any project that uses deepagents with OpenAI only (ChatOpenAI) must install @langchain/anthropic as a dependency — even though it's never used at runtime.

Steps to reproduce

pnpm add deepagents@1.9.0
# next build or tsc
# → Module not found: Can't resolve '@langchain/anthropic'

Expected behavior

@langchain/anthropic should be a true optional/peer dependency. The import should be lazy (dynamic import() inside a factory or guard) so tree-shaking / bundlers don't force it on users who never pass a ChatAnthropic instance.

Workaround

Install @langchain/anthropic even if unused:

pnpm add @langchain/anthropic

Environment

  • deepagents: 1.9.0
  • bundler: Next.js 16 (Turbopack)
  • LLM used: @langchain/openai / ChatOpenAI
Originally created by @anouar-bm on GitHub (Apr 8, 2026). Original GitHub issue: https://github.com/langchain-ai/deepagentsjs/issues/443 ## Bug `deepagents@1.9.0` unconditionally imports `@langchain/anthropic` at the top of `dist/index.js`: ```js import { ChatAnthropic } from "@langchain/anthropic"; ``` This means any project that uses `deepagents` with **OpenAI only** (`ChatOpenAI`) must install `@langchain/anthropic` as a dependency — even though it's never used at runtime. ## Steps to reproduce ```bash pnpm add deepagents@1.9.0 # next build or tsc # → Module not found: Can't resolve '@langchain/anthropic' ``` ## Expected behavior `@langchain/anthropic` should be a true optional/peer dependency. The import should be lazy (dynamic `import()` inside a factory or guard) so tree-shaking / bundlers don't force it on users who never pass a `ChatAnthropic` instance. ## Workaround Install `@langchain/anthropic` even if unused: ```bash pnpm add @langchain/anthropic ``` ## Environment - deepagents: 1.9.0 - bundler: Next.js 16 (Turbopack) - LLM used: `@langchain/openai` / `ChatOpenAI`
yindo closed this issue 2026-06-05 17:21:19 -04:00
Author
Owner

@anouar-bm commented on GitHub (Apr 8, 2026):

Root cause (after inspecting dist/index.js)

Two issues in the bundled output:

1. Top-level static import (line 2)

import { ChatAnthropic } from "@langchain/anthropic";

This is not lazy — it runs at module load time regardless of what model the caller passes.

2. ChatAnthropic is the hardcoded default model (line 6457)

const { model = new ChatAnthropic("claude-sonnet-4-6"), ... } = params;

So even if a caller always provides their own model (e.g. ChatOpenAI), the default expression references ChatAnthropic, which means the static import must resolve.

3. Prompt caching middleware is Anthropic-gated (lines 6460–6539)

const anthropicModel = isAnthropicModel(model);
const cacheMiddleware = anthropicModel ? [anthropicPromptCachingMiddleware(...)] : [];

This part is fine at runtime (conditional), but the static import on line 2 makes it irrelevant — @langchain/anthropic must be installed unconditionally.

Suggested fix

  1. Change the default model to something model-agnostic, or remove the default entirely (force callers to provide a model).
  2. Lazy-load ChatAnthropic only when needed:
// Instead of top-level import:
const { ChatAnthropic } = await import("@langchain/anthropic");

Or gate it behind the isAnthropicModel check so bundlers can tree-shake it.

<!-- gh-comment-id:4210721810 --> @anouar-bm commented on GitHub (Apr 8, 2026): ## Root cause (after inspecting `dist/index.js`) Two issues in the bundled output: **1. Top-level static import (line 2)** ```js import { ChatAnthropic } from "@langchain/anthropic"; ``` This is not lazy — it runs at module load time regardless of what model the caller passes. **2. `ChatAnthropic` is the hardcoded default model (line 6457)** ```js const { model = new ChatAnthropic("claude-sonnet-4-6"), ... } = params; ``` So even if a caller always provides their own model (e.g. `ChatOpenAI`), the default expression references `ChatAnthropic`, which means the static import must resolve. **3. Prompt caching middleware is Anthropic-gated (lines 6460–6539)** ```js const anthropicModel = isAnthropicModel(model); const cacheMiddleware = anthropicModel ? [anthropicPromptCachingMiddleware(...)] : []; ``` This part is fine at runtime (conditional), but the static import on line 2 makes it irrelevant — `@langchain/anthropic` must be installed unconditionally. ## Suggested fix 1. Change the default model to something model-agnostic, or remove the default entirely (force callers to provide a model). 2. Lazy-load `ChatAnthropic` only when needed: ```js // Instead of top-level import: const { ChatAnthropic } = await import("@langchain/anthropic"); ``` Or gate it behind the `isAnthropicModel` check so bundlers can tree-shake it.
Author
Owner

@anouar-bm commented on GitHub (Apr 8, 2026):

This appears to be a regression in 1.9.0

The official docs state:

By default, deepagents uses "claude-sonnet-4-5-20250929". You can customize this by passing any LangChain model object.

So the documented default is a model string, not an instantiated ChatAnthropic object.

But in the 1.9.0 dist/index.js (line 6457), the actual default is:

const { model = new ChatAnthropic("claude-sonnet-4-6"), ... } = params;

This looks like a regression — the default was likely changed from a string identifier to new ChatAnthropic(...) somewhere in the 1.8.x → 1.9.0 range, which silently pulled @langchain/anthropic from an optional import to a required one.

The fix should restore the default to a string (as documented), and keep the @langchain/anthropic import lazy/conditional for users who actually pass a ChatAnthropic instance.

<!-- gh-comment-id:4210730285 --> @anouar-bm commented on GitHub (Apr 8, 2026): ## This appears to be a regression in 1.9.0 The official docs state: > By default, deepagents uses `"claude-sonnet-4-5-20250929"`. You can customize this by passing any LangChain model object. So the documented default is a **model string**, not an instantiated `ChatAnthropic` object. But in the 1.9.0 `dist/index.js` (line 6457), the actual default is: ```js const { model = new ChatAnthropic("claude-sonnet-4-6"), ... } = params; ``` This looks like a regression — the default was likely changed from a string identifier to `new ChatAnthropic(...)` somewhere in the 1.8.x → 1.9.0 range, which silently pulled `@langchain/anthropic` from an optional import to a required one. The fix should restore the default to a string (as documented), and keep the `@langchain/anthropic` import lazy/conditional for users who actually pass a `ChatAnthropic` instance.
Author
Owner

@JadenKim-dev commented on GitHub (Apr 10, 2026):

@anouar-bm
Hi, submitted a fix in #451 — removed the static import and changed the default model to a string.
createAgent natively accepts a model name string, so no need to use ChatAnthropic.

<!-- gh-comment-id:4227563799 --> @JadenKim-dev commented on GitHub (Apr 10, 2026): @anouar-bm Hi, submitted a fix in #451 — removed the static import and changed the default model to a string. `createAgent` natively accepts a model name string, so no need to use `ChatAnthropic`.
Author
Owner

@anouar-bm commented on GitHub (Apr 11, 2026):

Thanks

<!-- gh-comment-id:4229086966 --> @anouar-bm commented on GitHub (Apr 11, 2026): Thanks
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langchain-ai/deepagentsjs#260