LiveKit docs › Build Agents › Models › LLM › Additional models › LangChain

---

# LangChain integration guide

> How to use LangGraph workflows and LangChain agents with LiveKit.

Available in:
- [ ] Node.js
- [x] Python

## Overview

This plugin allows you to use LangGraph and other graph-based LangChain agents as an LLM provider for your voice agents.

### Installation

Install the LiveKit LangChain plugin from PyPI:

```shell
uv add "livekit-agents[langchain]~=1.8"

```

### Usage

To use a LangGraph workflow within an `AgentSession`, compile your graph and wrap it with the `LLMAdapter`. The following example builds a single-node graph that calls a chat model and uses it as the agent's LLM. For a full agent you can run, see the [complete example](#complete-example).

```python
from typing import Annotated, TypedDict

from langchain.chat_models import init_chat_model
from langchain_core.messages import BaseMessage
from langgraph.graph import START, StateGraph
from langgraph.graph.message import add_messages

from livekit.agents import AgentSession
from livekit.plugins import langchain


class State(TypedDict):
    messages: Annotated[list[BaseMessage], add_messages]


def create_graph():
    llm = init_chat_model("openai:gpt-4.1-mini")

    def chatbot(state: State):
        return {"messages": [llm.invoke(state["messages"])]}

    builder = StateGraph(State)
    builder.add_node("chatbot", chatbot)
    builder.add_edge(START, "chatbot")
    return builder.compile()


# Use the compiled graph as the LLM
session = AgentSession(
    llm=langchain.LLMAdapter(graph=create_graph()),
    # ... stt, tts, vad, turn_handling, etc.
)

```

