`createAI` creates a React context provider for an application's AI state, UI state, and server actions. Define their initial values together, then wrap the application layout with the returned provider. Components beneath it can access state and registered actions without passing them through every component. section 4.2.2
In a chat application, the pieces have distinct jobs:
- AI state holds conversation history used by server actions. An action can read and update it with `getMutableAIState`. section 4.2.3
- UI state holds what the interface displays, such as messages. Client components access it with `useUIState`; `useAIState` reads AI state. section 4.2.3
- `useActions` exposes actions registered with `createAI` to components inside the provider. Register actions there rather than importing them directly into client components. section 4.3.4
Wire a chat provider
Define `AI = createAI({ actions: { continueConversation }, initialAIState: [], initialUIState: { messages: [] } })`, then render `<AI>{children}</AI>` in the application layout. A chat component can call `continueConversation` through `useActions` and add the returned display message to UI state. The server action reads conversation history with `getMutableAIState` and streams a React component with `streamUI`. section 4.2.3
The same wiring supports a different response format: register `generateProductList` instead of the chat action, then render its structured product results in the UI. For persistence, `onSetAIState` can save completed AI state, and a previously saved state can supply `initialAIState`. TypeScript can check registered action types. section 4.3.4 section 4.2.2
Listing 4.7 Managing the conversation history with getMutableAIState
export async function
continueConversation(input, provider, model) {
'use server';
const supportedModel = getSupportedModel(provider, model);
const history = getMutableAIState(); #1
const result = await streamUI({. #2
model: supportedModel,
messages: [...history.get(), { role: 'user', content: input }], #3
text: ({ content, done }) => {
if (done) {
history.done([...history.get(),
{ role: 'assistant', content: input }]); #4
}
return <ChatBubble role="assistant" text={content}
className={`mr-auto border-none`} />;
},
});
return {
id: generateId(),
role: 'assistant',
display: result.value, #5
};
}
export const AI = createAI({. #6
actions: {
continueConversation,
},
initialAIState: [],
initialUIState: {
messages: [],
},
});
See the chat action and its `createAI` configuration together: conversation history is updated on the server while the action returns a display value for the UI. section 4.2.3
