# Chat History for LangGraph Cloud
URL: /docs/cloud/persistence/langgraph

Integrate cloud persistence and thread management with LangGraph Cloud.

Overview \[#overview]

assistant-cloud provides thread management and persistent chat history for applications built with [LangGraph Cloud](https://langchain-ai.github.io/langgraph/cloud/). This guide shows you how to integrate cloud persistence into your LangGraph application.

Prerequisites \[#prerequisites]

<Callout type="info">
  You need an assistant-cloud account to follow this guide. [Sign up
  here](https://cloud.assistant-ui.com/) to get started.
</Callout>

Setup Guide \[#setup-guide]

<Steps>
  <Step>
    Create a Cloud Project \[#create-a-cloud-project]

    Create a new project in the [assistant-cloud dashboard](https://cloud.assistant-ui.com/) and from the settings page, copy:

    * **Frontend API URL**: `https://proj-[ID].assistant-api.com`
    * **API Key**: For server-side operations
  </Step>

  <Step>
    Configure Environment Variables \[#configure-environment-variables]

    Add the following environment variables to your project:

    ```bash title=".env.local"
    # Frontend API URL from your cloud project settings
    NEXT_PUBLIC_ASSISTANT_BASE_URL=https://proj-[YOUR-ID].assistant-api.com

    # API key for server-side operations
    ASSISTANT_API_KEY=your-api-key-here
    ```
  </Step>

  <Step>
    Install Dependencies \[#install-dependencies]

    Install the required packages:

    <InstallCommand npm={["@assistant-ui/react", "@assistant-ui/react-langgraph"]} />
  </Step>

  <Step>
    Create the Runtime Provider \[#create-the-runtime-provider]

    Create a runtime provider that integrates LangGraph with assistant-cloud. Choose between anonymous mode for demos/prototypes or authenticated mode for production:

    <Tabs items={["Anonymous", "Authenticated (Clerk)"]}>
      <Tab value="Anonymous">
        ```tsx title="app/chat/runtime-provider.tsx"
        "use client";

        import {
          AssistantCloud,
          AssistantRuntimeProvider,
        } from "@assistant-ui/react";
        import { useLangGraphRuntime } from "@assistant-ui/react-langgraph";
        import { createThread, getThreadState, sendMessage } from "@/lib/chatApi";
        import { LangChainMessage } from "@assistant-ui/react-langgraph";
        import { useMemo } from "react";

        export function MyRuntimeProvider({
          children,
        }: Readonly<{
          children: React.ReactNode;
        }>) {
          const cloud = useMemo(
            () =>
              new AssistantCloud({
                baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL!,
                anonymous: true, // Creates browser session-based user ID
              }),
            [],
          );

          const runtime = useLangGraphRuntime({
            cloud,
            stream: async function* (messages, { initialize }) {
              const { externalId } = await initialize();
              if (!externalId) throw new Error("Thread not found");

              return sendMessage({
                threadId: externalId,
                messages,
              });
            },
            create: async () => {
              const { thread_id } = await createThread();
              return { externalId: thread_id };
            },
            load: async (externalId) => {
              const state = await getThreadState(externalId);
              return {
                messages:
                  (state.values as { messages?: LangChainMessage[] }).messages ?? [],
              };
            },
          });

          return (
            <AssistantRuntimeProvider runtime={runtime}>
              {children}
            </AssistantRuntimeProvider>
          );
        }
        ```
      </Tab>

      <Tab value="Authenticated (Clerk)">
        ```tsx title="app/chat/runtime-provider.tsx"
        "use client";

        import {
          AssistantCloud,
          AssistantRuntimeProvider,
        } from "@assistant-ui/react";
        import { useLangGraphRuntime } from "@assistant-ui/react-langgraph";
        import { createThread, getThreadState, sendMessage } from "@/lib/chatApi";
        import { LangChainMessage } from "@assistant-ui/react-langgraph";
        import { useAuth } from "@clerk/nextjs";
        import { useMemo } from "react";

        export function MyRuntimeProvider({
          children,
        }: Readonly<{
          children: React.ReactNode;
        }>) {
          const { getToken } = useAuth();

          const cloud = useMemo(
            () =>
              new AssistantCloud({
                baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL!,
                authToken: async () => getToken({ template: "assistant-ui" }),
              }),
            [getToken],
          );

          const runtime = useLangGraphRuntime({
            cloud,
            stream: async function* (messages, { initialize }) {
              const { externalId } = await initialize();
              if (!externalId) throw new Error("Thread not found");

              return sendMessage({
                threadId: externalId,
                messages,
              });
            },
            create: async () => {
              const { thread_id } = await createThread();
              return { externalId: thread_id };
            },
            load: async (externalId) => {
              const state = await getThreadState(externalId);
              return {
                messages:
                  (state.values as { messages?: LangChainMessage[] }).messages ?? [],
              };
            },
          });

          return (
            <AssistantRuntimeProvider runtime={runtime}>
              {children}
            </AssistantRuntimeProvider>
          );
        }
        ```

        <Callout type="info">
          For Clerk authentication, configure the `"assistant-ui"` token template in
          your Clerk dashboard.
        </Callout>
      </Tab>
    </Tabs>

    <Callout type="info">
      The `useLangGraphRuntime` hook now directly accepts `cloud`, `create`, and `load` parameters for simplified thread management. The runtime handles thread lifecycle internally.
    </Callout>
  </Step>

  <Step>
    Add Thread UI Components \[#add-thread-ui-components]

    Install the thread list component:

    <Tabs items={["assistant-ui", "shadcn (namespace)", "shadcn"]}>
      <Tab>
        ```sh
        npx assistant-ui@latest add thread-list
        ```
      </Tab>

      <Tab>
        ```sh
        npx shadcn@latest add https://r.assistant-ui.com/thread-list.json
        ```
      </Tab>

      <Tab>
        ```sh
        npx shadcn@latest add https://r.assistant-ui.com/thread-list.json
        ```
      </Tab>
    </Tabs>

    Then add it to your application layout:

    ```tsx title="app/chat/page.tsx"
    import { Thread } from "@/components/assistant-ui/thread";
    import { ThreadList } from "@/components/assistant-ui/thread-list";

    export default function ChatPage() {
      return (
        <div className="grid h-dvh grid-cols-[250px_1fr] gap-x-2">
          <ThreadList />
          <Thread />
        </div>
      );
    }
    ```
  </Step>
</Steps>

Authentication \[#authentication]

The examples above show two authentication modes:

* **Anonymous**: Suitable for demos and prototypes. Creates a browser session-based user ID.
* **Authenticated**: For production use with user accounts. The authenticated example uses [Clerk](https://clerk.com/), but you can integrate any auth provider.

For other authentication providers or custom implementations, see the [Cloud Authorization](/docs/cloud/authorization) guide.

Next Steps \[#next-steps]

* Learn about [LangGraph runtime setup](/docs/runtimes/langgraph) for your application
* Explore [ThreadListRuntime](/docs/api-reference/runtimes/thread-list-runtime) for advanced thread management
* Check out the [LangGraph example](https://github.com/assistant-ui/assistant-ui/tree/main/examples/with-langgraph) on GitHub