The `LLMAdapter` automatically converts the LiveKit chat context to [LangChain messages](https://docs.langchain.com/oss/python/langchain/messages). The mapping is as follows:

- `system` and `developer` messages to `SystemMessage`.
- `user` messages to `HumanMessage`.
- `assistant` messages to `AIMessage`.

### Parameters

This section describes the available parameters for the `LLMAdapter`. See the [plugin reference](https://docs.livekit.io/reference/python/livekit/plugins/langchain/index.html.md#livekit.plugins.langchain.LLMAdapter) for a complete list of all available parameters.

- **`graph`** _(PregelProtocol)_: The LangGraph workflow to use as an LLM. Must be a locally compiled graph. To learn more, see [Graph Definitions](https://reference.langchain.com/python/langgraph/graphs).

- **`config`** _(RunnableConfig | None)_ (optional) - Default: `None`: Configuration options for the LangGraph workflow execution. This can include runtime configuration, callbacks, and other LangGraph-specific options. To learn more, see [RunnableConfig](https://reference.langchain.com/python/langchain-core/runnables/config/RunnableConfig).

- **`context`** _(ContextT | None)_ (optional) - Default: `None`: Static runtime context passed to the graph on each invocation. Use it to supply values your nodes read at runtime, such as a user ID or feature flags. To learn more, see [Runtime context](https://docs.langchain.com/oss/python/langchain/runtime).

- **`subgraphs`** _(bool)_ (optional) - Default: `False`: Whether to stream outputs from nested subgraphs. Enable this when your graph composes other graphs and you want their tokens and custom data to reach the agent. To learn more, see [subgraphs](https://docs.langchain.com/oss/python/langgraph/use-subgraphs).

- **`stream_mode`** _(StreamMode | list[StreamMode])_ (optional) - Default: `messages`: Which LangGraph [streaming mode](#streaming-modes) the adapter consumes. Only `messages` and `custom` are supported. Other values raise a `ValueError`.

## Streaming modes

The `LLMAdapter` consumes your graph's output using [LangGraph streaming](https://docs.langchain.com/oss/python/langgraph/streaming) and forwards it to the agent's TTS in realtime. Use the `stream_mode` parameter to control which output the adapter streams. Only two modes are supported:

- `messages` (default): Streams LLM token chunks as the graph's chat model generates them. This minimizes time to first token and is the right choice for most voice agents.
- `custom`: Streams data your nodes emit explicitly with LangGraph's `get_stream_writer`. Use this to speak text that doesn't come directly from an LLM, such as a fixed acknowledgment or the result of a tool call.

To consume both at once, pass a list:

```python
llm = langchain.LLMAdapter(graph=create_graph(), stream_mode=["messages", "custom"])

```

### Stream custom data

In `custom` mode, call `get_stream_writer()` inside a node to get a writer, then pass it the data you want spoken. The adapter speaks a string directly, or the `content` field of a dictionary that includes one. It skips payloads without text content.

```python
from langchain_core.messages import AIMessage
from langgraph.config import get_stream_writer


def lookup_status(state: State):
    writer = get_stream_writer()
    writer("Let me check on that for you.")  # spoken immediately

    status = fetch_status()  # your own long-running call
    message = f"Your order status is {status}."
    writer(message)  # spoken when ready

    # Record the turn in graph state. Only the writer output is spoken.
    return {"messages": [AIMessage(content=message)]}

```

Enable `custom` mode, alone or in a list, when you construct the adapter:

```python
llm = langchain.LLMAdapter(graph=create_graph(), stream_mode=["messages", "custom"])

```

## Supported LangChain agent types

The LiveKit LangChain plugin supports [LangGraph](https://reference.langchain.com/python/langgraph/graphs) and other graph-based LangChain agents:

- [Agents](https://docs.langchain.com/oss/python/langchain/agents) built with `create_agent`.
- [Deep agents](https://docs.langchain.com/oss/python/deepagents/overview) built with `create_deep_agent`.

All of these return a `CompiledStateGraph` (Pregel-compatible), which the `LLMAdapter` accepts directly.

To add voice to an existing LangChain agent, pass the compiled graph to `LLMAdapter` and use it as the `Agent`'s LLM: `llm=langchain.LLMAdapter(graph=your_compiled_graph)`.

The plugin does not support non-graph patterns such as plain LCEL chains (`prompt | llm`) or bare chat models.

For complete examples including LangGraph, LangChain agents, and deep agents, see the [recipes page](https://docs.livekit.io/reference/recipes.md?tag=langchain).

## Complete example

The following agent uses a LangGraph workflow as its LLM. The graph handles the model call and any tool use, while the `AgentSession` handles voice orchestration such as turns and interruptions. To run it, install the plugin with the `langchain` extra and add `langchain[openai]` and `langgraph` to your dependencies.

```python
import logging
from typing import Annotated, TypedDict

from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
from langchain_core.messages import BaseMessage
from langgraph.graph import START, StateGraph
from langgraph.graph.message import add_messages

from livekit import agents
from livekit.agents import (
    Agent,
    AgentServer,
    AgentSession,
    JobContext,
    inference,
)
from livekit.plugins import langchain

logger = logging.getLogger("langgraph-agent")

load_dotenv()


class State(TypedDict):
    messages: Annotated[list[BaseMessage], add_messages]


def create_graph():
    llm = init_chat_model("openai:gpt-4.1-mini")

    def chatbot(state: State):
        return {"messages": [llm.invoke(state["messages"])]}

    builder = StateGraph(State)
    builder.add_node("chatbot", chatbot)
    builder.add_edge(START, "chatbot")
    return builder.compile()


server = AgentServer()


@server.rtc_session()
async def entrypoint(ctx: JobContext):
    # Instructions and tool calls live in the LangGraph workflow, so the
    # Agent's own instructions can be left empty.
    agent = Agent(
        instructions="",
        llm=langchain.LLMAdapter(graph=create_graph()),
    )

    session = AgentSession(
        stt=inference.STT("assemblyai/universal-3-6-pro", language="en"),

        tts=inference.TTS("fishaudio/s2.1-pro", voice="fa4c9eb3dccc4806b382b40d61c6b10a"),

    )

    await session.start(agent=agent, room=ctx.room)
    await session.generate_reply(instructions="Ask the user how they're doing.")


if __name__ == "__main__":
    agents.cli.run_app(server)

```

## Latency

This plugin uses LangGraph's streaming mode to minimize time to first token as much as possible, but take care when porting LangChain workflows that were not originally designed for voice use cases. For more information on handling long-running operations and providing a better user experience, see the [user feedback documentation](https://docs.livekit.io/agents/logic/external-data.md#user-feedback).

## Additional resources

The following resources provide more information about using LangChain with LiveKit Agents.

- **[Python package](https://pypi.org/project/livekit-plugins-langchain/)**: The `livekit-plugins-langchain` package on PyPI.

- **[Plugin reference](https://docs.livekit.io/reference/python/livekit/plugins/langchain/index.html.md#livekit.plugins.langchain.LLMAdapter)**: Reference for the LangChain LLM adapter.

- **[GitHub repo](https://github.com/livekit/agents/tree/main/livekit-plugins/livekit-plugins-langchain)**: View the source or contribute to the LiveKit LangChain plugin.

- **[LangChain docs](https://docs.langchain.com/oss/python/langchain/overview)**: LangChain documentation and tutorials.

- **[LangGraph docs](https://docs.langchain.com/oss/python/langgraph/overview)**: LangGraph documentation for building stateful workflows.

- **[Example apps](https://docs.livekit.io/reference/recipes.md?tag=langchain)**: Examples showing LangChain integration with LiveKit.

---

This document was rendered at 2026-10-07T15:45:40.481Z.
For the latest version of this document, see [https://docs.livekit.io/agents/models/llm/langchain.md](https://docs.livekit.io/agents/models/llm/langchain.md).

To explore all LiveKit documentation, see [llms.txt](https://docs.livekit.io/llms.txt).