@pillar-ai/react
v0.2.0
Published
React SDK for Pillar product copilot — AI assistant for SaaS and web apps
Readme
@pillar-ai/react
React bindings for Pillar, the open-source product copilot SDK. Add an AI assistant to your React or Next.js app that executes tasks using your UI. GitHub · Docs
What is Pillar?
Pillar is a product copilot for SaaS and web apps. Users say what they want, and Pillar uses your UI to make it happen.
A CRM user could ask:
"Close the Walmart deal as won and notify implementation"
An analytics user could ask:
"Add a weekly signups chart to my dashboard"
Pillar understands the intent, builds a plan, and executes it client-side with the user's session. No proxy servers, no token forwarding.
Documentation
Full docs · React quickstart · API reference
Installation
npm install @pillar-ai/react
# or
pnpm add @pillar-ai/react
# or
yarn add @pillar-ai/reactQuick start
1. Get your agent slug
Sign up at app.trypillar.com and grab your agent slug from the dashboard.
2. Add the provider
Wrap your app with PillarProvider:
import { PillarProvider } from "@pillar-ai/react";
function App() {
return (
<PillarProvider agentSlug="your-agent-slug">
<YourApp />
</PillarProvider>
);
}For Next.js App Router, create a client wrapper:
// providers/PillarSDKProvider.tsx
"use client";
import { PillarProvider } from "@pillar-ai/react";
export function PillarSDKProvider({ children }: { children: React.ReactNode }) {
return (
<PillarProvider agentSlug="your-agent-slug">{children}</PillarProvider>
);
}// app/layout.tsx
import { PillarSDKProvider } from "@/providers/PillarSDKProvider";
export default function RootLayout({ children }) {
return (
<html>
<body>
<PillarSDKProvider>{children}</PillarSDKProvider>
</body>
</html>
);
}3. Define your first tool
Tools tell Pillar what your app can do. Define them with the usePillarTool hook:
import { usePillarTool } from "@pillar-ai/react";
import { useRouter } from "next/navigation";
export function usePillarTools() {
const router = useRouter();
usePillarTool({
name: "open_settings",
type: "navigate",
description: "Navigate to the settings page",
examples: ["open settings", "go to settings"],
autoRun: true,
execute: () => router.push("/settings"),
});
}Call usePillarTools() from any component inside PillarProvider (e.g. your layout).
Defining tools
Tools are the building blocks. When a user makes a request, Pillar matches intent to tools and executes them.
Single tool
usePillarTool({
name: "open_dashboard",
type: "navigate",
description: "Navigate to the main dashboard",
examples: ["go to dashboard", "show me the dashboard"],
execute: () => router.push("/dashboard"),
});Tool with input schema
Pillar extracts parameters from the user's request:
usePillarTool({
name: "view_user_profile",
type: "navigate",
description: "View a specific user's profile page",
inputSchema: {
type: "object",
properties: {
userId: { type: "string", description: "The user ID to view" },
},
required: ["userId"],
},
execute: ({ userId }) => router.push(`/users/${userId}`),
});Multiple tools at once
usePillarTool([
{
name: "open_billing",
type: "navigate",
description: "Navigate to billing and subscription settings",
examples: ["go to billing", "view my subscription"],
execute: () => router.push("/settings/billing"),
},
{
name: "open_team",
type: "navigate",
description: "Navigate to team management page",
examples: ["manage team", "invite team members"],
execute: () => router.push("/settings/team"),
},
]);Tool types
| Type | Use case |
| --------------- | ----------------------------------------- |
| navigate | Navigate to a page or view |
| trigger_tool | Run a function (export, toggle, API call) |
| query | Return data to the assistant |
| external_link | Open an external URL |
| copy_text | Copy text to clipboard |
See Setting Up Tools for the full guide.
Hooks
usePillar
Access SDK state and methods:
import { usePillar } from "@pillar-ai/react";
function MyComponent() {
const {
pillar, // SDK instance
isReady, // Whether SDK is initialized
isPanelOpen, // Panel open state
open, // Open the panel
close, // Close the panel
toggle, // Toggle the panel
navigate, // Navigate to a view
setTheme, // Update theme at runtime
on, // Subscribe to events
} = usePillar();
if (!isReady) return <div>Loading...</div>;
return <button onClick={() => open()}>Get Help</button>;
}useHelpPanel
Panel-specific controls:
import { useHelpPanel } from "@pillar-ai/react";
function HelpButton() {
const {
isOpen,
open,
close,
toggle,
openArticle,
openCategory,
openSearch,
openChat,
} = useHelpPanel();
return (
<div>
<button onClick={toggle}>{isOpen ? "Close" : "Help"}</button>
<button onClick={openChat}>Ask co-pilot</button>
</div>
);
}| Method | Description |
| -------------------- | ------------------------------- |
| open(options?) | Open the panel |
| close() | Close the panel |
| toggle() | Toggle open/closed |
| openArticle(slug) | Open a specific article |
| openCategory(slug) | Open a category view |
| openSearch(query?) | Open search with optional query |
| openChat() | Open the co-pilot chat view |
Components
PillarProvider
The root component. Initializes and configures the SDK.
| Prop | Type | Required | Description |
| ------------ | ---------------- | -------- | ------------------------------------------ |
| agentSlug | string | Yes | Your agent slug from app.trypillar.com |
| config | object | No | SDK configuration (panel, theme, triggers) |
| onTask | (task) => void | No | Generic handler for dynamic tools |
<PillarProvider
agentSlug="your-agent-slug"
config={{
panel: { position: "right", mode: "push", width: 400 },
theme: { mode: "auto", colors: { primary: "#2563eb" } },
}}
>
{children}
</PillarProvider>PillarPanel
For custom panel placement, set panel.container to 'manual' and render PillarPanel where you want it:
import { PillarProvider, PillarPanel } from "@pillar-ai/react";
function App() {
return (
<PillarProvider
agentSlug="your-agent-slug"
config={{ panel: { container: "manual" } }}
>
<div className="layout">
<main>Your content</main>
<PillarPanel className="sidebar-panel" />
</div>
</PillarProvider>
);
}Generic task handler
For dynamic or backend-triggered tools, use the onTask prop on PillarProvider. For most cases, prefer usePillarTool which co-locates the handler with the tool definition.
<PillarProvider
agentSlug="your-agent-slug"
onTask={(task) => {
if (task.name.startsWith("nav_")) {
router.push(task.data.path);
return;
}
switch (task.name) {
case "notification":
showNotification(task.data.message);
break;
case "refresh_data":
queryClient.invalidateQueries();
break;
}
}}
>
{children}
</PillarProvider>Inline UI with render
For inline_ui tools, use the render prop to display custom React components in the chat. The AI agent provides data directly to the render component — no execute function needed:
import { usePillarTool, type ToolRenderProps } from "@pillar-ai/react";
function InviteCard({ data }: ToolRenderProps<{ emails: string[]; teamName: string }>) {
return (
<div className="p-4 border rounded">
<p>Invite {data.emails?.length || 0} members to {data.teamName}</p>
</div>
);
}
usePillarTool({
name: "invite_members",
description: "Invite team members via email",
type: "inline_ui",
inputSchema: {
type: "object",
properties: {
emails: { type: "array", items: { type: "string" } },
teamName: { type: "string" },
},
},
render: InviteCard,
});The render component receives:
data— Data provided by the AI agent (extracted from the conversation viainputSchema)onStateChange?(state, message?)— optional loading/success/error states
Exports
| Export | Description |
| ---------------- | ----------------------------------------- |
| PillarProvider | Context provider that initializes the SDK |
| PillarPanel | Component for custom panel placement |
| usePillar | Hook for SDK access and panel control |
| useHelpPanel | Hook for panel-specific controls |
| usePillarTool | Hook to register tools |
Related packages
| Package | Description | | ----------------------------------------------------------- | ------------------- | | @pillar-ai/sdk | Core vanilla JS SDK | | @pillar-ai/vue | Vue 3 bindings | | @pillar-ai/svelte | Svelte bindings |
Requirements
- React 17+ or React 19+
- React DOM 17+ or React DOM 19+
License
MIT
