@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
npm install @b4run/langchain @langchain/core @langchain/langgraph-checkpointimport {
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
| Surface | Runtime | Purity | Audience | Stability |
|---|---|---|---|---|
@b4run/langchain | edge-safe | not-claimed | integration | supported |
@b4run/langchain/package.json | package metadata | n/a | tooling | supported |
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
| Export | Responsibility |
|---|---|
AgentStreamChunk | Describe streamed tokens, tool activity, interrupts, completion, and extensions. |
AgentTurnResult | Describe a settled agent turn's output and whether it parked on an interrupt. |
B4ToolDefinition | Describe a B4.run tool accepted by agent materialization. |
__resetMaterializedAgentsForTests | Reset the process-global materialized-agent cache for tests. |
executeAgent | Consume an agent stream and return its completed output. |
executeAgentTurn | Execute one materialized-agent turn and return its structured result. |
materializeAgentGraph | Compile a B4.run agent descriptor into a LangGraph graph. |
streamAgent | Stream normalized agent chunks. |
chainAdapter | Adapt a LangChain runnable to B4.run's chain backend contract. |
BuiltInModelProviderId | Re-export the SDK-owned built-in provider union. |
ModelProviderId | Re-export the SDK-owned provider identifier. |
createChatModel | Load and construct a selected provider chat model, optionally bound to a JSON-schema response format. |
JsonSchemaResponseFormat | Describe a JSON schema the root model's final message must match. |
JSON_SCHEMA_RESPONSE_FORMAT_PROVIDERS | List the providers whose schema-constrained output coexists with tool calls. |
supportsJsonSchemaResponseFormat | Report whether a provider can be bound to a JSON-schema response format. |
unsupportedResponseFormatMessage | Produce the rejection message for a provider that cannot. |
ModalitySupport | Describe which content parts a route's model takes, by modality and source. |
DEFAULT_MODALITY_SUPPORT | Supply the support assumed for a model with no profile: images inline and by URL. |
resolveModalitySupport | Read a model's LangChain profile and apply the provider's converter limits. |
readModelProfile | Read a model's LangChain profile off its provider class without constructing it; undefined when the provider package is not installed. |
ConvertedContent | Describe converted message content and the parts dropped from it. |
LangChainContentBlock | Describe one LangChain standard content block. |
DroppedPart | Describe one dropped part: its index, type, source and reason. |
DropReason | Name why a part was dropped. |
DroppedPartsReport | Describe the parts dropped from one message, with the model and route they were judged against. |
toLangChainContent | Convert content parts to LangChain content blocks, dropping what the model cannot take. |
formatDroppedPartsWarning | Format the server-log warning that announces dropped parts. |
pickDroppedPartsReport | Pick the report fields off a content_parts_dropped or subagent.content_parts_dropped chunk's data. |
providerPackages | Map built-in provider IDs to integration packages. |
seedModelImporter | Install the process-global fallback provider importer. |
inferProvider | Re-export SDK provider inference. |
resolveProvider | Resolve an explicit provider or infer one from a model ID. |
modelMaxRetries | Map an agent's retry to a chat model's maxRetries (maxAttempts - 1, default 2). |
resolveReasoningConfig | Check an agent's reasoning against its resolved provider and map it to the chat model's constructor options, reporting whether reasoning text will stream. |
ResolvedReasoningConfig | Describe the resolved reasoning controls: constructor options and the streams flag GET /agui/:routeId advertises. |
RetryOptions | Configure retry attempts, backoff, cap, and cancellation. |
isRetryableError | Classify known transient error messages. |
withRetry | Retry transient async failures with jittered exponential backoff. |
openaiEmbedder | Construct the OpenAI-backed memory embedder. |
OffloadStoreOptions | Configure an offload store and its cleanup limits. |
buildOffloadFileName | Produce a sanitized deterministic output filename. |
OffloadStore | Persist tool output and perform throttled best-effort cleanup. |
OffloadToolOutputCtx | Configure one conditional tool-output offload. |
offloadToolOutput | Replace oversized output with a saved-file preview stub. |
buildStub | Format a human-readable offloaded-output stub. |
OffloadFn | Describe the tool converter's output-offload callback. |
ToolResultModality | Describe the root model's modality support, used to shape a tool's media result. |
B4_CONTENT_PARTS_KEY | Name the ToolMessage additional_kwargs key that keeps every part a tool returned, for the UI. |
convertToolToLangChain | Convert a B4.run tool into a LangChain structured tool. |
executeWithToolLoop | Invoke a chain and execute bounded tool-call rounds. |
UnwrappedToolResult | Describe agent-visible content and optional state updates. |
unwrapToolResult | Decode B4.run's strict { result, state? } tool-return wrapper. |
Command | Re-export LangGraph's resume/state-update command. |
materializeStateSchema | Build a LangGraph annotation root from resolved state fields. |
ResolvedSubagentGraph | Describe a resolved child route graph. |
SubagentResolver | Resolve an allowed task request to a child graph or rejection. |
convertSubagentTaskToLangChain | Convert B4.run's task placeholder to a resumable LangChain tool. |
RunningSummary | Track summary text and covered message count. |
TokenCounter | Count text tokens synchronously or asynchronously. |
SummarizeFn | Describe the injected summarization operation. |
ResolvedSummarizationConfig | Hold resolved thresholds and summarization dependencies. |
PreModelHookState | Describe messages and the optional running summary. |
PreModelHookResult | Return a model-only message view and updated summary. |
buildSummarizationHook | Build the non-destructive pre-model summary hook. |
splitForSummary | Split aged messages from recent turns. |
defaultSummarize | Summarize messages with the selected chat model. |
countMessagesTokens | Count tokens across LangChain messages. |
defaultTokenCounter | Count 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
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
| Field | Type | Required | Description |
|---|---|---|---|
readonly type | | "token" | "tool_call" | "tool_call_args" | "tool_result" | "interrupt" | "done" | (string & {}) | yes | Identify the chunk kind. |
readonly data | unknown | yes | Carry the chunk payload. |
readonly messageId | string | no | Identify 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.
export interface RetryOptions {
readonly maxAttempts?: number
readonly baseDelayMs?: number
readonly maxDelayMs?: number
readonly signal?: AbortSignal
}Fields: @b4run/langchain#.:RetryOptions
| Field | Type | Required | Description |
|---|---|---|---|
readonly maxAttempts | number | no | Set total attempts; defaults to 3. |
readonly baseDelayMs | number | no | Set the first backoff; defaults to 1000. |
readonly maxDelayMs | number | no | Cap backoff; defaults to 10000. |
readonly signal | AbortSignal | no | Cancel the retry loop. |
export declare function resolveProvider(options: {
readonly model: string
readonly provider?: ModelProviderId
}): BuiltInModelProviderIdexport declare function withRetry<T>(
fn: () => Promise<T>,
options?: RetryOptions,
): Promise<T>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
| Field | Type | Required | Description |
|---|---|---|---|
readonly toolName | string | yes | Name the output's tool. |
readonly thresholdChars | number | yes | Set the character threshold. |
readonly previewLines | number | yes | Set the retained preview length. |
readonly store | Pick<OffloadStore, "write"> | yes | Persist full output. |
readonly signal | AbortSignal | no | Cancel the write. |
readonly toolCallId | string | no | Key the filename; content hashing is the fallback. |
export interface UnwrappedToolResult {
readonly content: string | readonly B4ContentPart[]
readonly stateUpdates: Record<string, unknown> | undefined
}Fields: @b4run/langchain#.:UnwrappedToolResult
| Field | Type | Required | Description |
|---|---|---|---|
readonly content | string | readonly B4ContentPart[] | yes | Carry agent-visible content: text, or the content parts the tool returned. |
readonly stateUpdates | Record<string, unknown> | undefined | yes | Carry 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:
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.
Examples and related guidesCopy link to section: Examples and related guides
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.