@b4run/langchain

Use this whenCopy link to section: Use this when

Use this package when framework code must materialize B4.run agent descriptors, adapt LangChain runnables, convert B4.run tools, configure provider loading, or compose the package's retry, summarization, offloading, and subagent helpers. Most application code declares agents through agent() and lets the B4.run runtime call this layer.

Install and importCopy link to section: Install and import

bash
npm install @b4run/langchain @langchain/core @langchain/langgraph-checkpoint
ts
import {
  chainAdapter,
  openaiEmbedder,
  resolveProvider,
  withRetry,
} from "@b4run/langchain"

Install the optional LangChain provider package selected by your agents. @langchain/openai is included. Anthropic, Google, Mistral, Groq, Ollama, xAI, and OpenRouter integrations are optional peer dependencies.

Compatibility and audienceCopy link to section: Compatibility and audience

SurfaceRuntimePurityAudienceStability
@b4run/langchainedge-safenot-claimedintegrationsupported
@b4run/langchain/package.jsonpackage metadatan/atoolingsupported

The runtime root is edge-safe for B4.run's emitted Hono/workerd target. The evidence is the emitted Hono app round trip on Node and a gated real-workerd lane without nodejs_compat. Guards bundle the exact surface with the model layer externalized. The root is not dependency-free and makes no general browser promise: provider integrations, application tools, stores, and dynamically selected imports keep their own requirements. ./package.json is data for tooling, not TypeScript inventory or runtime code.

Public exportsCopy link to section: Public exports

@b4run/langchainCopy link to section: @b4run/langchain

ExportResponsibility
AgentStreamChunkDescribe streamed tokens, tool activity, interrupts, completion, and extensions.
AgentTurnResultDescribe a settled agent turn's output and whether it parked on an interrupt.
B4ToolDefinitionDescribe a B4.run tool accepted by agent materialization.
__resetMaterializedAgentsForTestsReset the process-global materialized-agent cache for tests.
executeAgentConsume an agent stream and return its completed output.
executeAgentTurnExecute one materialized-agent turn and return its structured result.
materializeAgentGraphCompile a B4.run agent descriptor into a LangGraph graph.
streamAgentStream normalized agent chunks.
chainAdapterAdapt a LangChain runnable to B4.run's chain backend contract.
BuiltInModelProviderIdRe-export the SDK-owned built-in provider union.
ModelProviderIdRe-export the SDK-owned provider identifier.
createChatModelLoad and construct a selected provider chat model, optionally bound to a JSON-schema response format.
JsonSchemaResponseFormatDescribe a JSON schema the root model's final message must match.
JSON_SCHEMA_RESPONSE_FORMAT_PROVIDERSList the providers whose schema-constrained output coexists with tool calls.
supportsJsonSchemaResponseFormatReport whether a provider can be bound to a JSON-schema response format.
unsupportedResponseFormatMessageProduce the rejection message for a provider that cannot.
ModalitySupportDescribe which content parts a route's model takes, by modality and source.
DEFAULT_MODALITY_SUPPORTSupply the support assumed for a model with no profile: images inline and by URL.
resolveModalitySupportRead a model's LangChain profile and apply the provider's converter limits.
readModelProfileRead a model's LangChain profile off its provider class without constructing it; undefined when the provider package is not installed.
ConvertedContentDescribe converted message content and the parts dropped from it.
LangChainContentBlockDescribe one LangChain standard content block.
DroppedPartDescribe one dropped part: its index, type, source and reason.
DropReasonName why a part was dropped.
DroppedPartsReportDescribe the parts dropped from one message, with the model and route they were judged against.
toLangChainContentConvert content parts to LangChain content blocks, dropping what the model cannot take.
formatDroppedPartsWarningFormat the server-log warning that announces dropped parts.
pickDroppedPartsReportPick the report fields off a content_parts_dropped or subagent.content_parts_dropped chunk's data.
providerPackagesMap built-in provider IDs to integration packages.
seedModelImporterInstall the process-global fallback provider importer.
inferProviderRe-export SDK provider inference.
resolveProviderResolve an explicit provider or infer one from a model ID.
modelMaxRetriesMap an agent's retry to a chat model's maxRetries (maxAttempts - 1, default 2).
resolveReasoningConfigCheck an agent's reasoning against its resolved provider and map it to the chat model's constructor options, reporting whether reasoning text will stream.
ResolvedReasoningConfigDescribe the resolved reasoning controls: constructor options and the streams flag GET /agui/:routeId advertises.
RetryOptionsConfigure retry attempts, backoff, cap, and cancellation.
isRetryableErrorClassify known transient error messages.
withRetryRetry transient async failures with jittered exponential backoff.
openaiEmbedderConstruct the OpenAI-backed memory embedder.
OffloadStoreOptionsConfigure an offload store and its cleanup limits.
buildOffloadFileNameProduce a sanitized deterministic output filename.
OffloadStorePersist tool output and perform throttled best-effort cleanup.
OffloadToolOutputCtxConfigure one conditional tool-output offload.
offloadToolOutputReplace oversized output with a saved-file preview stub.
buildStubFormat a human-readable offloaded-output stub.
OffloadFnDescribe the tool converter's output-offload callback.
ToolResultModalityDescribe the root model's modality support, used to shape a tool's media result.
B4_CONTENT_PARTS_KEYName the ToolMessage additional_kwargs key that keeps every part a tool returned, for the UI.
convertToolToLangChainConvert a B4.run tool into a LangChain structured tool.
executeWithToolLoopInvoke a chain and execute bounded tool-call rounds.
UnwrappedToolResultDescribe agent-visible content and optional state updates.
unwrapToolResultDecode B4.run's strict { result, state? } tool-return wrapper.
CommandRe-export LangGraph's resume/state-update command.
materializeStateSchemaBuild a LangGraph annotation root from resolved state fields.
ResolvedSubagentGraphDescribe a resolved child route graph.
SubagentResolverResolve an allowed task request to a child graph or rejection.
convertSubagentTaskToLangChainConvert B4.run's task placeholder to a resumable LangChain tool.
RunningSummaryTrack summary text and covered message count.
TokenCounterCount text tokens synchronously or asynchronously.
SummarizeFnDescribe the injected summarization operation.
ResolvedSummarizationConfigHold resolved thresholds and summarization dependencies.
PreModelHookStateDescribe messages and the optional running summary.
PreModelHookResultReturn a model-only message view and updated summary.
buildSummarizationHookBuild the non-destructive pre-model summary hook.
splitForSummarySplit aged messages from recent turns.
defaultSummarizeSummarize messages with the selected chat model.
countMessagesTokensCount tokens across LangChain messages.
defaultTokenCounterCount tokens with the package tokenizer.

