LangChain Tutorial (TypeScript): building conditional routing for beginners

By Cyprian AaronsUpdated 2026-04-21
langchainbuilding-conditional-routing-for-beginnerstypescript

This tutorial shows you how to build a simple conditional router in LangChain TypeScript that sends user input down different chains based on intent. You need this when one prompt is not enough and your app has to choose between paths like support, sales, or general Q&A.

What You'll Need

  • Node.js 18+
  • TypeScript project with ts-node or tsx
  • langchain installed
  • @langchain/openai installed
  • An OpenAI API key set as OPENAI_API_KEY
  • Basic familiarity with async/await and LangChain chat models

Install the packages:

npm install langchain @langchain/openai
npm install -D typescript tsx @types/node

Step-by-Step

  1. Start by creating a small routing function. The router will classify the user message into one of three buckets: billing, technical, or general.
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "langchain/prompts";
import { StringOutputParser } from "langchain/output_parsers";

const model = new ChatOpenAI({
  modelName: "gpt-4o-mini",
  temperature: 0,
});

const routePrompt = ChatPromptTemplate.fromMessages([
  ["system", "Classify the user's message as billing, technical, or general. Return only one word."],
  ["human", "{input}"],
]);

const routeChain = routePrompt.pipe(model).pipe(new StringOutputParser());
  1. Add the destination chains. Each chain can use a different prompt and return a focused answer for that intent.
const billingPrompt = ChatPromptTemplate.fromMessages([
  ["system", "You are a billing support assistant. Answer clearly and concisely."],
  ["human", "{input}"],
]);

const technicalPrompt = ChatPromptTemplate.fromMessages([
  ["system", "You are a technical support assistant. Give practical troubleshooting steps."],
  ["human", "{input}"],
]);

const generalPrompt = ChatPromptTemplate.fromMessages([
  ["system", "You are a helpful general assistant."],
  ["human", "{input}"],
]);

const billingChain = billingPrompt.pipe(model);
const technicalChain = technicalPrompt.pipe(model);
const generalChain = generalPrompt.pipe(model);
  1. Build the router function. This is the conditional logic that calls the classifier first, then dispatches to the correct chain.
async function answerUser(input: string) {
  const route = (await routeChain.invoke({ input })).trim().toLowerCase();

  if (route === "billing") {
    return billingChain.invoke({ input });
  }

  if (route === "technical") {
    return technicalChain.invoke({ input });
  }

  return generalChain.invoke({ input });
}
  1. Add a runnable example so you can test the full flow from the command line.
async function main() {
  const questions = [
    "Why was I charged twice this month?",
    "My app crashes when I upload a file.",
    "What is your refund policy?",
  ];

  for (const question of questions) {
    const response = await answerUser(question);
    console.log("\nQ:", question);
    console.log("A:", response.content);
  }
}

main().catch(console.error);
  1. If you want stricter routing, validate the classifier output before dispatching. This prevents bad model output from breaking your app when it returns something unexpected.
type Route = "billing" | "technical" | "general";

function normalizeRoute(value: string): Route {
  const route = value.trim().toLowerCase();
  if (route === "billing" || route === "technical" || route === "general") {
    return route;
  }
  return "general";
}

async function safeAnswerUser(input: string) {
  const rawRoute = await routeChain.invoke({ input });
  const route = normalizeRoute(rawRoute);

  switch (route) {
    case "billing":
      return billingChain.invoke({ input });
    case "technical":
      return technicalChain.invoke({ input });
    default:
      return generalChain.invoke({ input });
  }
}

Testing It

Run the file with npx tsx your-file.ts after setting OPENAI_API_KEY. You should see each question routed to a different style of answer depending on whether it looks like billing, technical, or general support.

To verify routing, log the selected route before returning the final response. If every question goes to the wrong branch, tighten the system prompt in routePrompt so it returns only one label and nothing else.

Try edge cases like "I was overcharged and my invoice is wrong" or "The dashboard throws a timeout error". Those should clearly map to billing and technical respectively; if they do not, your classifier prompt needs better examples.

Next Steps

  • Replace string labels with structured JSON output using LangChain output parsers
  • Add more routes like sales, security, and account-access
  • Move from manual if statements to LangChain’s branching/runnable composition patterns

Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides