!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}return t}()||function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}(),document.documentElement.setAttribute("data-announcement-bar-initially-dismissed",function(){try{return"true"===localStorage.getItem("docusaurus.announcement.dismiss")}catch(t){}return!1}())

[Skip to main content](#__docusaurus_skipToContent_fallback)

You are viewing the **preview** v0.2 docs. View the **stable** v0.1 docs [here](/v0.1/docs/get_started/introduction/). Leave feedback on the v0.2 docs [here](https://github.com/langchain-ai/langchainjs/discussions/5386).

[

![🦜️🔗 Langchain](/v0.2/img/brand/wordmark.png)![🦜️🔗 Langchain](/v0.2/img/brand/wordmark-dark.png)

](/v0.2/)[Integrations](/v0.2/docs/integrations/platforms/)[API Reference](https://v02.api.js.langchain.com)

[More](#)

*   [People](/v0.2/docs/people/)
*   [Community](/v0.2/docs/community)
*   [Tutorials](/v0.2/docs/additional_resources/tutorials)
*   [Contributing](/v0.2/docs/contributing)

[v0.2](#)

*   [v0.2](/v0.2/docs/introduction)
*   [v0.1](https://js.langchain.com/v0.1/docs/get_started/introduction)

[🦜🔗](#)

*   [LangSmith](https://smith.langchain.com)
*   [LangSmith Docs](https://docs.smith.langchain.com)
*   [LangChain Hub](https://smith.langchain.com/hub)
*   [LangServe](https://github.com/langchain-ai/langserve)
*   [Python Docs](https://python.langchain.com/)

[Chat](https://chatjs.langchain.com)[](https://github.com/langchain-ai/langchainjs)

Search

*   [Introduction](/v0.2/docs/introduction)
*   [Tutorials](/v0.2/docs/tutorials/)
    
    *   [Build a Question Answering application over a Graph Database](/v0.2/docs/tutorials/graph)
    *   [Tutorials](/v0.2/docs/tutorials/)
    *   [Build a Simple LLM Application](/v0.2/docs/tutorials/llm_chain)
    *   [Build a Query Analysis System](/v0.2/docs/tutorials/query_analysis)
    *   [Build a Chatbot](/v0.2/docs/tutorials/chatbot)
    *   [Build an Agent](/v0.2/docs/tutorials/agents)
    *   [Build an Extraction Chain](/v0.2/docs/tutorials/extraction)
    *   [Summarize Text](/v0.2/docs/tutorials/summarization)
    *   [Tagging](/v0.2/docs/tutorials/classification)
    *   [Build a Local RAG Application](/v0.2/docs/tutorials/local_rag)
    *   [Conversational RAG](/v0.2/docs/tutorials/qa_chat_history)
    *   [Build a Retrieval Augmented Generation (RAG) App](/v0.2/docs/tutorials/rag)
    *   [Build a Question/Answering system over SQL data](/v0.2/docs/tutorials/sql_qa)
*   [How-to guides](/v0.2/docs/how_to/)
    
    *   [How-to guides](/v0.2/docs/how_to/)
    *   [How to use example selectors](/v0.2/docs/how_to/example_selectors)
    *   [Installation](/v0.2/docs/how_to/installation)
    *   [How to stream responses from an LLM](/v0.2/docs/how_to/streaming_llm)
    *   [How to stream chat model responses](/v0.2/docs/how_to/chat_streaming)
    *   [How to embed text data](/v0.2/docs/how_to/embed_text)
    *   [How to use few shot examples in chat models](/v0.2/docs/how_to/few_shot_examples_chat)
    *   [How to cache model responses](/v0.2/docs/how_to/llm_caching)
    *   [How to cache chat model responses](/v0.2/docs/how_to/chat_model_caching)
    *   [How to create a custom LLM class](/v0.2/docs/how_to/custom_llm)
    *   [How to use few shot examples](/v0.2/docs/how_to/few_shot_examples)
    *   [How to use output parsers to parse an LLM response into structured format](/v0.2/docs/how_to/output_parser_structured)
    *   [How to return structured data from a model](/v0.2/docs/how_to/structured_output)
    *   [How to add ad-hoc tool calling capability to LLMs and Chat Models](/v0.2/docs/how_to/tools_prompting)
    *   [How to create a custom chat model class](/v0.2/docs/how_to/custom_chat)
    *   [How to do per-user retrieval](/v0.2/docs/how_to/qa_per_user)
    *   [How to track token usage](/v0.2/docs/how_to/chat_token_usage_tracking)
    *   [How to track token usage](/v0.2/docs/how_to/llm_token_usage_tracking)
    *   [How to pass through arguments from one step to the next](/v0.2/docs/how_to/passthrough)
    *   [How to compose prompts together](/v0.2/docs/how_to/prompts_composition)
    *   [How to use legacy LangChain Agents (AgentExecutor)](/v0.2/docs/how_to/agent_executor)
    *   [How to add values to a chain's state](/v0.2/docs/how_to/assign)
    *   [How to attach runtime arguments to a Runnable](/v0.2/docs/how_to/binding)
    *   [How to cache embedding results](/v0.2/docs/how_to/caching_embeddings)
    *   [How to split by character](/v0.2/docs/how_to/character_text_splitter)
    *   [How to manage memory](/v0.2/docs/how_to/chatbots_memory)
    *   [How to do retrieval](/v0.2/docs/how_to/chatbots_retrieval)
    *   [How to use tools](/v0.2/docs/how_to/chatbots_tools)
    *   [How to split code](/v0.2/docs/how_to/code_splitter)
    *   [How to do retrieval with contextual compression](/v0.2/docs/how_to/contextual_compression)
    *   [How to write a custom retriever class](/v0.2/docs/how_to/custom_retriever)
    *   [How to create custom Tools](/v0.2/docs/how_to/custom_tools)
    *   [How to debug your LLM apps](/v0.2/docs/how_to/debugging)
    *   [How to load CSV data](/v0.2/docs/how_to/document_loader_csv)
    *   [How to write a custom document loader](/v0.2/docs/how_to/document_loader_custom)
    *   [How to load data from a directory](/v0.2/docs/how_to/document_loader_directory)
    *   [How to load PDF files](/v0.2/docs/how_to/document_loader_pdf)
    *   [How to load JSON data](/v0.2/docs/how_to/document_loaders_json)
    *   [How to select examples by length](/v0.2/docs/how_to/example_selectors_length_based)
    *   [How to select examples by similarity](/v0.2/docs/how_to/example_selectors_similarity)
    *   [How to use reference examples](/v0.2/docs/how_to/extraction_examples)
    *   [How to handle long text](/v0.2/docs/how_to/extraction_long_text)
    *   [How to do extraction without using function calling](/v0.2/docs/how_to/extraction_parse)
    *   [Fallbacks](/v0.2/docs/how_to/fallbacks)
    *   [Few Shot Prompt Templates](/v0.2/docs/how_to/few_shot)
    *   [How to run custom functions](/v0.2/docs/how_to/functions)
    *   [How to construct knowledge graphs](/v0.2/docs/how_to/graph_constructing)
    *   [How to map values to a database](/v0.2/docs/how_to/graph_mapping)
    *   [How to improve results with prompting](/v0.2/docs/how_to/graph_prompting)
    *   [How to add a semantic layer over the database](/v0.2/docs/how_to/graph_semantic)
    *   [How to reindex data to keep your vectorstore in-sync with the underlying data source](/v0.2/docs/how_to/indexing)
    *   [How to get log probabilities](/v0.2/docs/how_to/logprobs)
    *   [How to add message history](/v0.2/docs/how_to/message_history)
    *   [How to generate multiple embeddings per document](/v0.2/docs/how_to/multi_vector)
    *   [How to generate multiple queries to retrieve data for](/v0.2/docs/how_to/multiple_queries)
    *   [How to parse JSON output](/v0.2/docs/how_to/output_parser_json)
    *   [How to retry when output parsing errors occur](/v0.2/docs/how_to/output_parser_retry)
    *   [How to parse XML output](/v0.2/docs/how_to/output_parser_xml)
    *   [How to invoke runnables in parallel](/v0.2/docs/how_to/parallel)
    *   [How to retrieve the whole document for a chunk](/v0.2/docs/how_to/parent_document_retriever)
    *   [How to partially format prompt templates](/v0.2/docs/how_to/prompts_partial)
    *   [How to add chat history to a question-answering chain](/v0.2/docs/how_to/qa_chat_history_how_to)
    *   [How to return citations](/v0.2/docs/how_to/qa_citations)
    *   [How to return sources](/v0.2/docs/how_to/qa_sources)
    *   [How to stream from a question-answering chain](/v0.2/docs/how_to/qa_streaming)
    *   [How to construct filters](/v0.2/docs/how_to/query_constructing_filters)
    *   [How to add examples to the prompt](/v0.2/docs/how_to/query_few_shot)
    *   [How to deal with high cardinality categorical variables](/v0.2/docs/how_to/query_high_cardinality)
    *   [How to handle multiple queries](/v0.2/docs/how_to/query_multiple_queries)
    *   [How to handle multiple retrievers](/v0.2/docs/how_to/query_multiple_retrievers)
    *   [How to handle cases where no queries are generated](/v0.2/docs/how_to/query_no_queries)
    *   [How to recursively split text by characters](/v0.2/docs/how_to/recursive_text_splitter)
    *   [How to reduce retrieval latency](/v0.2/docs/how_to/reduce_retrieval_latency)
    *   [How to route execution within a chain](/v0.2/docs/how_to/routing)
    *   [How to chain runnables](/v0.2/docs/how_to/sequence)
    *   [How to split text by tokens](/v0.2/docs/how_to/split_by_token)
    *   [How to deal with large databases](/v0.2/docs/how_to/sql_large_db)
    *   [How to use prompting to improve results](/v0.2/docs/how_to/sql_prompting)
    *   [How to do query validation](/v0.2/docs/how_to/sql_query_checking)
    *   [How to stream](/v0.2/docs/how_to/streaming)
    *   [How to create a time-weighted retriever](/v0.2/docs/how_to/time_weighted_vectorstore)
    *   [How to use a chat model to call tools](/v0.2/docs/how_to/tool_calling)
    *   [How to call tools with multi-modal data](/v0.2/docs/how_to/tool_calls_multi_modal)
    *   [How to use LangChain tools](/v0.2/docs/how_to/tools_builtin)
    *   [How use a vector store to retrieve data](/v0.2/docs/how_to/vectorstore_retriever)
    *   [How to create and query vector stores](/v0.2/docs/how_to/vectorstores)
*   [Conceptual guide](/v0.2/docs/concepts)
*   Ecosystem
    
    *   [🦜🛠️ LangSmith](/v0.2/docs/langsmith/)
        
    *   [🦜🕸️LangGraph.js](/v0.2/docs/langgraph)
*   Versions
    
    *   [Overview](/v0.2/docs/versions/overview)
    *   [v0.2](/v0.2/docs/versions/v0_2)
    *   [Release Policy](/v0.2/docs/versions/release_policy)
    *   [Packages](/v0.2/docs/versions/packages)
*   [Security](/v0.2/docs/security)

*   [](/v0.2/)
*   Ecosystem
*   🦜🕸️LangGraph.js

On this page

🦜🕸️LangGraph.js
=================

⚡ Building language agents as graphs ⚡

Overview[​](#overview "Direct link to Overview")
------------------------------------------------

LangGraph is a library for building stateful, multi-actor applications with LLMs, built on top of (and intended to be used with) [LangChain.js](https://github.com/langchain-ai/langchainjs). It extends the [LangChain Expression Language](/v0.2/docs/how_to/#langchain-expression-language-lcel) with the ability to coordinate multiple chains (or actors) across multiple steps of computation in a cyclic manner. It is inspired by [Pregel](https://research.google/pubs/pub37252/) and [Apache Beam](https://beam.apache.org/). The current interface exposed is one inspired by [NetworkX](https://networkx.org/documentation/latest/).

The main use is for adding **cycles** to your LLM application. Crucially, LangGraph is NOT optimized for only **DAG** workflows. If you want to build a DAG, you should use just use [LangChain Expression Language](/v0.2/docs/how_to/#langchain-expression-language-lcel).

Cycles are important for agent-like behaviors, where you call an LLM in a loop, asking it what action to take next.

> Looking for the Python version? Click [here](https://github.com/langchain-ai/langgraph).

Installation[​](#installation "Direct link to Installation")
------------------------------------------------------------

    npm install @langchain/langgraph

Quick start[​](#quick-start "Direct link to Quick start")
---------------------------------------------------------

One of the central concepts of LangGraph is state. Each graph execution creates a state that is passed between nodes in the graph as they execute, and each node updates this internal state with its return value after it executes. The way that the graph updates its internal state is defined by either the type of graph chosen or a custom function.

State in LangGraph can be pretty general, but to keep things simpler to start, we'll show off an example where the graph's state is limited to a list of chat messages using the built-in `MessageGraph` class. This is convenient when using LangGraph with LangChain chat models because we can return chat model output directly.

First, install the LangChain OpenAI integration package:

    npm i @langchain/openai

We also need to export some environment variables:

    export OPENAI_API_KEY=sk-...

And now we're ready! The graph below contains a single node called `"oracle"` that executes a chat model, then returns the result:

    import { ChatOpenAI } from "@langchain/openai";import { HumanMessage, BaseMessage } from "@langchain/core/messages";import { END, MessageGraph } from "@langchain/langgraph";const model = new ChatOpenAI({ temperature: 0 });const graph = new MessageGraph();graph.addNode("oracle", async (state: BaseMessage[]) => {  return model.invoke(state);});graph.addEdge("oracle", END);graph.setEntryPoint("oracle");const runnable = graph.compile();

Let's run it!

    // For Message graph, input should always be a message or list of messages.const res = await runnable.invoke(new HumanMessage("What is 1 + 1?"));

    [  HumanMessage {    content: 'What is 1 + 1?',    additional_kwargs: {}  },  AIMessage {    content: '1 + 1 equals 2.',    additional_kwargs: { function_call: undefined, tool_calls: undefined }  }]

So what did we do here? Let's break it down step by step:

1.  First, we initialize our model and a `MessageGraph`.
2.  Next, we add a single node to the graph, called `"oracle"`, which simply calls the model with the given input.
3.  We add an edge from this `"oracle"` node to the special value `END`. This means that execution will end after current node.
4.  We set `"oracle"` as the entrypoint to the graph.
5.  We compile the graph, ensuring that no more modifications to it can be made.

Then, when we execute the graph:

1.  LangGraph adds the input message to the internal state, then passes the state to the entrypoint node, `"oracle"`.
2.  The `"oracle"` node executes, invoking the chat model.
3.  The chat model returns an `AIMessage`. LangGraph adds this to the state.
4.  Execution progresses to the special `END` value and outputs the final state.

And as a result, we get a list of two chat messages as output.

### Interaction with LCEL[​](#interaction-with-lcel "Direct link to Interaction with LCEL")

As an aside for those already familiar with LangChain - `addNode` actually takes any runnable as input. In the above example, the passed function is automatically converted, but we could also have passed the model directly:

    graph.addNode("oracle", model);

In which case the `.invoke()` method will be called when the graph executes.

Just make sure you are mindful of the fact that the input to the runnable is the entire current state. So this will fail:

    // This will NOT work with MessageGraph!import {  ChatPromptTemplate,  MessagesPlaceholder,} from "@langchain/core/prompts";const prompt = ChatPromptTemplate.fromMessages([  ["system", "You are a helpful assistant who always speaks in pirate dialect"],  MessagesPlaceholder("messages"),]);const chain = prompt.pipe(model);// State is a list of messages, but our chain expects an object input://// { messages: [] }//// Therefore, the graph will throw an exception when it executes here.graph.addNode("oracle", chain);

Conditional edges[​](#conditional-edges "Direct link to Conditional edges")
---------------------------------------------------------------------------

Now, let's move onto something a little bit less trivial. Because math can be difficult for LLMs, let's allow the LLM to conditionally call a calculator node using tool calling.

    npm i langchain @langchain/openai

We'll recreate our graph with an additional `"calculator"` that will take the result of the most recent message, if it is a math expression, and calculate the result. We'll also bind the calculator to the OpenAI model as a tool to allow the model to optionally use the tool if it deems necessary:

    import { ToolMessage } from "@langchain/core/messages";import { Calculator } from "langchain/tools/calculator";import { convertToOpenAITool } from "@langchain/core/utils/function_calling";const model = new ChatOpenAI({  temperature: 0,}).bind({  tools: [convertToOpenAITool(new Calculator())],  tool_choice: "auto",});const graph = new MessageGraph();graph.addNode("oracle", async (state: BaseMessage[]) => {  return model.invoke(state);});graph.addNode("calculator", async (state: BaseMessage[]) => {  const tool = new Calculator();  const toolCalls = state[state.length - 1].additional_kwargs.tool_calls ?? [];  const calculatorCall = toolCalls.find(    (toolCall) => toolCall.function.name === "calculator"  );  if (calculatorCall === undefined) {    throw new Error("No calculator input found.");  }  const result = await tool.invoke(    JSON.parse(calculatorCall.function.arguments)  );  return new ToolMessage({    tool_call_id: calculatorCall.id,    content: result,  });});graph.addEdge("calculator", END);graph.setEntryPoint("oracle");

Now let's think - what do we want to have happen?

*   If the `"oracle"` node returns a message expecting a tool call, we want to execute the `"calculator"` node
*   If not, we can just end execution

We can achieve this using **conditional edges**, which routes execution to a node based on the current state using a function.

Here's what that looks like:

    const router = (state: BaseMessage[]) => {  const toolCalls = state[state.length - 1].additional_kwargs.tool_calls ?? [];  if (toolCalls.length) {    return "calculator";  } else {    return "end";  }};graph.addConditionalEdges("oracle", router, {  calculator: "calculator",  end: END,});

If the model output contains a tool call, we move to the `"calculator"` node. Otherwise, we end.

Great! Now all that's left is to compile the graph and try it out. Math-related questions are routed to the calculator tool:

    const runnable = graph.compile();const mathResponse = await runnable.invoke(new HumanMessage("What is 1 + 1?"));

    [  HumanMessage {    content: 'What is 1 + 1?',    additional_kwargs: {}  },  AIMessage {    content: '',    additional_kwargs: { function_call: undefined, tool_calls: [Array] }  },  ToolMessage {    content: '2',    name: undefined,    additional_kwargs: {},    tool_call_id: 'call_P7KWQoftVsj6fgsqKyolWp91'  }]

While conversational responses are outputted directly:

    const otherResponse = await runnable.invoke(  new HumanMessage("What is your name?"));

    [  HumanMessage {    content: 'What is your name?',    additional_kwargs: {}  },  AIMessage {    content: 'My name is Assistant. How can I assist you today?',    additional_kwargs: { function_call: undefined, tool_calls: undefined }  }]

Cycles[​](#cycles "Direct link to Cycles")
------------------------------------------

Now, let's go over a more general example with a cycle. We will recreate the [`AgentExecutor`](/v0.2/docs/how_to/agent_executor/) class from LangChain.

The benefits of creating it with LangGraph is that it is more modifiable.

We will need to install some LangChain packages:

    npm install langchain @langchain/core @langchain/community @langchain/openai

We also need additional environment variables.

    export OPENAI_API_KEY=sk-...export TAVILY_API_KEY=tvly-...

Optionally, we can set up [LangSmith](https://docs.smith.langchain.com/) for best-in-class observability.

    export LANGCHAIN_TRACING_V2="true"export LANGCHAIN_API_KEY=ls__...export LANGCHAIN_ENDPOINT=https://api.langchain.com

### Set up the tools[​](#set-up-the-tools "Direct link to Set up the tools")

As above, we will first define the tools we want to use. For this simple example, we will use a built-in search tool via Tavily. However, it is really easy to create your own tools - see documentation [here](/v0.2/docs/how_to/custom_tools) on how to do that.

    import { TavilySearchResults } from "@langchain/community/tools/tavily_search";const tools = [new TavilySearchResults({ maxResults: 1 })];

We can now wrap these tools in a ToolExecutor, which simply takes in a ToolInvocation and calls that tool, returning the output.

A ToolInvocation is any type with `tool` and `toolInput` attribute.

    import { ToolExecutor } from "@langchain/langgraph/prebuilt";const toolExecutor = new ToolExecutor({ tools });

### Set up the model[​](#set-up-the-model "Direct link to Set up the model")

Now we need to load the chat model we want to use. This time, we'll use the older function calling interface. This walkthrough will use OpenAI, but we can choose any model that supports OpenAI function calling.

    import { ChatOpenAI } from "@langchain/openai";// We will set streaming: true so that we can stream tokens// See the streaming section for more information on this.const model = new ChatOpenAI({  temperature: 0,  streaming: true,});

After we've done this, we should make sure the model knows that it has these tools available to call. We can do this by converting the LangChain tools into the format for OpenAI function calling, and then bind them to the model class.

    import { convertToOpenAIFunction } from "@langchain/core/utils/function_calling";const toolsAsOpenAIFunctions = tools.map((tool) =>  convertToOpenAIFunction(tool));const newModel = model.bind({  functions: toolsAsOpenAIFunctions,});

### Define the agent state[​](#define-the-agent-state "Direct link to Define the agent state")

This time, we'll use the more general `StateGraph`. This graph is parameterized by a state object that it passes around to each node. Remember that each node then returns operations to update that state. These operations can either SET specific attributes on the state (e.g. overwrite the existing values) or ADD to the existing attribute. Whether to set or add is denoted by annotating the state object you construct the graph with.

For this example, the state we will track will just be a list of messages. We want each node to just add messages to that list. Therefore, we will use an object with one key (`messages`) with the value as an object: `{ value: Function, default?: () => any }`

The `default` key must be a factory that returns the default value for that attribute.

    import { BaseMessage } from "@langchain/core/messages";const agentState = {  messages: {    value: (x: BaseMessage[], y: BaseMessage[]) => x.concat(y),    default: () => [],  },};

You can think of the `MessageGraph` used in the initial example as a preconfigured version of this graph. The difference is that the state is directly a list of messages, instead of an object containing a key called `"messages"` whose value is a list of messages. The `MessageGraph` update step is similar to the one above where we always append the returned values of a node to the internal state.

### Define the nodes[​](#define-the-nodes "Direct link to Define the nodes")

We now need to define a few different nodes in our graph. In LangGraph, a node can be either a function or a [runnable](/v0.2/docs/how_to/#langchain-expression-language-lcel). There are two main nodes we need for this:

1.  The agent: responsible for deciding what (if any) actions to take.
2.  A function to invoke tools: if the agent decides to take an action, this node will then execute that action.

We will also need to define some edges. Some of these edges may be conditional. The reason they are conditional is that based on the output of a node, one of several paths may be taken. The path that is taken is not known until that node is run (the LLM decides).

1.  Conditional Edge: after the agent is called, we should either: a. If the agent said to take an action, then the function to invoke tools should be called b. If the agent said that it was finished, then it should finish
2.  Normal Edge: after the tools are invoked, it should always go back to the agent to decide what to do next

Let's define the nodes, as well as a function to decide how what conditional edge to take.

    import { FunctionMessage } from "@langchain/core/messages";import { AgentAction } from "@langchain/core/agents";import {  ChatPromptTemplate,  MessagesPlaceholder,} from "@langchain/core/prompts";// Define the function that determines whether to continue or notconst shouldContinue = (state: { messages: Array<BaseMessage> }) => {  const { messages } = state;  const lastMessage = messages[messages.length - 1];  // If there is no function call, then we finish  if (    !("function_call" in lastMessage.additional_kwargs) ||    !lastMessage.additional_kwargs.function_call  ) {    return "end";  }  // Otherwise if there is, we continue  return "continue";};// Define the function to execute toolsconst _getAction = (state: { messages: Array<BaseMessage> }): AgentAction => {  const { messages } = state;  // Based on the continue condition  // we know the last message involves a function call  const lastMessage = messages[messages.length - 1];  if (!lastMessage) {    throw new Error("No messages found.");  }  if (!lastMessage.additional_kwargs.function_call) {    throw new Error("No function call found in message.");  }  // We construct an AgentAction from the function_call  return {    tool: lastMessage.additional_kwargs.function_call.name,    toolInput: JSON.parse(      lastMessage.additional_kwargs.function_call.arguments    ),    log: "",  };};// Define the function that calls the modelconst callModel = async (state: { messages: Array<BaseMessage> }) => {  const { messages } = state;  // You can use a prompt here to tweak model behavior.  // You can also just pass messages to the model directly.  const prompt = ChatPromptTemplate.fromMessages([    ["system", "You are a helpful assistant."],    new MessagesPlaceholder("messages"),  ]);  const response = await prompt.pipe(newModel).invoke({ messages });  // We return a list, because this will get added to the existing list  return {    messages: [response],  };};const callTool = async (state: { messages: Array<BaseMessage> }) => {  const action = _getAction(state);  // We call the tool_executor and get back a response  const response = await toolExecutor.invoke(action);  // We use the response to create a FunctionMessage  const functionMessage = new FunctionMessage({    content: response,    name: action.tool,  });  // We return a list, because this will get added to the existing list  return { messages: [functionMessage] };};

### Define the graph[​](#define-the-graph "Direct link to Define the graph")

We can now put it all together and define the graph!

    import { StateGraph, END } from "@langchain/langgraph";// Define a new graphconst workflow = new StateGraph({  channels: agentState,});// Define the two nodes we will cycle betweenworkflow.addNode("agent", callModel);workflow.addNode("action", callTool);// Set the entrypoint as `agent`// This means that this node is the first one calledworkflow.setEntryPoint("agent");// We now add a conditional edgeworkflow.addConditionalEdges(  // First, we define the start node. We use `agent`.  // This means these are the edges taken after the `agent` node is called.  "agent",  // Next, we pass in the function that will determine which node is called next.  shouldContinue,  // Finally we pass in a mapping.  // The keys are strings, and the values are other nodes.  // END is a special node marking that the graph should finish.  // What will happen is we will call `should_continue`, and then the output of that  // will be matched against the keys in this mapping.  // Based on which one it matches, that node will then be called.  {    // If `tools`, then we call the tool node.    continue: "action",    // Otherwise we finish.    end: END,  });// We now add a normal edge from `tools` to `agent`.// This means that after `tools` is called, `agent` node is called next.workflow.addEdge("action", "agent");// Finally, we compile it!// This compiles it into a LangChain Runnable,// meaning you can use it as you would any other runnableconst app = workflow.compile();

### Use it![​](#use-it "Direct link to Use it!")

We can now use it! This now exposes the [same interface](/v0.2/docs/how_to/#langchain-expression-language-lcel) as all other LangChain runnables. This runnable accepts a list of messages.

    import { HumanMessage } from "@langchain/core/messages";const inputs = {  messages: [new HumanMessage("what is the weather in sf")],};const result = await app.invoke(inputs);

See a LangSmith trace of this run [here](https://smith.langchain.com/public/144af8a3-b496-43aa-ba9d-f0d5894196e2/r).

This may take a little bit - it's making a few calls behind the scenes. In order to start seeing some intermediate results as they happen, we can use streaming - see below for more information on that.

Streaming[​](#streaming "Direct link to Streaming")
---------------------------------------------------

LangGraph has support for several different types of streaming.

### Streaming Node Output[​](#streaming-node-output "Direct link to Streaming Node Output")

One of the benefits of using LangGraph is that it is easy to stream output as it's produced by each node.

    const inputs = {  messages: [new HumanMessage("what is the weather in sf")],};for await (const output of await app.stream(inputs)) {  console.log("output", output);  console.log("-----\n");}

See a LangSmith trace of this run [here](https://smith.langchain.com/public/968cd1bf-0db2-410f-a5b4-0e73066cf06e/r).

Running Examples[​](#running-examples "Direct link to Running Examples")
------------------------------------------------------------------------

You can find some more example notebooks of different use-cases in the `examples/` folder in this repo. These example notebooks use the [Deno runtime](https://deno.land/).

To pull in environment variables, you can create a `.env` file at the **root** of this repo (not in the `examples/` folder itself).

When to Use[​](#when-to-use "Direct link to When to Use")
---------------------------------------------------------

When should you use this versus [LangChain Expression Language](/v0.2/docs/how_to/#langchain-expression-language-lcel)?

If you need cycles.

Langchain Expression Language allows you to easily define chains (DAGs) but does not have a good mechanism for adding in cycles. `langgraph` adds that syntax.

Examples[​](#examples "Direct link to Examples")
------------------------------------------------

### ChatAgentExecutor: with function calling[​](#chatagentexecutor-with-function-calling "Direct link to ChatAgentExecutor: with function calling")

This agent executor takes a list of messages as input and outputs a list of messages. All agent state is represented as a list of messages. This specifically uses OpenAI function calling. This is recommended agent executor for newer chat based models that support function calling.

*   [Getting Started Notebook](https://github.com/langchain-ai/langgraphjs/tree/main/examples/chat_agent_executor_with_function_calling/base.ipynb): Walks through creating this type of executor from scratch

### AgentExecutor[​](#agentexecutor "Direct link to AgentExecutor")

This agent executor uses existing LangChain agents.

*   [Getting Started Notebook](https://github.com/langchain-ai/langgraphjs/tree/main/examples/agent_executor/base.ipynb): Walks through creating this type of executor from scratch

### Multi-agent Examples[​](#multi-agent-examples "Direct link to Multi-agent Examples")

*   [Multi-agent collaboration](https://github.com/langchain-ai/langgraphjs/tree/main/examples/multi_agent/multi_agent_collaboration.ipynb): how to create two agents that work together to accomplish a task
*   [Multi-agent with supervisor](https://github.com/langchain-ai/langgraphjs/tree/main/examples/multi_agent/agent_supervisor.ipynb): how to orchestrate individual agents by using an LLM as a "supervisor" to distribute work
*   [Hierarchical agent teams](https://github.com/langchain-ai/langgraphjs/tree/main/examples/multi_agent/hierarchical_agent_teams.ipynb): how to orchestrate "teams" of agents as nested graphs that can collaborate to solve a problem

Documentation[​](#documentation "Direct link to Documentation")
---------------------------------------------------------------

There are only a few new APIs to use.

### StateGraph[​](#stategraph "Direct link to StateGraph")

The main entrypoint is `StateGraph`.

    import { StateGraph } from "@langchain/langgraph";

This class is responsible for constructing the graph. It exposes an interface inspired by [NetworkX](https://networkx.org/documentation/latest/). This graph is parameterized by a state object that it passes around to each node.

#### `constructor`[​](#constructor "Direct link to constructor")

    interface StateGraphArgs<T = any> {  channels: Record<    string,    {      value: BinaryOperator<T> | null;      default?: () => T;    }  >;}class StateGraph<T> extends Graph {  constructor(fields: StateGraphArgs<T>) {}

When constructing the graph, you need to pass in a schema for a state. Each node then returns operations to update that state. These operations can either SET specific attributes on the state (e.g. overwrite the existing values) or ADD to the existing attribute. Whether to set or add is denoted by annotating the state object you construct the graph with.

Let's take a look at an example:

    import { BaseMessage } from "@langchain/core/messages";const schema = {  input: {    value: null,  },  agentOutcome: {    value: null,  },  steps: {    value: (x: Array<BaseMessage>, y: Array<BaseMessage>) => x.concat(y),    default: () => [],  },};

We can then use this like:

    // Initialize the StateGraph with this stateconst graph = new StateGraph({ channels: schema })// Create nodes and edges...// Compile the graphconst app = graph.compile()// The inputs should be an object, because the schema is an objectconst inputs = {   // Let's assume this the input   input: "hi"   // Let's assume agent_outcome is set by the graph as some point   // It doesn't need to be provided, and it will be null by default}

### `.addNode`[​](#addnode "Direct link to addnode")

    addNode(key: string, action: RunnableLike<RunInput, RunOutput>): void

This method adds a node to the graph. It takes two arguments:

*   `key`: A string representing the name of the node. This must be unique.
*   `action`: The action to take when this node is called. This should either be a function or a runnable.

### `.addEdge`[​](#addedge "Direct link to addedge")

    addEdge(startKey: string, endKey: string): void

Creates an edge from one node to the next. This means that output of the first node will be passed to the next node. It takes two arguments.

*   `startKey`: A string representing the name of the start node. This key must have already been registered in the graph.
*   `endKey`: A string representing the name of the end node. This key must have already been registered in the graph.

### `.addConditionalEdges`[​](#addconditionaledges "Direct link to addconditionaledges")

    addConditionalEdges(  startKey: string,  condition: CallableFunction,  conditionalEdgeMapping: Record<string, string>): void

This method adds conditional edges. What this means is that only one of the downstream edges will be taken, and which one that is depends on the results of the start node. This takes three arguments:

*   `startKey`: A string representing the name of the start node. This key must have already been registered in the graph.
*   `condition`: A function to call to decide what to do next. The input will be the output of the start node. It should return a string that is present in `conditionalEdgeMapping` and represents the edge to take.
*   `conditionalEdgeMapping`: A mapping of string to string. The keys should be strings that may be returned by `condition`. The values should be the downstream node to call if that condition is returned.

### `.setEntryPoint`[​](#setentrypoint "Direct link to setentrypoint")

    setEntryPoint(key: string): void

The entrypoint to the graph. This is the node that is first called. It only takes one argument:

*   `key`: The name of the node that should be called first.

### `.setFinishPoint`[​](#setfinishpoint "Direct link to setfinishpoint")

    setFinishPoint(key: string): void

This is the exit point of the graph. When this node is called, the results will be the final result from the graph. It only has one argument:

*   `key`: The name of the node that, when called, will return the results of calling it as the final output

Note: This does not need to be called if at any point you previously created an edge (conditional or normal) to `END`

### `END`[​](#end "Direct link to end")

    import { END } from "@langchain/langgraph";

This is a special node representing the end of the graph. This means that anything passed to this node will be the final output of the graph. It can be used in two places:

*   As the `endKey` in `addEdge`
*   As a value in `conditionalEdgeMapping` as passed to `addConditionalEdges`

When to Use[​](#when-to-use-1 "Direct link to When to Use")
-----------------------------------------------------------

When should you use this versus [LangChain Expression Language](/v0.2/docs/how_to/#langchain-expression-language-lcel)?

If you need cycles.

Langchain Expression Language allows you to easily define chains (DAGs) but does not have a good mechanism for adding in cycles. `langgraph` adds that syntax.

Examples[​](#examples-1 "Direct link to Examples")
--------------------------------------------------

### AgentExecutor[​](#agentexecutor-1 "Direct link to AgentExecutor")

See the above Quick Start for an example of re-creating the LangChain [`AgentExecutor`](/v0.2/docs/how_to/agent_executor/) class.

### Forced Function Calling[​](#forced-function-calling "Direct link to Forced Function Calling")

One simple modification of the above Graph is to modify it such that a certain tool is always called first. This can be useful if you want to enforce a certain tool is called, but still want to enable agentic behavior after the fact.

Assuming you have done the above Quick Start, you can build off it like:

#### Define the first tool call[​](#define-the-first-tool-call "Direct link to Define the first tool call")

Here, we manually define the first tool call that we will make. Notice that it does that same thing as `agent` would have done (adds the `agentOutcome` key). This is so that we can easily plug it in.

    import { AgentStep, AgentAction, AgentFinish } from "@langchain/core/agents";// Define the data type that the agent will return.type AgentData = {  input: string;  steps: Array<AgentStep>;  agentOutcome?: AgentAction | AgentFinish;};const firstAgent = (inputs: AgentData) => {  const newInputs = inputs;  const action = {    // We force call this tool    tool: "tavily_search_results_json",    // We just pass in the `input` key to this tool    toolInput: newInputs.input,    log: "",  };  newInputs.agentOutcome = action;  return newInputs;};

#### Create the graph[​](#create-the-graph "Direct link to Create the graph")

We can now create a new graph with this new node

    const workflow = new Graph();// Add the same nodes as before, plus this "first agent"workflow.addNode("firstAgent", firstAgent);workflow.addNode("agent", agent);workflow.addNode("tools", executeTools);// We now set the entry point to be this first agentworkflow.setEntryPoint("firstAgent");// We define the same edges as beforeworkflow.addConditionalEdges("agent", shouldContinue, {  continue: "tools",  exit: END,});workflow.addEdge("tools", "agent");// We also define a new edge, from the "first agent" to the tools node// This is so that we can call the toolworkflow.addEdge("firstAgent", "tools");// We now compile the graph as beforeconst chain = workflow.compile();

#### Use it![​](#use-it-1 "Direct link to Use it!")

We can now use it as before! Depending on whether or not the first tool call is actually useful, this may save you an LLM call or two.

    const result = await chain.invoke({  input: "what is the weather in sf",  steps: [],});

You can see a LangSmith trace of this chain [here](https://smith.langchain.com/public/2e0a089f-8c05-405a-8404-b0a60b79a84a/r).

* * *

#### Was this page helpful?

  

#### You can leave detailed feedback [on GitHub](https://github.com/langchain-ai/langchainjs/issues/new?assignees=&labels=03+-+Documentation&projects=&template=documentation.yml&title=DOC%3A+%3CPlease+write+a+comprehensive+title+after+the+%27DOC%3A+%27+prefix%3E).

[

Previous

walkthrough

](/v0.2/docs/langsmith/walkthrough)[

Next

Overview

](/v0.2/docs/versions/overview)

*   [Overview](#overview)
*   [Installation](#installation)
*   [Quick start](#quick-start)
    *   [Interaction with LCEL](#interaction-with-lcel)
*   [Conditional edges](#conditional-edges)
*   [Cycles](#cycles)
    *   [Set up the tools](#set-up-the-tools)
    *   [Set up the model](#set-up-the-model)
    *   [Define the agent state](#define-the-agent-state)
    *   [Define the nodes](#define-the-nodes)
    *   [Define the graph](#define-the-graph)
    *   [Use it!](#use-it)
*   [Streaming](#streaming)
    *   [Streaming Node Output](#streaming-node-output)
*   [Running Examples](#running-examples)
*   [When to Use](#when-to-use)
*   [Examples](#examples)
    *   [ChatAgentExecutor: with function calling](#chatagentexecutor-with-function-calling)
    *   [AgentExecutor](#agentexecutor)
    *   [Multi-agent Examples](#multi-agent-examples)
*   [Documentation](#documentation)
    *   [StateGraph](#stategraph)
    *   [`.addNode`](#addnode)
    *   [`.addEdge`](#addedge)
    *   [`.addConditionalEdges`](#addconditionaledges)
    *   [`.setEntryPoint`](#setentrypoint)
    *   [`.setFinishPoint`](#setfinishpoint)
    *   [`END`](#end)
*   [When to Use](#when-to-use-1)
*   [Examples](#examples-1)
    *   [AgentExecutor](#agentexecutor-1)
    *   [Forced Function Calling](#forced-function-calling)

Community

*   [Discord](https://discord.gg/cU2adEyC7w)
*   [Twitter](https://twitter.com/LangChainAI)

GitHub

*   [Python](https://github.com/langchain-ai/langchain)
*   [JS/TS](https://github.com/langchain-ai/langchainjs)

More

*   [Homepage](https://langchain.com)
*   [Blog](https://blog.langchain.dev)

Copyright © 2024 LangChain, Inc.