__resetMaterializedAgentsForTests is public so the testing harness can reach it. It is for tests only: it mutates process-wide cache state and is not an application lifecycle API. Helpers that implementation modules export but the root barrel omits (such as composePromptMessages, AgentOptions, ResolvedStateField, ExecuteWithToolLoopOptions, BuildStubArgs, jsonSchemaToZod, warning/message helpers, and default importers) are not owned exports.

@b4run/langchain/package.jsonCopy link to section: @b4run/langchain/package.json

This subpath is package metadata as JSON for tooling. It has no TypeScript exports, runtime classification, or purity claim. Don't execute it as application code.

Key contractsCopy link to section: Key contracts

ts
export interface AgentStreamChunk {
  readonly type:
    | "token"
    | "tool_call"
    | "tool_call_args"
    | "tool_result"
    | "interrupt"
    | "done"
    | (string & {})
  readonly data: unknown
  readonly messageId?: string
}

Fields: @b4run/langchain#.:AgentStreamChunk

FieldTypeRequiredDescription
readonly type| "token" | "tool_call" | "tool_call_args" | "tool_result" | "interrupt" | "done" | (string & {})yesIdentify the chunk kind.
readonly dataunknownyesCarry the chunk payload.
readonly messageIdstringnoIdentify the source model invocation for text tokens within this stream.

Text token data remains a string. Non-subagent model text carries messageId from its model invocation. A message_end chunk with { messageId } follows that model's text before any same-model tool announcements. Models that emit no text produce no completion chunk. This preserves independent text framing for concurrent nested models. Invocation identity does not deduplicate replays.

ts
export interface RetryOptions {
  readonly maxAttempts?: number
  readonly baseDelayMs?: number
  readonly maxDelayMs?: number
  readonly signal?: AbortSignal
}

Fields: @b4run/langchain#.:RetryOptions

FieldTypeRequiredDescription
readonly maxAttemptsnumbernoSet total attempts; defaults to 3.
readonly baseDelayMsnumbernoSet the first backoff; defaults to 1000.
readonly maxDelayMsnumbernoCap backoff; defaults to 10000.
readonly signalAbortSignalnoCancel the retry loop.
ts
export declare function resolveProvider(options: {
  readonly model: string
  readonly provider?: ModelProviderId
}): BuiltInModelProviderId
ts
export declare function withRetry<T>(
  fn: () => Promise<T>,
  options?: RetryOptions,
): Promise<T>
ts
export interface OffloadToolOutputCtx {
  readonly toolName: string
  readonly thresholdChars: number
  readonly previewLines: number
  readonly store: Pick<OffloadStore, "write">
  readonly signal?: AbortSignal
  readonly toolCallId?: string
}

Fields: @b4run/langchain#.:OffloadToolOutputCtx

FieldTypeRequiredDescription
readonly toolNamestringyesName the output's tool.
readonly thresholdCharsnumberyesSet the character threshold.
readonly previewLinesnumberyesSet the retained preview length.
readonly storePick<OffloadStore, "write">yesPersist full output.
readonly signalAbortSignalnoCancel the write.
readonly toolCallIdstringnoKey the filename; content hashing is the fallback.
ts
export interface UnwrappedToolResult {
  readonly content: string | readonly B4ContentPart[]
  readonly stateUpdates: Record<string, unknown> | undefined
}

Fields: @b4run/langchain#.:UnwrappedToolResult

