@openuidev/langchain
API reference for streaming LangChain and LangGraph agents to OpenUI over AG-UI.
Use this package to transform LangGraph protocol-v2 message and tool events into AG-UI and relay them to an OpenUI frontend over Server-Sent Events.
The package is framework-independent at the HTTP boundary. Its server APIs use Web-standard
Request, Response, fetch, and ReadableStream rather than depending on Next.js or
DeepAgents.
Install
Install the package for the Web-standard server helpers:
pnpm add @openuidev/langchainApplications that run the agent-side transformer also install the optional LangGraph peer:
npm install @openuidev/langchain @langchain/langgraphThe integration requires an agent-protocol-v2 server with both the custom:* and root lifecycle
event channels. The tested local-server baseline is @langchain/langgraph-cli 1.4.x.
Data flow
openUIStreamTransformer()converts LangGraphmessagesandtoolsevents to AG-UI events on the remotecustom:openuichannel.createLangChainStreamResponse()starts a stateless LangGraph run, adds the AG-UI run lifecycle, and relays that channel as SSE.- OpenUI's
agUIAdapter()consumes the response without LangChain-specific frontend code.
openUIStreamTransformer()
Import the transformer from the /transformer subpath and register it with any agent that accepts
LangGraph streamTransformers:
import { openUIStreamTransformer } from "@openuidev/langchain/transformer";
import { createDeepAgent } from "deepagents";
export const graph = createDeepAgent({
model: "openai:gpt-5.5",
tools: [getWeather, getStockPrice, searchWeb],
systemPrompt: SYSTEM_PROMPT,
streamTransformers: [openUIStreamTransformer],
});function openUIStreamTransformer(): StreamTransformer<{
openui: StreamChannel<AGUIEvent>;
}>;The transformer handles assistant text, tool-call deltas, tool results, and run errors. LangGraph
publishes the resulting events remotely under custom:openui. The transformer subpath is the only
entrypoint that loads @langchain/langgraph; the root server helpers communicate with LangGraph
over HTTP.
createLangChainStreamResponse(request, options)
Creates the complete AG-UI-request-to-LangGraph-response path for a stateless chat route:
function createLangChainStreamResponse(
request: Request,
options: CreateLangChainStreamResponseOptions,
): Promise<Response>;interface CreateLangChainStreamResponseOptions {
apiUrl: string;
assistantId: string;
apiKey?: string;
debug?: boolean;
cleanupThread?: boolean;
waitUntil?: (task: Promise<void>) => void;
prepareInput?: (context: PrepareLangChainRunInputContext) => unknown | Promise<unknown>;
}The request body must contain a non-empty { messages: Message[] } value in AG-UI format. Invalid
JSON or messages return a JSON 400 response without starting a LangGraph run.
The helper:
- Converts text and multimodal user content to LangChain input messages.
- Preserves complete assistant tool-call and tool-result pairs.
- Removes incomplete calls and orphaned tool results before starting the run.
- Returns AG-UI SSE with
RUN_STARTEDandRUN_FINISHEDorRUN_ERRORlifecycle events. - Creates a temporary LangGraph thread and attempts bounded cleanup after the response completes.
- Redacts upstream response details and registered graph ids unless trusted development code enables
debug.
It can be returned directly from a Next.js route or any other Web-standard route handler:
import { createLangChainStreamResponse } from "@openuidev/langchain";
export const runtime = "nodejs";
export async function POST(request: Request) {
return createLangChainStreamResponse(request, {
apiUrl: process.env.LANGGRAPH_API_URL ?? "http://localhost:2024",
assistantId: process.env.LANGGRAPH_ASSISTANT_ID ?? "agent",
apiKey: process.env.LANGSMITH_API_KEY,
debug: process.env.NODE_ENV !== "production",
});
}prepareInput(context)
Use prepareInput when the graph needs fields from the browser request in addition to converted
messages:
interface PrepareLangChainRunInputContext {
messages: LangChainInputMessage[];
requestBody: Record<string, unknown>;
}return createLangChainStreamResponse(request, {
apiUrl: process.env.LANGGRAPH_API_URL ?? "http://localhost:2024",
assistantId: "agent",
prepareInput: ({ messages, requestBody }) => ({
messages: messages.slice(-1),
conversationId: requestBody.threadId,
model: requestBody.model,
}),
});If prepareInput throws, the helper returns its error message in a 400 response and does not
start a run.
Cleanup on serverless platforms
Temporary-thread cleanup defaults to enabled. Pass the platform's waitUntil-style registration
function when cleanup should survive a client disconnect:
return createLangChainStreamResponse(request, {
apiUrl,
assistantId,
waitUntil: (task) => executionContext.waitUntil(task),
});Set cleanupThread: false only when the temporary thread must remain available for local debugging.
streamOpenUI(options)
Use the lower-level relay when the route builds the LangGraph input itself:
interface StreamOpenUIOptions {
apiUrl: string;
assistantId: string;
apiKey?: string;
input: unknown;
signal?: AbortSignal;
debug?: boolean;
cleanupThread?: boolean;
waitUntil?: (task: Promise<void>) => void;
}
function streamOpenUI(options: StreamOpenUIOptions): ReadableStream<Uint8Array>;import { streamOpenUI } from "@openuidev/langchain";
const body = streamOpenUI({
apiUrl: "http://localhost:2024",
assistantId: "agent",
input: { messages: [{ type: "human", content: "Hello" }] },
signal: request.signal,
});
return new Response(body, {
headers: { "Content-Type": "text/event-stream" },
});Cancelling the returned stream or aborting signal aborts both upstream LangGraph requests.
Connect the OpenUI frontend
The route returns standard AG-UI SSE, so the browser uses OpenUI's normal adapter:
import { AgentInterface, agUIAdapter, fetchLLM } from "@openuidev/react-ui";
const llm = fetchLLM({
url: "/api/chat",
streamAdapter: agUIAdapter(),
});
export function Chat() {
return <AgentInterface llm={llm} />;
}Exports
| Entry point | Export | Description |
|---|---|---|
@openuidev/langchain | createLangChainStreamResponse | Complete Web-standard request/response helper |
@openuidev/langchain | streamOpenUI | Lower-level protocol-v2 runner and AG-UI relay |
@openuidev/langchain | CreateLangChainStreamResponseOptions | Request helper configuration |
@openuidev/langchain | PrepareLangChainRunInputContext | Values passed to prepareInput |
@openuidev/langchain | LangChainInputMessage | Converted graph input message shape |
@openuidev/langchain | StreamOpenUIOptions | Lower-level relay configuration |
@openuidev/langchain/transformer | openUIStreamTransformer | Agent-side protocol-v2 to AG-UI transformer |
See the complete langchain-chat
example for local and LangGraph Platform setups.