A comprehensive React/Next.js library for building AI agent interfaces with chat, canvas, and interactive components integrated with VTEX Raccoon.
npm install @vtex/agentic-uiA comprehensive React/Next.js library for building AI agent interfaces with chat, canvas, and interactive components integrated with VTEX Raccoon.
@vtex/agentic-ui provides a complete toolkit for creating an AI agent user interfaces within the VTEX ecosystem. It offers a standardized way to build conversational interfaces, display rich content, manage state, and integrate seamlessly with VTEX Admin applications.
- React Components - Pre-built components for chat, canvas, messages, threads, and tools
- Composable Architecture - MessageComposer and other components use composition pattern for maximum flexibility
- Agent Integration System - useAgentPlatform hook and createAgent() function for type-safe agent configuration
- UI Protocol - Standardized communication layer between frontend and backend with automatic authentication
- SSE Integration - Server-Sent Events with automatic reconnection, backoff, and connection management
- State Management - Built-in hooks and utilities powered by Jotai
- VTEX Admin Integration - Drop-in solution for admin application development with route-based agent loading
- Tool Registry - Extensible system for custom tool rendering with canvas and inline modes
- TypeScript Support - Full type safety across the entire library with Zod schema validation
``bash`
pnpm add @vtex/agentic-ui@latest
This package requires the following peer dependencies:
- react >= 18.3react-dom
- >= 18.3next
- >= 14@vtex/shoreline
- (latest)@vtex/raccoon-next
- (latest)@vtex/raccoon-analytics
- (latest)@tanstack/react-table
- ^8.21.3typescript
- >= 5
| Guide | Description |
|-------|-------------|
| Components | Complete reference for all React components, hooks, and utilities |
| UI Protocol | Communication protocol specification and data fetching hooks |
| Server-Sent Events (SSE) | Real-time communication utilities with automatic reconnection |
| Admin Integration | Integration solution for VTEX Admin applications |
| Migration Guide | Step-by-step guide for migrating from 0.2.4 to 0.4.1 |
This example demonstrates how to set up a Next.js application with Raccoon and agentic-ui.
Create your _app.tsx file with the necessary providers:
`typescript
import type { AppProps } from "next/app";
import { useRouter } from "next/router";
import { connect, bootstrap, useAdmin } from "@vtex/raccoon-next";
import {
ChatProvider,
useAgentPlatform,
AgenticUIProvider,
} from "@vtex/agentic-ui";
import { IntlProvider } from "react-intl";
// Import required styles
import "@vtex/shoreline/css";
import "@vtex/agentic-ui/css";
import { agents } from "../agents";
import { messages } from "../messages";
// Initialize Raccoon connection
connect();
function AppContent({ Component, pageProps }: AppProps) {
const router = useRouter();
// Load agent configuration based on current route
const { isLoading, agent, error } = useAgentPlatform({
agents,
pathname: router.asPath,
});
const { locale = "en-US", account, token } = useAdmin();
if (isLoading) {
return
if (error || !agent) {
return
return (
locale={locale}
account={account}
token={token}
>
messages={
messages[locale as keyof typeof messages] ?? messages["en-US"]
}
defaultLocale="en-US"
>
);
}
function App(props: AppProps) {
return
}
export default bootstrap(App);
`
Create a page component that renders the initial chat interface at pages/app/[app]/index.tsx:
`typescript
import { useState } from "react";
import { useIntl } from "react-intl";
import { useNavigation } from "@vtex/raccoon-next";
import {
AgentHome,
ChatLayout,
MessageComposer,
MessageComposerInput,
MessageComposerTextarea,
MessageComposerControls,
MessageComposerSendButton,
MessageComposerSuggestions,
Suggestion,
useAgenticUI,
useChatContext,
useResetAtoms,
useStatus,
} from "@vtex/agentic-ui";
export default function AgenticPage() {
const { reset } = useResetAtoms();
const { agent } = useAgenticUI();
const { formatMessage } = useIntl();
const { stop, sendMessage, appSlug } = useChatContext();
const { loading } = useStatus();
const { navigate } = useNavigation();
const [input, setInput] = useState("");
const basePath = /app/${appSlug};
async function handleSendMessage() {
const userContent = input.trim();
setInput("");
try {
const { threadId } = await sendMessage({
inputs: [{ type: "text", text: userContent }],
});
navigate(${basePath}/${threadId});
} catch (error) {
console.error(error);
}
}
return (
onThreadClick={(threadId) => {
reset();
navigate(${basePath}/${threadId});`
}}
>
subtitle={formatMessage({ id: agent?.ui.subtitle })}
name={formatMessage({ id: agent?.ui.name })}
/>
setInput={setInput}
isLoading={loading}
isEmpty
onSend={handleSendMessage}
onStop={stop}
>
{agent?.ui.promptSuggestions.map((prompt) => (
title={formatMessage({ id: prompt.title })}
description={formatMessage({ id: prompt.description })}
promptText={formatMessage({ id: prompt.promptText })}
requiresUrl={prompt.requiresUrl}
requiresImage={prompt.requiresImage}
/>
))}
);
}
Create a page for ongoing conversations at pages/app/[app]/[threadId]/index.tsx:
`typescript
import { useEffect, useState } from "react";
import { useRouter } from "next/router";
import { useNavigation } from "@vtex/raccoon-next";
import {
ChatLayout,
MessageComposer,
MessageComposerInput,
MessageComposerTextarea,
MessageComposerControls,
MessageComposerSendButton,
MessageComposerFeedback,
MessagesArea,
useChatContext,
useMessageIds,
useResetAtoms,
useStatus,
useThreadId,
} from "@vtex/agentic-ui";
export default function ThreadPage() {
const { stop, sendMessage, appSlug } = useChatContext();
const { navigate } = useNavigation();
const router = useRouter();
const { threadId, setThreadId } = useThreadId();
const { reset } = useResetAtoms();
const { loading } = useStatus();
const { messageIds } = useMessageIds();
const [input, setInput] = useState("");
const basePath = /app/${appSlug};
async function handleSendMessage() {
const userContent = input.trim();
setInput("");
try {
await sendMessage({ inputs: [{ type: "text", text: userContent }] });
} catch (error) {
console.error(error);
}
}
// Sync threadId from router query
useEffect(() => {
if (!router.query.threadId || Array.isArray(router.query.threadId)) return;
if (threadId === router.query.threadId) return;
setThreadId(router.query.threadId);
}, [router.query.threadId]);
return (
onNavigateBack={() => {
reset();
navigate(basePath);
}}
onThreadClick={(threadId) => {
reset();
navigate(${basePath}/${threadId});`
}}
>
error={null}
isLoading={loading}
/>
setInput={setInput}
isLoading={loading}
isEmpty={false}
onSend={handleSendMessage}
onStop={stop}
>
);
}
The useAgentPlatform hook automatically detects the agent based on the URL path, and the threadId parameter is used to load the specific conversation. The useThreadId hook manages the thread ID state and syncs with the router query parameter.
Agents are configured in your consuming application (not in the library). Create agent configuration files in your agents/ folder. For example, create agents/my-agent.ts:
`typescript
import { createAgent } from "@vtex/agentic-ui";
export default createAgent({
slug: "my-agent",
id: "MY_AGENT_ID",
apiUrl: process.env.NEXT_PUBLIC_MY_AGENT_BASE_URL ?? "",
routes: {
frontend: "/app/my-agent",
stream: "/api/agent/responses",
tasks: "/api/agent/tasks",
},
settings: {
enableFeedback: true,
enableImageProcessing: false,
},
ui: {
name: "My Agent",
title: "My Agent Assistant",
subtitle: "Help with custom operations",
promptSuggestions: [
{
title: "Get Started",
description: "Learn what I can do",
promptText: "What operations can you help me with?",
},
{
title: "Analyze Data",
description: "Process and analyze your data",
promptText: "Help me analyze my sales data",
},
],
},
});
`
Then create agents/index.ts to export all agents as an array:
`typescript
import myAgent from "./my-agent";
export const agents = [myAgent];
`
Import and use this array in your _app.tsx (as shown in Step 1). The useAgentPlatform hook will match the current route to the appropriate agent configuration. For more details, see Admin Integration documentation.
`bash`
pnpm dev
Your agent interface is now ready! Users can:
- Start new conversations from the home page
- Continue existing conversations via thread pages
- Interact with tools and view rich content in the canvas
- Navigate between different threads seamlessly
- GitHub Repository
- Report Issues
- Shoreline Design System
- Raccoon Documentation
When developing the agentic-ui package, changes will automatically reflect in dependent applications like @ui/. Start the development mode with:
`bash`
pnpm install
pnpm dev
This enables hot-reload, allowing you to see your changes immediately in any application that depends on this package.
To build the package for production:
`bash`
pnpm install
pnpm build
This compiles the TypeScript code and generates the distribution files in the dist/ directory.
To publish a new version to npm, follow these steps (be sure to be in the root of the repository):
1. Bump the version (choose patch, minor, or major):`
bash`
pnpm lerna version patch --force-publish
# or
pnpm lerna version minor --force-publish
2. Publish to npm:
`bash`
pnpm lerna publish from-git
The version bump will create a git tag and update the package.json`. Publishing from git ensures only tagged releases are published.