FieldTypeRequiredDescription
readonly contentstring | readonly B4ContentPart[]yesCarry agent-visible content: text, or the content parts the tool returned.
readonly stateUpdatesRecord<string, unknown> | undefinedyesCarry optional channel updates.

Several callable exports use non-barrel helper shapes in their declarations. These shapes are listed here for reading. You can't import them:

ts
type Importer = (specifier: string) => Promise<Record<string, unknown>>
type ResolvedStateField = {
  readonly name: string
  readonly reducer: "append" | "replace" | ((current: unknown, incoming: unknown) => unknown)
  readonly default: unknown
}
type ToolExecutor = {
  readonly name: string
  readonly run: (
    input: unknown,
    context: {
      readonly middleware?: Readonly<Record<string, unknown>>
      readonly signal: AbortSignal
    },
  ) => Promise<unknown> | unknown
}
type ExecuteWithToolLoopOptions = {
  readonly chain: { readonly invoke: (input: unknown) => Promise<unknown> }
  readonly input: unknown
  readonly middlewareContext?: Readonly<Record<string, unknown>>
  readonly tools: readonly ToolExecutor[]
  readonly signal: AbortSignal
  readonly maxIterations?: number
}
type BuildStubArgs = {
  readonly content: string
  readonly relPath: string
  readonly previewLines: number
  readonly thresholdChars: number
}

The larger inline AgentOptions shape used by executeAgent and streamAgent requires checkpointer, entry, input, routeParamNames, signal, and tools. It also accepts middleware, retry, state, prompt, offload, summarization, subagent, thread, sandbox, and cache-bypass controls. The subagent converter accepts a private { name, description?, schema? } placeholder, and the tool converter accepts the same basic tool definition plus a run callback. defaultSummarize accepts messages, model, optional previous summary, signal, and optional maxRetries for the model it builds.

Materialized graphs are cached by descriptor plus checkpointer. Sandbox-bound tools, subagents, stream transformers, and explicit bypass requests skip reuse. A checkpointer is mandatory at runtime. threadId is also required for an interrupted run to resume. Generated edge assembly must seed its static provider importer before model construction.

Behavior contractsCopy link to section: Behavior contracts

Behavior contract langchain.provider.explicit

An explicit model provider bypasses provider inference.

Provider lifecycle and failures

Unknown explicit providers throw with the supported list. If no provider is explicit and inference fails, resolution throws before model construction. seedModelImporter() is last-call-wins process state. Seed it during runtime assembly, not per request.

createChatModel({ responseFormat }) and streamAgent({ responseFormat }) bind a JsonSchemaResponseFormat on the root model as the provider's native schema-constrained output (OpenAI response_format with json_schema and strict: true, or Anthropic output_config.format). The route's tools stay bound, so tool-calling turns are unaffected and only the final message is constrained.

Only the providers in JSON_SCHEMA_RESPONSE_FORMAT_PROVIDERS qualify. Any other provider throws unsupportedResponseFormatMessage(provider) before its package is imported, so it never runs unconstrained. A format-bound agent always compiles a fresh graph and never touches the materialized-agent cache. The AG-UI endpoint sources it from the client's hashbrown.responseSchema. See AG-UI.

Behavior contract langchain.retry.exhaustion

Retry throws after the configured maximum attempts are exhausted.

Retry failures

Only recognized transient messages retry. Non-transient failures throw immediately, cancellation throws Operation aborted, and retry delays include up to 500 ms of jitter capped by maxDelayMs.

Behavior contract langchain.tool-loop.limit

The tool loop limits iterations to prevent an infinite loop.

Tool-loop failures

Unknown tools and thrown tool failures become ToolMessage error content. Reaching the default 10 rounds, or an explicit lower limit, throws rather than returning a partial result.

Behavior contract langchain.chain.stream-fallback

A chain stream falls back to invoke when the entry has no stream method.

Chain, offload, and summarization limits

The fallback yields the invocation result once. Both execute and stream reject entries without invoke. Native stream() results may be returned directly or through a promise.

Offload thresholds count characters, and the full tool output is written into the workspace. Both stored content and preview stubs may contain sensitive data. Filenames sanitize tool names and call IDs. Without a call ID they use a content hash. Cleanup is throttled and best-effort, while offloadToolOutput() returns original content if persistence fails. Tool wrapper recognition is strict: extra keys, arrays, missing result, or result: undefined use plain-return handling.

Summarization changes only the model's input view. If the summarizer fails, that turn falls back to full history. It compresses context and isn't a security control.

ts
import { chainAdapter, resolveProvider, withRetry } from "@b4run/langchain"
 
const provider = resolveProvider({ model: "gpt-5-mini" })
const runnable = {
  invoke: async (input: { prompt: string }) => ({ provider, answer: input.prompt }),
}
 
const result = await withRetry(
  () =>
    chainAdapter.execute(runnable, { prompt: "hello" }, {
      signal: new AbortController().signal,
    }),
  { maxAttempts: 3 },
)

Continue with Agents, Context Management, Retry, and SDK API.