*   [](/v0.2/)
*   [How-to guides](/v0.2/docs/how_to/)
*   How to build an LLM generated UI

How to build an LLM generated UI
================================

This guide will walk through some high level concepts and code snippets for building generative UI's using LangChain.js. To see the full code for generative UI, [click here to visit our official LangChain Next.js template](https://github.com/langchain-ai/langchain-nextjs-template/blob/main/app/generative_ui/README.md).

The sample implements a tool calling agent, which outputs an interactive UI element when streaming intermediate outputs of tool calls to the client.

We introduce two utilities which wraps the AI SDK to make it easier to yield React elements inside runnables and tool calls: [`createRunnableUI`](https://github.com/langchain-ai/langchain-nextjs-template/blob/7f764d558682214d50b064f4293667123a31e6fe/app/generative_ui/utils/server.tsx#L89) and [`streamRunnableUI`](https://github.com/langchain-ai/langchain-nextjs-template/blob/7f764d558682214d50b064f4293667123a31e6fe/app/generative_ui/utils/server.tsx#L126).

*   The `streamRunnableUI` executes the provided Runnable with `streamEvents` method and sends every `stream` event to the client via the React Server Components stream.
*   The `createRunnableUI` wraps the `createStreamableUI` function from AI SDK to properly hook into the Runnable event stream.

The usage is then as follows:

    "use server";const tool = new DynamicStructuredTool({  // ...  func: async (input, config) => {    // create a new streamable UI and wire it up to the streamEvents    const stream = createRunnableUI(config);    stream.update(<div>Searching...</div>);    const result = await images(input);    // update the UI element with the rendered results    stream.done(      <Images        images={result.images_results          .map((image) => image.thumbnail)          .slice(0, input.limit)}      />    );    return `[Returned ${result.images_results.length} images]`;  },});// add LLM, prompt, etc...const tools = [tool];export const agentExecutor = new AgentExecutor({  agent: createToolCallingAgent({ llm, tools, prompt }),  tools,});

    async function agent(inputs: { input: string }) {  "use server";  return streamRunnableUI(agentExecutor, inputs);}export const EndpointsContext = exposeEndpoints({ agent });

In order to ensure all of the client components are included in the bundle, we need to wrap all of the Server Actions into `exposeEndpoints` method. These endpoints will be accessible from the client via the Context API, seen in the `useActions` hook.

    "use client";import type { EndpointsContext } from "./agent";export default function Page() {  const actions = useActions<typeof EndpointsContext>();  const [node, setNode] = useState();  return (    <div>      {node}      <button        onClick={async () => {          setNode(await actions.agent({ input: "cats" }));        }}      >        Get images of cats      </button>    </div>  );}

* * *

#### Was this page helpful?

  

#### You can also 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

How to run custom functions

](/v0.2/docs/how_to/functions)[

Next

How to construct knowledge graphs

](/v0.2/docs/how_to/graph_constructing)