@cntyclub/agent-react
v0.14.2
Published
Embeddable AI agent chat widget for Country Club dashboards — floating button, popup panel, fullscreen Agent Mode, MCP tool approvals, and paginated result tables. Built exclusively on @cntyclub/ui-react.
Readme
@cntyclub/agent-react
Embeddable AI agent chat widget for Country Club dashboards — the frontend for the
backend's Agent Mode (agent_mode Django app). A floating button opens a popup
chat panel (desktop) or fullscreen chat (mobile); an Agent Mode button expands the
popup to fullscreen. The agent can call MCP tools on the user's behalf: read-only tools
run automatically, write tools require in-chat user approval. Tabular tool results are
rendered as paginated, searchable tables.
Built exclusively on @cntyclub/ui-react —
no custom styles or components. Light/dark mode follows the host dashboard's theme
tokens automatically.
Install
pnpm add @cntyclub/agent-react @cntyclub/ui-reactRequirements:
- React 19+
- Tailwind CSS v4 with the UI kit stylesheet + sources configured:
@import "tailwindcss";
@import "@cntyclub/ui-react/styles.css";
@source "../node_modules/@cntyclub/ui-react/src";
@source "../node_modules/@cntyclub/agent-react/src";- An Agent Mode client ID, created in the Country Club office panel (Office → AI → Agent Mode → Create Agent). The client ID identifies the agent only; the backend resolves the MCP connector, model, and system prompt from it.
- The host page's origin must be on the agent's allowed domains list — other origins get a CORS error from the backend.
- A logged-in user: every request carries the user's Country Club JWT. Users who are not signed in cannot chat.
Usage
- Create the agent config file (
lib/agent/agent-config.ts):
import { defineAgentConfig } from "@cntyclub/agent-react";
import { getAccessToken } from "@/lib/api/tokens";
export const agentConfig = defineAgentConfig({
clientId: process.env.NEXT_PUBLIC_AGENT_CLIENT_ID!,
apiBaseUrl: process.env.NEXT_PUBLIC_API_URL!,
getAccessToken,
agentName: "Assistant",
suggestions: ["Show my target companies", "List my products"],
pages: [
{
tools: ["business_target_companies_list"],
route: "/dashboard/target-companies",
title: "Target Companies",
},
{
tools: ["business_companies_get"],
route: "/dashboard/company/:id",
title: "Company",
buildRoute: (args) => (args.id ? `/dashboard/company/${args.id}` : null),
},
],
});- Mount the widget inside your authenticated layout (client component):
"use client";
import { AgentWidget } from "@cntyclub/agent-react";
import { useRouter } from "next/navigation";
import { agentConfig } from "@/lib/agent/agent-config";
export function DashboardAgent() {
const router = useRouter();
return <AgentWidget config={{ ...agentConfig, navigate: (path) => router.push(path) }} />;
}pages + navigate power page-follow: in popup mode, when the agent uses a tool
that maps to a page, the host app navigates there while the chat shows the same data.
API schema (OpenAPI)
The backend publishes a dedicated, scoped OpenAPI document for Agent Mode:
- Schema:
GET {API_BASE}/agent-mode/schema/(YAML) - Swagger UI:
{API_BASE}/agent-mode/docs/
This repo vendors that document at api-spec/agent-mode-api.yaml
and generates TypeScript types from it into src/api/schema.ts (committed). All wire
types in src/types.ts derive from the generated schema, so the client cannot drift
from the backend contract silently.
Update workflow when the backend API changes:
curl https://api.country.club/agent-mode/schema/ -o api-spec/agent-mode-api.yaml
pnpm gen:api # regenerates src/api/schema.ts
pnpm typecheck # surfaces any breaking contract changes immediatelyConsumers can also import the full typed surface for their own tooling:
import type { AgentModePaths, AgentModeComponents, AgentModeOperations } from "@cntyclub/agent-react";Exports
AgentWidget— the complete widget (launcher + popup + fullscreen Agent Mode).AgentPanel— just the chat surface, for custom shells.useAgentChat(config)— headless chat state (messages, approvals, conversations).AgentApiClient— low-level API client.defineAgentConfig, plus all public types.
Development
pnpm install # uses a link: to the sibling UI kit repo for local dev
pnpm typecheck
pnpm build # tsup → dist/
./publish.sh # publish to npm (needs NPM_TOKEN in .env)