Skip to content

feat(examples): replace langgraph-chat with deepagents-based langchain-chat#689

Open
christian-bromann wants to merge 1 commit into
thesysdev:mainfrom
christian-bromann:cb/langchain-chat-deepagents-example
Open

feat(examples): replace langgraph-chat with deepagents-based langchain-chat#689
christian-bromann wants to merge 1 commit into
thesysdev:mainfrom
christian-bromann:cb/langchain-chat-deepagents-example

Conversation

@christian-bromann

@christian-bromann christian-bromann commented Jun 28, 2026

Copy link
Copy Markdown

What

Updating the LangChain example to use stream transformer to simplify user code. I would love to see OpenUI maintain some of these primitives, e.g. examples/langchain-chat/src/lib as well as the stream transformer, in so users wouldn't need to maintain the code themselves. Ideally all the user needs to do to use LangChain with OpenUI is:

Define an agent, e.g.:

import { streamTransformer } from "@openuidev/langchain";

export const graph = createDeepAgent({
  model: `openai:gpt-5.5`,
  tools: [getWeather, getStockPrice, searchWeb],
  systemPrompt: SYSTEM_PROMPT,
  streamTransformers: [openUIStreamTransformer],
});

Define the custom API endpoint in Next.js:

import { createLangChainStreamResponse } from "@openuidev/langchain";
import { NextRequest } from "next/server";

export const runtime = "nodejs";

/**
 * Local LangGraph server configuration defined via langgraph.json
 */
const API_URL = process.env.LANGGRAPH_API_URL || "http://localhost:2024";
const ASSISTANT_ID = process.env.LANGGRAPH_ASSISTANT_ID || "agent";

/**
 * Proxies the browser <-> LangGraph server. The browser posts native AG-UI
 * messages; {@link createLangChainStreamResponse} converts them to LangChain
 * messages, starts the graph over the protocol-v2 endpoints, and relays only
 * the custom OpenUI channel.
 */
export async function POST(req: NextRequest) {
  return createLangChainStreamResponse(req, {
    apiUrl: API_URL,
    assistantId: ASSISTANT_ID,
  });
}

The stream transformer transforms the agent stream to be AGUI compatible so that in the frontend code, no LangChain specific adapter is needed.

Changes

  • Renamed/rewrote examples/langgraph-chat to examples/langchain-chat, swapping the hand-built supervisor graph for a single createDeepAgent agent (src/agent/agent.ts) that loads the generated OpenUI system prompt via readFileSync (the LangGraph dev server's tsx/CJS loader can't handle with { type: "text" } import attributes).
  • Added a local openUIStreamTransformer (src/agent/openui-transformer.ts) that consumes @langchain/protocol MessagesData events and emits AG-UI events on a StreamChannel.remote("openui") channel, with no namespace filtering so nested model_request:*/tools:* messages are forwarded.
  • Added src/lib/stream-openui.ts, a framework-agnostic helper that drives an agent-protocol-v2 run, subscribes to custom:openui (no namespace/depth filter), unwraps the forwarded AG-UI events, and relays them as SSE — fully TSDoc-documented.
  • Extracted the request→stream→Response glue into createLangChainStreamResponse (src/lib/langchain-stream-response.ts) so OpenUI can later export it as a reusable helper; the route handler (src/app/api/chat/route.ts) is now a thin delegator.
  • Simplified the frontend (src/app/page.tsx) to use OpenUI's default apiUrl adapter (removed the custom processMessage/streamProtocol wiring) and dropped the local LANGSMITH_API_KEY read since this is a local demo (the apiKey option remains optional on the helpers).
  • Used the web-standard global crypto.randomUUID() instead of importing from node:crypto.
  • Updated package.json (deepagents/langchain deps, dev script that runs the UI and LangGraph server together), README.md, and .env.example to match the new architecture; refreshed pnpm-lock.yaml.

Test Plan

Describe how you validated this change.

  • Not applicable (explain why)
  • Verified locally

Checklist

  • I linked a related issue, if applicable
  • I updated docs/README when needed
  • I considered backwards compatibility

…n-chat

Rewrite the example agent on top of deepagents and stream OpenUI Lang
to the browser via a custom transformer, so the UI no longer needs
bespoke message/stream-protocol handling. The transformer is kept local
to the example until the OpenUI team decides where it should live.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant