---
title: "Module Setup"
framework: react
version: "2.1.2"
---

# Module Setup

The AI assistant is an opt-in module. This page covers the plumbing every integration needs: registering the module, providing an adapter, showing the panel, and persisting conversation state. It is provider-agnostic - connecting a specific LLM is covered in [LLM Adapter](https://www.ag-grid.com/studio/react/ai-adapter/).

## Register the Module

The assistant lives in `AgStudioAiModule`. Register it before creating a Studio instance.

```ts
import { AgStudioAiModule, AgStudioModuleRegistry } from 'ag-studio';

AgStudioModuleRegistry.registerModules([AgStudioAiModule]);
```

> **Note**
>
> The AI module requires an **AG Studio Pro with AI** licence. It will not activate without a valid key.

## Provide an Adapter

The `ai` property accepts your `AgAiAssistant` adapter - the connection to your LLM. It is marked `@initial`: set it at construction time; it cannot be changed later.

```jsx
const ai = myAdapter;

<AgStudio ai={ai} />
```

The panel appears automatically once an adapter is set. See [LLM Adapter](https://www.ag-grid.com/studio/react/ai-adapter/) for how to implement `AgAiAssistant`.

## Show or Hide the Panel

The panel is visible by default. Control its initial visibility through `initialState`:

```jsx
const ai = myAdapter;
const initialState = useMemo(() => { 
	return {
        pages: [{ id: 'main', widgets: {}, widgetLayout: {} }],
        selectedPageId: 'main',
        panels: {
            ai: {
                collapsed: false,
            },
        },
    };
}, []);

<AgStudio
    ai={ai}
    initialState={initialState}
/>
```

Set `collapsed: true` to start with the panel hidden. Users can toggle it from the toolbar at any time.

## Persist Conversation State

Conversation state is part of Studio state. `getState()` includes an `ai` key holding the full `AgAiAssistantState` - threads, conversations, exchanges, and artifacts - and `setState()` restores it.

```ts
const state = studioApi.getState();
localStorage.setItem('myReport', JSON.stringify(state));

const saved = JSON.parse(localStorage.getItem('myReport')!);
studioApi.setState(saved);
```

To restore conversations at construction time, pass saved state under the `ai` key of `initialState`:

```jsx
const ai = myAdapter;
const initialState = useMemo(() => { 
	return {
        pages: [{ id: 'main', widgets: {}, widgetLayout: {} }],
        selectedPageId: 'main',
        ai: savedAiState,
    };
}, []);

<AgStudio
    ai={ai}
    initialState={initialState}
/>
```

The example below is constructed this way: its `initialState.ai` holds a saved conversation, so the AI panel opens with that chat history already in place rather than an empty thread.

#### Persisted Conversation

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgStudio, AgStudioRef } from "ag-studio-react";
import { openaiAdapter } from "./shared/openaiAdapter.tsx";
import {
  AgAiAssistant,
  AgDataEngine,
  AgDataSourcesDefinition,
  AgReportState,
  AgStudioAiModule,
  AgStudioApi,
  AgStudioMode,
  AgStudioModuleRegistry,
  AgStudioProperties,
} from "ag-studio";
import { getMainDemoData } from "./data.tsx";
import { exampleAiState } from "./exampleAiState.tsx";

AgStudioModuleRegistry.registerModules([AgStudioAiModule]);

export const AI_API_URL = "https://ai-api.ag-grid.com/api/openai/v1";

export const AI_API_TOKEN = "";

const StudioExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const studioStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
  const [data, setData] = useState<AgDataSource>(
    getMainDemoData("https://www.ag-grid.com/studio/example-assets"),
  );
  const initialState = useMemo<AgReportState>(() => {
    return {
      pages: [{ id: "main", widgets: {}, widgetLayout: {} }],
      selectedPageId: "main",
      panels: {
        filters: { collapsed: true },
        edit: { collapsed: true },
        data: { collapsed: true },
      },
      ai: exampleAiState,
    };
  }, []);
  const ai = useMemo<AgAiAssistant>(() => {
    return openaiAdapter({
      endpoint: AI_API_URL,
      key: AI_API_TOKEN,
    });
  }, []);

  return (
    <div style={containerStyle}>
      <div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
        <AgStudio
          style={studioStyle}
          className="my-studio-container"
          data={data}
          mode={"edit"}
          initialState={initialState}
          ai={ai}
        />
      </div>
    </div>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <StudioExample />
  </StrictMode>,
);
```

[Live example: Persisted Conversation](https://www.ag-grid.com/studio/examples/ai-configuration/ai-persistence-example/reactFunctionalTs/)

## Next Steps

- [LLM Adapter](https://www.ag-grid.com/studio/react/ai-adapter/) - Connect the assistant to your LLM.
- [Default Agents](https://www.ag-grid.com/studio/react/ai-ax/) - The agents and tools you get out of the box.
