Skip to main content
CopilotKit provides a full React chat runtime and pairs especially well with LangGraph when you want the agent to return structured UI payloads instead of only plain text. In this pattern, your LangGraph deployment serves both the graph API and a custom CopilotKit endpoint, while the frontend parses assistant messages into dynamic React components. On the server, the copilotkit package provides CopilotKitMiddleware so a LangGraph graph, a LangChain agent, or a Deep Agent can speak the Agent UI (AG-UI) wire protocol, stream tool and message events to a chat UI, and read or write the shared CopilotKit slice of state, with helpers to mount a CopilotKit-compatible HTTP endpoint in front of your graph. This approach is useful when you want:
  • a ready-made chat runtime instead of wiring stream.messages yourself
  • a custom server endpoint that can add provider-specific behavior next to your deployed graph
  • structured generative UI rendered from a constrained component registry
CopilotKit for LangGraph also documents generative UI, human in the loop (HITL), and shared state on top of the same middleware and clients.
For CopilotKit-specific APIs, UI patterns, and runtime configuration, see the CopilotKit docs. For a Deep Agent walkthrough, see Deep Agents and CopilotKit in the CopilotKit docs.

How it works

At a high level, CopilotKit sits between your React app and the LangGraph deployment. The frontend sends conversation state to a custom /api/copilotkit route mounted alongside the graph API, that route forwards the request to LangGraph, and the response comes back with both assistant messages and any structured UI payloads your component registry can render.
  1. Deploy the graph as usual using LangSmith or using a LangGraph development server.
  2. Extend the deployment with an HTTP app that mounts a CopilotKit route next to the graph API.
  3. Wrap the frontend in CopilotKit and point it at that custom runtime URL.
  4. Register dynamic UI components and parse assistant responses into those components at render time.

What you get on the Python server

The copilotkit and related packages bridge a LangGraph deployment and CopilotKit clients. CopilotKitMiddleware is the same middleware for create_deep_agent and for a graph from create_agent when you add it to the middleware list. For a create_agent graph with CopilotKitState and a FastAPI bridge, follow the Python main.py example below. Structured generative UI (for example useAgentContext and an output_schema from the client) needs extra middleware that maps Copilot state to a structured output strategy, as in the expandable src/middleware.py example in the same section. Mounting app on the http key in langgraph.json follows the usual LangGraph or LangSmith deployment so one process serves the graph and the same FastAPI app to the CopilotKit client.

Installation

For the backend endpoint:
The middleware package sits alongside the Deep Agents stack. Install it with your chat model package (this example uses OpenAI):
For the frontend app:

Use CopilotKit with a Deep Agent

Add CopilotKitMiddleware to the middleware list you pass to create_deep_agent. The middleware lets CopilotKit route frontend tool calls and align chat state with your graph. Keep any other middleware you configure in the same list. The compiled graph is then ready to plug into a CopilotKit- or AG-UI–aware process (for example, the FastAPI pattern below) or a guide such as Deep Agents and CopilotKit in the CopilotKit documentation.

Extend the LangGraph deployment with a custom endpoint

The key idea is that the LangGraph deployment does not only serve graphs. It can also load an HTTP app, which lets you mount extra routes next to the deployment itself. In langgraph.json, point http.app at your custom app entrypoint:
In Python, create a FastAPI app and expose the LangGraph agent through CopilotKit’s AG-UI bridge:
main.py
This custom app is the important extension point: it mounts a CopilotKit-aware runtime without replacing the underlying LangGraph deployment. In Python, the equivalent work happens in middleware: normalize the CopilotKit context and forward the output_schema from useAgentContext(...) into the model’s structured output configuration.
src/middleware.py
The result is a clean separation of concerns:
  • LangGraph still owns graph execution and persistence
  • CopilotKit owns the chat-facing runtime contract
  • your custom endpoint glues them together inside one deployment
Point your CopilotKit runtimeUrl at the route the FastAPI (or other) app exposes, not only the raw graph REST surface, when you use the CopilotKit runtime adapter. Follow the CopilotKit documentation for LangGraphHttpAgent or LangGraphAgent in the Node CopilotRuntime; the Python graph and middleware still define tool behavior and agent logic. :::

Structure the frontend app

On the frontend, wrap your app in CopilotKit and point it at the custom runtime URL:
There are two important pieces here:
  • runtimeUrl="/api/copilotkit" sends the chat to your custom backend route rather than directly to the raw LangGraph API
  • useAgentContext(...) sends the UI schema to the agent so the model knows what structured output format it should produce

Register the dynamic components

The component registry lives in useChatKit(). This is where you define the set of components the agent is allowed to emit, such as cards, rows, columns, charts, code blocks, and buttons.
This registry becomes the contract between the agent and the UI. The model is not generating arbitrary JSX. It is generating structured data that must validate against the components and props you exposed.

Render assistant messages as dynamic UI

Once the assistant response arrives, the custom message renderer decides how to display it. In this example:
  • assistant messages are parsed as structured JSON against the UI kit schema
  • valid structured output is rendered as real React components
  • user messages are rendered as ordinary chat bubbles
This renderer pattern is what makes the integration feel native:
  • CopilotKit handles chat state and transport
  • the custom renderer decides how assistant payloads become UI
  • Hashbrown turns validated structured data into concrete React elements

Resources

Best practices

  • Keep the custom endpoint thin: use it to adapt CopilotKit to your graph deployment, not to duplicate business logic already inside the graph
  • Send the schema explicitly: useAgentContext should describe the UI contract every time the page mounts
  • Register a constrained component set: expose only the components and props you actually want the model to use
  • Treat rendering as a parsing step: parse assistant content against your schema before rendering it
  • Keep user messages plain: only assistant messages need the structured renderer; user messages can stay normal chat bubbles