diff --git a/apps/docs/concepts/architecture.mdx b/apps/docs/concepts/architecture.mdx new file mode 100644 index 00000000..48246435 --- /dev/null +++ b/apps/docs/concepts/architecture.mdx @@ -0,0 +1,347 @@ +--- +title: Architecture +description: Understand how CopilotKit works under the hood +icon: "sitemap" +--- + +## Overview + +CopilotKit is thoughtfully architected to scale with you, your teams, and your product. The framework is designed with a clear separation of concerns, making it flexible, maintainable, and framework-agnostic. + +## High-Level Architecture + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Frontend Layer │ +│ ┌────────────────┐ ┌────────────────┐ │ +│ │ React Package │ │ Angular Package│ │ +│ │ - Components │ │ - Components │ │ +│ │ - Hooks │ │ - Services │ │ +│ │ - Providers │ │ - Directives │ │ +│ └────────┬───────┘ └────────┬───────┘ │ +│ │ │ │ +│ └───────────┬───────────────────┘ │ +│ │ │ +│ ┌───────────▼───────────┐ │ +│ │ Core Package │ │ +│ │ - CopilotKitCore │ │ +│ │ - Agent Management │ │ +│ │ - Tool Registry │ │ +│ │ - State Management │ │ +│ └───────────┬───────────┘ │ +└───────────────────────┼─────────────────────────────────────┘ + │ + │ WebSocket / HTTP + │ +┌───────────────────────▼─────────────────────────────────────┐ +│ Runtime Layer │ +│ ┌──────────────────────────────────────────────────────┐ │ +│ │ CopilotRuntime │ │ +│ │ - Request Handling │ │ +│ │ - Agent Execution │ │ +│ │ - Tool Orchestration │ │ +│ │ - Streaming Support │ │ +│ └──────────────────────────────────────────────────────┘ │ +│ │ +│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ +│ │ Agent 1 │ │ Agent 2 │ │ Agent N │ │ +│ │ (OpenAI) │ │ (Anthropic) │ │ (Custom) │ │ +│ └──────────────┘ └──────────────┘ └──────────────┘ │ +└─────────────────────────────────────────────────────────────┘ +``` + +## Core Components + +### 1. Core Package (`@copilotkitnext/core`) + +The core package is framework-agnostic and provides the foundational functionality: + +**CopilotKitCore** +- Central class that manages all CopilotKit functionality +- Handles agent registration and discovery +- Manages tool registry +- Coordinates communication with runtime + +**Agent Management** +- Abstract agent interface for different implementations +- Agent lifecycle management +- Message routing and state handling + +**Tool Registry** +- Centralized registry for frontend and backend tools +- Tool validation and schema management +- Tool execution coordination + +**State Management** +- Shared state between UI and agents +- State synchronization mechanisms +- Event-driven updates + +### 2. Framework Packages + +#### React Package (`@copilotkitnext/react`) + +Provides React-specific integrations: + +- **CopilotKitProvider**: React context provider +- **Components**: Pre-built UI components (CopilotChat, etc.) +- **Hooks**: React hooks for accessing CopilotKit functionality + - `useCopilotKit`: Access core instance + - `useAgent`: Interact with agents + - `useAgentContext`: Access shared state + - `useFrontendTool`: Register frontend tools + - `useHumanInTheLoop`: Define HITL interactions + - `useRenderToolCall`: Render generative UI + +#### Angular Package (`@copilotkitnext/angular`) + +Provides Angular-specific integrations: + +- **CopilotKitModule**: Angular module for setup +- **Components**: Angular components (copilot-chat, etc.) +- **Services**: Angular services for functionality + - `CopilotKitService`: Access core instance + - `AgentService`: Interact with agents + - `AgentContextService`: Access shared state + - `FrontendToolService`: Register frontend tools + - `HumanInTheLoopService`: Define HITL interactions + - `RenderToolCallService`: Render generative UI + +### 3. Runtime Package (`@copilotkitnext/runtime`) + +Server-side runtime for agent execution: + +**CopilotRuntime** +- HTTP/WebSocket endpoint handler +- Request validation and routing +- Response streaming +- Error handling + +**Agent Runners** +- Execute agent logic +- Manage agent state +- Handle tool calls +- Stream responses + +**Middleware** +- Authentication and authorization +- Rate limiting +- Logging and monitoring +- Custom middleware support + +## Communication Flow + +### 1. Frontend → Runtime + +``` +User Interaction + ↓ +Frontend Component + ↓ +CopilotKitCore + ↓ +HTTP/WebSocket Request + ↓ +CopilotRuntime + ↓ +Agent Execution +``` + +### 2. Tool Execution + +``` +Agent decides to use tool + ↓ +Runtime sends tool call request + ↓ +Frontend receives tool call + ↓ +Tool handler executes + ↓ +Result sent back to runtime + ↓ +Agent continues with result +``` + +### 3. State Synchronization + +``` +Agent updates state + ↓ +Runtime broadcasts state change + ↓ +Frontend receives update + ↓ +UI re-renders with new state + ↓ +User modifies state via UI + ↓ +Frontend sends state update + ↓ +Runtime updates agent state +``` + +## Key Design Principles + +### 1. Framework Agnostic Core + +The core package has no dependencies on React or Angular, making it: +- Reusable across frameworks +- Easier to test +- More maintainable +- Future-proof for new frameworks + +### 2. Type Safety + +Full TypeScript support throughout: +- Strongly typed APIs +- Schema validation with Zod +- Type inference for tools and state +- Compile-time error checking + +### 3. Extensibility + +Multiple extension points: +- Custom agents +- Custom tools +- Custom middleware +- Custom UI components + +### 4. Performance + +Optimized for performance: +- Streaming responses +- Efficient state updates +- Lazy loading +- Request batching + +### 5. Developer Experience + +Focus on great DX: +- Intuitive APIs +- Comprehensive documentation +- Clear error messages +- Helpful TypeScript types + +## Data Flow + +### Message Flow + +1. **User Input**: User sends a message through the chat UI +2. **Frontend Processing**: Frontend packages the message with context +3. **Runtime Request**: Message sent to runtime endpoint +4. **Agent Processing**: Runtime routes to appropriate agent +5. **Tool Execution**: Agent may call frontend or backend tools +6. **Response Streaming**: Agent streams response back +7. **UI Update**: Frontend displays response in real-time + +### State Flow + +1. **Initial State**: Agent initializes with default state +2. **State Updates**: Agent or user modifies state +3. **Synchronization**: Changes broadcast to all subscribers +4. **UI Reflection**: Components re-render with new state +5. **Persistence**: State optionally persisted to storage + +## Security Considerations + +### Frontend Security + +- **Input Validation**: All user inputs validated before sending +- **XSS Prevention**: Proper sanitization of rendered content +- **CSRF Protection**: Token-based request validation +- **Secure Storage**: Sensitive data encrypted in storage + +### Runtime Security + +- **Authentication**: Support for various auth mechanisms +- **Authorization**: Role-based access control +- **Rate Limiting**: Prevent abuse and DoS attacks +- **Input Sanitization**: Validate all incoming requests +- **Audit Logging**: Track all agent actions + +### Tool Security + +- **Permission System**: Tools require explicit permissions +- **Sandboxing**: Tools run in isolated contexts +- **Validation**: All tool parameters validated +- **Monitoring**: Track tool usage and errors + +## Scalability + +### Horizontal Scaling + +- **Stateless Runtime**: Runtime can be scaled horizontally +- **Load Balancing**: Distribute requests across instances +- **Session Management**: Sticky sessions or distributed state + +### Vertical Scaling + +- **Resource Management**: Efficient memory and CPU usage +- **Connection Pooling**: Reuse database and API connections +- **Caching**: Cache frequently accessed data + +### Performance Optimization + +- **Lazy Loading**: Load components and data on demand +- **Code Splitting**: Split bundles for faster loading +- **Streaming**: Stream responses for better perceived performance +- **Debouncing**: Reduce unnecessary updates + +## Deployment Options + +### Self-Hosted + +Deploy the runtime on your own infrastructure: +- Full control over data and security +- Custom scaling and monitoring +- Integration with existing systems + +### Cloud Platforms + +Deploy to popular cloud platforms: +- Vercel, Netlify for frontend +- AWS, GCP, Azure for runtime +- Serverless or container-based + +### Hybrid + +Combine self-hosted and cloud: +- Frontend on CDN +- Runtime on private infrastructure +- Best of both worlds + +## Monitoring and Observability + +### Built-in Monitoring + +- Request/response logging +- Performance metrics +- Error tracking +- Usage analytics + +### Integration Points + +- Custom logging adapters +- Metrics exporters +- Tracing integration +- Alert webhooks + +## Related Topics + + + + Get started with React + + + Get started with Angular + + + Learn about runtime configuration + + + Secure your application + + + + diff --git a/apps/docs/docs.json b/apps/docs/docs.json index 369f7026..d05581ba 100644 --- a/apps/docs/docs.json +++ b/apps/docs/docs.json @@ -1,21 +1,21 @@ { "$schema": "https://mintlify.com/schema.json", - "name": "CopilotKit vnext_experimental", + "name": "CopilotKit", "theme": "mint", "logo": { - "dark": "/logo/dark.svg", - "light": "/logo/light.svg" + "dark": "https://cdn.copilotkit.ai/docs/copilotkit/copilotkit-logo-dark.png", + "light": "https://cdn.copilotkit.ai/docs/copilotkit/copilotkit-logo-light.png" }, "favicon": "/favicon.ico", "colors": { - "primary": "#0D9373", - "light": "#07C983", - "dark": "#0D9373" + "primary": "#7C4DFF", + "light": "#B388FF", + "dark": "#5E35B1" }, "topbarLinks": [ { "name": "Support", - "url": "mailto:hi@copilotkitnext.ai" + "url": "mailto:hi@copilotkit.ai" } ], "topbarCtaButton": { @@ -26,37 +26,115 @@ "anchors": [ { "name": "Community", - "icon": "slack", + "icon": "discord", "url": "https://discord.gg/6dffbvGU3D" }, { "name": "Blog", "icon": "newspaper", "url": "https://copilotkit.ai/blog" + }, + { + "name": "GitHub", + "icon": "github", + "url": "https://github.com/copilotkit/copilotkit" } ], "groups": [ { - "group": "Get Started", - "pages": ["introduction"] + "group": "Getting Started", + "pages": [ + "introduction", + "quickstart/react", + "quickstart/angular" + ] + }, + { + "group": "Core Concepts", + "pages": [ + "concepts/architecture" + ] + }, + { + "group": "Guides", + "pages": [ + "guides/agentic-chat-ui", + "guides/frontend-actions", + "guides/shared-state", + "guides/human-in-the-loop", + "guides/generative-ui" + ] + }, + { + "group": "Integrations", + "pages": [ + "integrations/overview", + { + "group": "Basic Agent", + "icon": "robot", + "pages": [ + "integrations/basicagent", + "integrations/basicagent/openai", + "integrations/basicagent/anthropic", + "integrations/basicagent/gemini", + "integrations/basicagent/others" + ] + }, + "integrations/langgraph", + "integrations/mastra", + "integrations/crewai", + "integrations/custom" + ] + }, + { + "group": "Examples", + "pages": ["examples"] }, { "group": "API Reference", "pages": [ { "group": "Core", - "pages": ["reference/copilotkit-core", "reference/proxied-copilot-runtime-agent", "reference/frontend-tool"] + "icon": "code", + "pages": [ + "reference/copilotkit-core", + "reference/proxied-copilot-runtime-agent", + "reference/frontend-tool", + "reference/basic-agent", + "reference/copilot-runtime" + ] }, { "group": "React", + "icon": "react", "pages": [ { "group": "Providers", - "pages": ["reference/copilotkit-provider", "reference/copilot-chat-configuration-provider"] + "pages": [ + "reference/copilotkit-provider", + "reference/copilot-chat-configuration-provider" + ] }, { "group": "Components", - "pages": ["reference/copilot-chat"] + "pages": [ + "reference/copilot-chat", + "reference/copilot-sidebar", + "reference/copilot-sidebar-view", + "reference/copilot-popup", + "reference/copilot-popup-view", + "reference/copilot-chat-view", + "reference/copilot-chat-message-view", + "reference/copilot-chat-input", + "reference/copilot-chat-suggestion-view", + "reference/copilot-chat-suggestion-pill", + "reference/copilot-chat-tool-calls-view", + "reference/copilot-chat-toggle-button", + "reference/copilot-chat-audio-recorder", + "reference/copilot-chat-assistant-message", + "reference/copilot-chat-user-message", + "reference/copilot-modal-header" + ] }, { "group": "Hooks", @@ -66,18 +144,52 @@ "reference/use-agent-context", "reference/use-frontend-tool", "reference/use-human-in-the-loop", - "reference/use-render-tool-call" + "reference/use-render-tool-call", + "reference/use-suggestions", + "reference/use-configure-suggestions", + "reference/use-render-custom-messages", + "reference/use-render-activity-message" + ] + }, + { + "group": "Utilities", + "pages": [ + "reference/copilotkit-inspector", + "reference/wildcard-tool-call-render", + "reference/define-tool-call-renderer", + "reference/copilotkit-core-react" ] } ] + }, + { + "group": "Angular", + "icon": "angular", + "pages": [ + "reference/angular-provide-copilotkit", + "reference/angular-copilotkit-service", + "reference/angular-register-tools", + "reference/angular-agent-context", + "reference/angular-inject-agent-store", + "reference/angular-directives", + "reference/angular-copilot-chat" + ] } ] + }, + { + "group": "Troubleshooting", + "pages": [ + "troubleshooting/common-issues", + "troubleshooting/debugging" + ] } ] }, "footerSocials": { "x": "https://x.com/copilotkit", "github": "https://github.com/copilotkit/copilotkit", - "linkedin": "https://www.linkedin.com/company/copilotkit" + "linkedin": "https://www.linkedin.com/company/copilotkit", + "discord": "https://discord.gg/6dffbvGU3D" } } diff --git a/apps/docs/examples.mdx b/apps/docs/examples.mdx new file mode 100644 index 00000000..5f7f025b --- /dev/null +++ b/apps/docs/examples.mdx @@ -0,0 +1,79 @@ +--- +title: CopilotKit Examples +description: Explore example applications built with CopilotKit +icon: "code" +--- + +## Example Applications + +Need some inspiration? These examples live inside this repository and are ready to explore. + + + + Next.js application showcasing CopilotKit’s React components, shared state, frontend actions, and the in-app demo chat experience. + + + + Angular application featuring the CopilotKit chat component, frontend tooling, and Angular-specific patterns. + + + + Node runtime for the Angular demo app showing how to wire CopilotKit to backend agents and expose the AG-UI endpoint. + + + + Minimal Node.js runtime highlighting how to run CopilotKit agents outside of a web framework. + + + +## Running Examples Locally + +To run any example locally: + +1. Clone the repository: +```bash +git clone https://github.com/copilotkit/copilotkit.git +cd copilotkit/examples/[example-name] +``` + +2. Install dependencies: +```bash +pnpm install +``` + +3. Set up environment variables: +```bash +cp .env.example .env +# Edit .env with your API keys +``` + +4. Run the development server: +```bash +pnpm dev +``` + +## Contributing Examples + +We welcome community contributions! If you've built something cool with CopilotKit: + +1. Fork the repository +2. Create your example in the `examples/` directory +3. Add a README with setup instructions +4. Submit a pull request + + + Learn how to contribute to CopilotKit + + +## Need Help? + + + + Join our Discord for help and discussions + + + Ask questions and share ideas + + + + diff --git a/apps/docs/guides/agentic-chat-ui.mdx b/apps/docs/guides/agentic-chat-ui.mdx new file mode 100644 index 00000000..6c920238 --- /dev/null +++ b/apps/docs/guides/agentic-chat-ui.mdx @@ -0,0 +1,248 @@ +--- +title: Agentic Chat UI +description: Add a chat interface powered by AI agents +icon: "message-square" +--- + +## Overview + +The Agentic Chat UI provides a complete chat interface that connects to your AI agents. It handles messages, tool execution, and real-time updates automatically. + +## Quick Start + + + +```tsx +import { CopilotKitProvider, CopilotChat } from "@copilotkitnext/react"; + +function App() { + return ( + +
+ + +
+
+ ); +} +``` +
+ + +```html + +
+ + +
+``` + +```typescript +// app.config.ts +import { provideCopilotKit } from "@copilotkitnext/angular"; + +export const appConfig: ApplicationConfig = { + providers: [ + provideCopilotKit({ + runtimeUrl: "/api/copilotkit", + }), + ], +}; +``` +
+
+ +## Customization + +### Custom Labels + + + +```tsx + +``` + + + +```typescript +// app.config.ts +import { provideCopilotChatLabels } from "@copilotkitnext/angular"; + +export const appConfig: ApplicationConfig = { + providers: [ + provideCopilotChatLabels({ + chatInputPlaceholder: "Ask me anything...", + chatDisclaimerText: "AI responses may need verification.", + }), + ], +}; +``` + + + +### Specific Agent + + + +```tsx + +``` + + + +```html + +``` + + + +### Thread Management + + + +```tsx +const [threadId] = useState(() => generateThreadId()); + + +``` + + + +```typescript +threadId = signal(generateThreadId()); +``` + +```html + +``` + + + +## Layout Options + +### Sidebar + + + +```tsx +import { CopilotSidebar } from "@copilotkitnext/react"; + +
+
{/* Your content */}
+ +
+``` +
+ + +```html +
+
+ +
+``` +
+
+ +### Popup + + + +```tsx +import { CopilotPopup } from "@copilotkitnext/react"; + +
+ + +
+``` +
+ + +```html +
+ + +
+``` +
+
+ +## Custom Input + + + +```tsx +function CustomInput({ onSubmit, isDisabled }) { + const [value, setValue] = useState(""); + + return ( +
+ setValue(e.target.value)} + disabled={isDisabled} + /> + +
+ ); +} + + +``` +
+ + +```typescript +@Component({ + selector: "app-custom-input", + template: ` +
+ + +
+ `, +}) +class CustomInputComponent { + value = ""; + isDisabled = input(); + chatState = inject(ChatState); + + async send() { + await this.chatState.submitMessage(this.value); + this.value = ""; + } +} +``` + +```html + +``` +
+
+ +## Next Steps + + + + Add interactive tools + + + Render custom UI + + + Request user input + + diff --git a/apps/docs/guides/frontend-actions.mdx b/apps/docs/guides/frontend-actions.mdx new file mode 100644 index 00000000..f3bf7abe --- /dev/null +++ b/apps/docs/guides/frontend-actions.mdx @@ -0,0 +1,317 @@ +--- +title: Frontend Actions +description: Let AI agents interact with your UI +icon: "wrench" +--- + +## Overview + +Frontend actions allow AI agents to directly update your application's UI - triggering state changes, showing notifications, navigating pages, and more. + +## + + Quick Start + + + +Use the `useFrontendTool` hook to register actions: + +```tsx +import { useFrontendTool } from "@copilotkitnext/react"; +import { z } from "zod"; + +function MyComponent() { + const [theme, setTheme] = useState("light"); + + useFrontendTool({ + name: "updateTheme", + description: "Update the application theme", + parameters: z.object({ + theme: z.enum(["light", "dark", "auto"]), + }), + handler: async ({ theme }) => { + setTheme(theme); + return `Theme updated to ${theme}`; + }, + }); + + return
{/* Your UI */}
; +} +``` +
+ + +Use `registerFrontendTool` in your component constructor: + +```typescript +import { Component, signal } from "@angular/core"; +import { registerFrontendTool } from "@copilotkitnext/angular"; +import { z } from "zod"; + +@Component({ + selector: "app-my-component", + template: `
{{ theme() }}
`, +}) +export class MyComponent { + theme = signal("light"); + + constructor() { + registerFrontendTool({ + name: "updateTheme", + description: "Update the application theme", + parameters: z.object({ + theme: z.enum(["light", "dark", "auto"]), + }), + handler: async ({ theme }) => { + this.theme.set(theme); + return `Theme updated to ${theme}`; + }, + }); + } +} +``` +
+
+ +## Common Patterns + +### UI State Management + + + +```tsx +useFrontendTool({ + name: "toggleSidebar", + description: "Toggle sidebar visibility", + parameters: z.object({}), + handler: async () => { + setSidebarOpen(prev => !prev); + return `Sidebar ${sidebarOpen ? "closed" : "opened"}`; + }, +}); +``` + + + +```typescript +constructor() { + registerFrontendTool({ + name: "toggleSidebar", + description: "Toggle sidebar visibility", + parameters: z.object({}), + handler: async () => { + this.sidebarOpen.update(v => !v); + return `Sidebar ${this.sidebarOpen() ? "opened" : "closed"}`; + }, + }); +} +``` + + + +### Navigation + + + +```tsx +import { useRouter } from "next/navigation"; + +const router = useRouter(); + +useFrontendTool({ + name: "navigateToPage", + description: "Navigate to a page", + parameters: z.object({ + page: z.enum(["home", "dashboard", "settings"]), + }), + handler: async ({ page }) => { + router.push(`/${page}`); + return `Navigated to ${page}`; + }, +}); +``` + + + +```typescript +import { Router } from "@angular/router"; +import { inject } from "@angular/core"; + +constructor() { + const router = inject(Router); + + registerFrontendTool({ + name: "navigateToPage", + description: "Navigate to a page", + parameters: z.object({ + page: z.enum(["home", "dashboard", "settings"]), + }), + handler: async ({ page }) => { + await router.navigate([`/${page}`]); + return `Navigated to ${page}`; + }, + }); +} +``` + + + +### Form Manipulation + + + +```tsx +useFrontendTool({ + name: "fillForm", + description: "Fill out a form", + parameters: z.object({ + name: z.string(), + email: z.string().email(), + }), + handler: async ({ name, email }) => { + setFormData({ name, email }); + return "Form filled successfully"; + }, +}); +``` + + + +```typescript +registerFrontendTool({ + name: "fillForm", + description: "Fill out a form", + parameters: z.object({ + name: z.string(), + email: z.string().email(), + }), + handler: async ({ name, email }) => { + this.formData.set({ name, email }); + return "Form filled successfully"; + }, +}); +``` + + + +### Notifications + + + +```tsx +import { toast } from "sonner"; + +useFrontendTool({ + name: "showNotification", + description: "Display a notification", + parameters: z.object({ + message: z.string(), + type: z.enum(["info", "success", "warning", "error"]), + }), + handler: async ({ message, type }) => { + toast[type](message); + return "Notification displayed"; + }, +}); +``` + + + +```typescript +import { MatSnackBar } from "@angular/material/snack-bar"; + +constructor() { + const snackBar = inject(MatSnackBar); + + registerFrontendTool({ + name: "showNotification", + description: "Display a notification", + parameters: z.object({ + message: z.string(), + type: z.enum(["info", "success", "warning", "error"]), + }), + handler: async ({ message, type }) => { + snackBar.open(message, "Close", { duration: 3000 }); + return "Notification displayed"; + }, + }); +} +``` + + + +## Static Registration + +You can also register tools statically in the provider: + + + +```tsx +import { CopilotKitProvider } from "@copilotkitnext/react"; + +const frontendTools = [ + { + name: "updateTheme", + description: "Update theme", + parameters: z.object({ theme: z.enum(["light", "dark"]) }), + handler: async ({ theme }) => { + // Update theme logic + return `Theme set to ${theme}`; + }, + }, +]; + +function App() { + return ( + + {children} + + ); +} +``` + + + +```typescript +// app.config.ts +import { provideCopilotKit } from "@copilotkitnext/angular"; +import { z } from "zod"; + +export const appConfig: ApplicationConfig = { + providers: [ + provideCopilotKit({ + runtimeUrl: "/api/copilotkit", + frontendTools: [ + { + name: "updateTheme", + description: "Update theme", + parameters: z.object({ theme: z.enum(["light", "dark"]) }), + handler: async ({ theme }) => { + // Update theme logic + return `Theme set to ${theme}`; + }, + }, + ], + }), + ], +}; +``` + + + +## Next Steps + + + + Sync state between UI and agent + + + Request user approval + + + Render dynamic UI + + diff --git a/apps/docs/guides/generative-ui.mdx b/apps/docs/guides/generative-ui.mdx new file mode 100644 index 00000000..1c48f01e --- /dev/null +++ b/apps/docs/guides/generative-ui.mdx @@ -0,0 +1,266 @@ +--- +title: Generative UI +description: Render dynamic UI components from agent tool calls +icon: "sparkles" +--- + +## Overview + +Generative UI allows agents to render custom UI components when executing tools. Instead of just showing text, agents can display charts, forms, interactive elements, and more. + +## Quick Start + + + +Use `useRenderToolCall` to define custom rendering: + +```tsx +import { useRenderToolCall } from "@copilotkitnext/react"; +import { z } from "zod"; + +function MyComponent() { + useRenderToolCall({ + name: "showChart", + args: z.object({ + data: z.array(z.number()), + labels: z.array(z.string()), + }), + render: ({ args, status }) => { + if (status === "complete") { + return ; + } + return
Loading chart...
; + }, + }); + + return
{/* Your UI */}
; +} +``` +
+ + +Create a component and register it: + +```typescript +import { Component, input } from "@angular/core"; +import { registerRenderToolCall, ToolRenderer } from "@copilotkitnext/angular"; +import { z } from "zod"; + +@Component({ + selector: "app-chart-render", + standalone: true, + template: ` +
+ +
+
Loading chart...
+ `, +}) +class ChartRenderComponent implements ToolRenderer { + args = input.required(); + status = input.required(); +} + +@Component({ + selector: "app-my-component", + template: `
`, +}) +export class MyComponent { + constructor() { + registerRenderToolCall({ + name: "showChart", + args: z.object({ + data: z.array(z.number()), + labels: z.array(z.string()), + }), + component: ChartRenderComponent, + }); + } +} +``` +
+
+ +## Common Patterns + +### Data Visualization + + + +```tsx +useRenderToolCall({ + name: "displayData", + args: z.object({ + items: z.array(z.record(z.any())), + view: z.enum(["table", "grid", "list"]), + }), + render: ({ args }) => { + if (args.view === "table") { + return ; + } + return ; + }, +}); +``` + + + +```typescript +@Component({ + selector: "app-data-display", + template: ` + + + `, +}) +class DataDisplayComponent implements ToolRenderer { + args = input.required(); +} +``` + + + +### Progress Indicators + + + +```tsx +useRenderToolCall({ + name: "processData", + args: z.object({ + taskName: z.string(), + progress: z.number(), + }), + render: ({ args, status }) => ( +
+

{args.taskName}

+ + {status === "complete" && ✓ Complete} +
+ ), +}); +``` +
+ + +```typescript +@Component({ + selector: "app-progress", + template: ` +
+

{{ args().taskName }}

+ + ✓ Complete +
+ `, +}) +class ProgressComponent implements ToolRenderer { + args = input.required(); + status = input.required(); +} +``` +
+
+ +### Interactive Forms + + + +```tsx +useRenderToolCall({ + name: "collectFeedback", + args: z.object({ + question: z.string(), + }), + render: ({ args, status, result }) => { + if (status === "complete") { + return
Thanks for your feedback: {result}
; + } + return ( +
+

{args.question}

+ +
+
+ Thanks for your feedback: {{ result() }} +
+ `, +}) +class FeedbackFormComponent implements ToolRenderer { + args = input.required(); + status = input.required(); + result = input(); +} +``` +
+
+ +## Static Registration + +Register render components in the provider: + + + +```tsx +const renderToolCalls = [ + { + name: "showChart", + args: z.object({ data: z.array(z.number()) }), + render: ({ args }) => , + }, +]; + + + {children} + +``` + + + +```typescript +// app.config.ts +provideCopilotKit({ + runtimeUrl: "/api/copilotkit", + renderToolCalls: [ + { + name: "showChart", + args: z.object({ data: z.array(z.number()) }), + component: ChartRenderComponent, + }, + ], +}) +``` + + + +## Next Steps + + + + Execute actions from tools + + + Request human input + + + Share context with agents + + diff --git a/apps/docs/guides/human-in-the-loop.mdx b/apps/docs/guides/human-in-the-loop.mdx new file mode 100644 index 00000000..96090dab --- /dev/null +++ b/apps/docs/guides/human-in-the-loop.mdx @@ -0,0 +1,258 @@ +--- +title: Human in the Loop +description: Request human approval for agent actions +icon: "user" +--- + +## Overview + +Human-in-the-Loop (HITL) allows agents to pause and request human approval before executing critical actions. Essential for building trustworthy AI systems. + +## Quick Start + + + +Use the `useHumanInTheLoop` hook: + +```tsx +import { useHumanInTheLoop } from "@copilotkitnext/react"; +import { z } from "zod"; + +function MyComponent() { + useHumanInTheLoop({ + name: "confirmDeletion", + description: "Request confirmation before deleting", + parameters: z.object({ + itemName: z.string(), + itemId: z.string(), + }), + render: ({ args, status, respond }) => { + if (status === "executing") { + return ( +
+

Delete "{args.itemName}"?

+ + +
+ ); + } + return null; + }, + }); + + return
{/* Your UI */}
; +} +``` +
+ + +Use `registerHumanInTheLoop`: + +```typescript +import { Component } from "@angular/core"; +import { registerHumanInTheLoop, HumanInTheLoopToolRenderer } from "@copilotkitnext/angular"; +import { z } from "zod"; + +@Component({ + selector: "app-confirm-delete", + standalone: true, + template: ` +
+

Delete "{{ toolCall().args.itemName }}"?

+ + +
+ `, +}) +class ConfirmDeleteComponent implements HumanInTheLoopToolRenderer { + toolCall = input.required(); + + confirm() { + this.toolCall().respond({ confirmed: true }); + } + + cancel() { + this.toolCall().respond({ confirmed: false }); + } +} + +@Component({ + selector: "app-my-component", + template: `
`, +}) +export class MyComponent { + constructor() { + registerHumanInTheLoop({ + name: "confirmDeletion", + description: "Request confirmation before deleting", + parameters: z.object({ + itemName: z.string(), + itemId: z.string(), + }), + component: ConfirmDeleteComponent, + }); + } +} +``` +
+
+ +## Common Patterns + +### Approval Workflow + + + +```tsx +useHumanInTheLoop({ + name: "approveTransaction", + description: "Approve financial transaction", + parameters: z.object({ + amount: z.number(), + recipient: z.string(), + }), + render: ({ args, status, respond }) => { + if (status !== "executing") return null; + + return ( +
+

Approve Transaction

+

Amount: ${args.amount}

+

To: {args.recipient}

+ + +
+ ); + }, +}); +``` +
+ + +```typescript +@Component({ + selector: "app-approve-transaction", + template: ` +
+

Approve Transaction

+

Amount: ${{ toolCall().args.amount }}

+

To: {{ toolCall().args.recipient }}

+ + +
+ `, +}) +class ApproveTransactionComponent implements HumanInTheLoopToolRenderer { + toolCall = input.required(); + + approve() { + this.toolCall().respond({ approved: true }); + } + + deny() { + this.toolCall().respond({ approved: false }); + } +} + +// Register in constructor +registerHumanInTheLoop({ + name: "approveTransaction", + description: "Approve financial transaction", + parameters: z.object({ + amount: z.number(), + recipient: z.string(), + }), + component: ApproveTransactionComponent, +}); +``` +
+
+ +### Data Review + + + +```tsx +useHumanInTheLoop({ + name: "reviewData", + description: "Review data before processing", + parameters: z.object({ + data: z.array(z.record(z.any())), + }), + render: ({ args, status, respond }) => { + if (status !== "executing") return null; + + return ( +
+

Review Data

+
{JSON.stringify(args.data, null, 2)}
+ + +
+ ); + }, +}); +``` +
+ + +```typescript +@Component({ + selector: "app-review-data", + template: ` +
+

Review Data

+
{{ toolCall().args.data | json }}
+ + +
+ `, +}) +class ReviewDataComponent implements HumanInTheLoopToolRenderer { + toolCall = input.required(); + + approve() { + this.toolCall().respond({ approved: true }); + } + + reject() { + this.toolCall().respond({ approved: false }); + } +} +``` +
+
+ +## Tool Call Status + +The `status` prop indicates the tool call's state: + +- `"in-progress"` - Agent is building arguments (args may be partial) +- `"executing"` - Waiting for human response (show UI) +- `"complete"` - Human has responded (show result) + +## Next Steps + + + + Let agents update UI + + + Render dynamic UI + + + Share context with agents + + diff --git a/apps/docs/guides/shared-state.mdx b/apps/docs/guides/shared-state.mdx new file mode 100644 index 00000000..fbcadc4e --- /dev/null +++ b/apps/docs/guides/shared-state.mdx @@ -0,0 +1,333 @@ +--- +title: Shared State +description: Two-way state synchronization between UI and agents +icon: "repeat" +--- + +## Overview + +Shared State provides bidirectional synchronization between your UI and AI agents. Your UI can read and update agent state, and agents can update state that reflects in your UI in real-time. + +## Quick Start + + + +Use the `useAgent` hook to access and update state: + +```tsx +import { useAgent } from "@copilotkitnext/react"; + +function MyComponent() { + const { agent } = useAgent(); + + // Read agent state + const currentTask = agent?.state?.currentTask; + const progress = agent?.state?.progress; + + // Update agent state + const updatePriority = () => { + agent?.setState({ priority: "high" }); + }; + + return ( +
+

Current Task: {currentTask}

+ + +
+ ); +} +``` +
+ + +Use `injectAgentStore` to access and update state: + +```typescript +import { Component, computed } from "@angular/core"; +import { injectAgentStore } from "@copilotkitnext/angular"; + +@Component({ + selector: "app-my-component", + template: ` +
+

Current Task: {{ currentTask() }}

+ + +
+ `, +}) +export class MyComponent { + agentStore = injectAgentStore("default"); + agent = computed(() => this.agentStore()?.agent); + state = computed(() => this.agentStore()?.state()); + + currentTask = computed(() => this.state()?.currentTask); + progress = computed(() => this.state()?.progress); + + updatePriority() { + this.agent()?.setState({ priority: "high" }); + } +} +``` +
+
+ +## Common Patterns + +### Task Progress Tracking + + + +```tsx +function TaskTracker() { + const { agent } = useAgent(); + const tasks = agent?.state?.tasks || []; + const currentIndex = agent?.state?.currentIndex || 0; + + return ( +
+

Task Progress

+

{currentIndex + 1} of {tasks.length}

+
    + {tasks.map((task, i) => ( +
  • + {task} + {i === currentIndex && " ← Current"} + {i < currentIndex && " ✓"} +
  • + ))} +
+
+ ); +} +``` +
+ + +```typescript +@Component({ + selector: "app-task-tracker", + template: ` +
+

Task Progress

+

{{ currentIndex() + 1 }} of {{ tasks().length }}

+
    +
  • + {{ task }} + ← Current + +
  • +
+
+ `, +}) +export class TaskTrackerComponent { + agentStore = injectAgentStore("default"); + state = computed(() => this.agentStore()?.state()); + + tasks = computed(() => this.state()?.tasks || []); + currentIndex = computed(() => this.state()?.currentIndex || 0); +} +``` +
+
+ +### Form State Synchronization + + + +```tsx +function FormSync() { + const { agent } = useAgent(); + const formData = agent?.state?.formData || {}; + + const updateField = (field: string, value: string) => { + agent?.setState({ + formData: { ...formData, [field]: value }, + }); + }; + + return ( +
+ updateField("name", e.target.value)} + /> + updateField("email", e.target.value)} + /> +
+ ); +} +``` +
+ + +```typescript +@Component({ + selector: "app-form-sync", + template: ` +
+ + +
+ `, +}) +export class FormSyncComponent { + agentStore = injectAgentStore("default"); + agent = computed(() => this.agentStore()?.agent); + state = computed(() => this.agentStore()?.state()); + + formData = computed(() => this.state()?.formData || {}); + + updateField(field: string, value: string) { + const current = this.formData(); + this.agent()?.setState({ + formData: { ...current, [field]: value }, + }); + } +} +``` +
+
+ +### User Preferences + + + +```tsx +function PreferencesPanel() { + const { agent } = useAgent(); + const preferences = agent?.state?.preferences || { + theme: "light", + notifications: true, + }; + + const updatePreference = (key: string, value: any) => { + agent?.setState({ + preferences: { ...preferences, [key]: value }, + }); + }; + + return ( +
+ + +
+ ); +} +``` +
+ + +```typescript +@Component({ + selector: "app-preferences-panel", + template: ` +
+ + +
+ `, +}) +export class PreferencesPanelComponent { + agentStore = injectAgentStore("default"); + agent = computed(() => this.agentStore()?.agent); + state = computed(() => this.agentStore()?.state()); + + preferences = computed(() => this.state()?.preferences || { + theme: "light", + notifications: true, + }); + + updatePreference(key: string, value: any) { + const current = this.preferences(); + this.agent()?.setState({ + preferences: { ...current, [key]: value }, + }); + } +} +``` +
+
+ +## Specific Agent + +Access state from a specific agent: + + + +```tsx +const { agent } = useAgent({ agentId: "sales" }); +const salesData = agent?.state?.salesData; +``` + + + +```typescript +agentStore = injectAgentStore("sales"); +state = computed(() => this.agentStore()?.state()); +salesData = computed(() => this.state()?.salesData); +``` + + + +## State Updates + +State updates are merged with existing state: + +```typescript +// Current state: { task: "research", priority: "low" } +agent?.setState({ priority: "high" }); +// New state: { task: "research", priority: "high" } +``` + +## Next Steps + + + + Let agents update your UI + + + Request user approval + + + Render dynamic UI + + diff --git a/apps/docs/integrations/basicagent.mdx b/apps/docs/integrations/basicagent.mdx new file mode 100644 index 00000000..9b2411c9 --- /dev/null +++ b/apps/docs/integrations/basicagent.mdx @@ -0,0 +1,142 @@ +--- +title: Overview +description: Direct LLM connections with CopilotKit using BasicAgent +icon: "robot" +--- + +## Overview + +The `BasicAgent` in CopilotKit provides a straightforward way to connect directly to LLM providers. It handles AG-UI event streaming and model interaction automatically. + +This is the simplest way to create an AI agent with CopilotKit. + +## Supported Providers + + + + GPT-4, GPT-4o, and other OpenAI models + + + Claude Sonnet, Opus, and Haiku models + + + Gemini Pro and Flash models + + + Groq, Mistral, Perplexity, and custom gateways + + + +## Quick Start + +### 1. Install Dependencies + +```bash +pnpm add @copilotkitnext/agent @copilotkitnext/runtime ai +``` + +### 2. Create Runtime Endpoint + +```typescript +// src/app/api/copilotkit/[[...slug]]/route.ts +import { CopilotRuntime, createCopilotEndpoint, InMemoryAgentRunner } from "@copilotkitnext/runtime"; +import { BasicAgent } from "@copilotkitnext/agent"; +import { handle } from "hono/vercel"; + +const agent = new BasicAgent({ + model: "openai/gpt-4o", // or any supported model + prompt: "You are a helpful AI assistant.", + temperature: 0.7, +}); + +const runtime = new CopilotRuntime({ + agents: { + default: agent, + }, + runner: new InMemoryAgentRunner(), +}); + +const app = createCopilotEndpoint({ + runtime, + basePath: "/api/copilotkit", +}); + +export const GET = handle(app); +export const POST = handle(app); +``` + +### 3. Connect Frontend + +```typescript +import { CopilotKitProvider } from "@copilotkitnext/react"; + +function App() { + return ( + + {/* Your app components */} + + ); +} +``` + +## Configuration Options + +```typescript +const agent = new BasicAgent({ + model: "openai/gpt-4o", // Model identifier (required) + prompt: "You are...", // System prompt + temperature: 0.7, // Randomness (0-2 for OpenAI, 0-1 for Anthropic) + maxOutputTokens: 1000, // Max response length + maxSteps: 5, // Max tool calling iterations + toolChoice: "auto", // "auto" | "required" | "none" + tools: [], // Backend tools + overridableProperties: [], // Properties that can be overridden from frontend +}); +``` + +## Adding Tools + +```typescript +import { z } from "zod"; + +const agent = new BasicAgent({ + model: "openai/gpt-4o", + tools: [ + { + name: "search_database", + description: "Search the database", + parameters: z.object({ + query: z.string(), + }), + execute: async ({ query }) => { + return await database.search(query); + }, + }, + ], +}); +``` + +## Multiple Agents + +```typescript +const runtime = new CopilotRuntime({ + agents: { + fast: new BasicAgent({ + model: "openai/gpt-4o-mini", + }), + powerful: new BasicAgent({ + model: "anthropic/claude-opus-4.1", + }), + }, + runner: new InMemoryAgentRunner(), +}); +``` + +## Next Steps + +Choose your LLM provider to get started: + +- [OpenAI](/integrations/basicagent/openai) - GPT models +- [Anthropic](/integrations/basicagent/anthropic) - Claude models +- [Google Gemini](/integrations/basicagent/gemini) - Gemini models +- [Any model](/integrations/basicagent/others) - Groq, Mistral, Perplexity, custom gateways diff --git a/apps/docs/integrations/basicagent/anthropic.mdx b/apps/docs/integrations/basicagent/anthropic.mdx new file mode 100644 index 00000000..5a7e5558 --- /dev/null +++ b/apps/docs/integrations/basicagent/anthropic.mdx @@ -0,0 +1,113 @@ +--- +title: Anthropic +description: Use Anthropic Claude models with BasicAgent +icon: "message-square" +--- + +## Overview + +Connect to Anthropic's Claude models using `BasicAgent`. Supports Claude Sonnet, Opus, and Haiku with 200K token context windows. + +## Prerequisites + +- Anthropic API key ([Get one here](https://console.anthropic.com/)) + +## Setup + +### 1. Environment Variables + +```bash +ANTHROPIC_API_KEY=sk-ant-... +``` + +### 2. Create Agent + +```typescript +import { BasicAgent } from "@copilotkitnext/agent"; + +const agent = new BasicAgent({ + model: "anthropic/claude-sonnet-4.5", + prompt: "You are a helpful AI assistant.", + temperature: 1.0, +}); +``` + +## Available Models + +```typescript +// Claude Sonnet 4.5 (recommended) +model: "anthropic/claude-sonnet-4.5" + +// Claude Opus 4.1 (most capable) +model: "anthropic/claude-opus-4.1" + +// Claude 3.5 Haiku (fastest) +model: "anthropic/claude-3.5-haiku" + +// Claude 3.7 Sonnet +model: "anthropic/claude-3.7-sonnet" + +// Claude Opus 4 +model: "anthropic/claude-opus-4" + +// Claude Sonnet 4 +model: "anthropic/claude-sonnet-4" +``` + +## Configuration + +```typescript +const agent = new BasicAgent({ + model: "anthropic/claude-sonnet-4.5", + temperature: 1.0, // 0-1 (higher = more random) + maxOutputTokens: 4096, + topP: 0.999, + topK: 250, // Anthropic-specific +}); +``` + +## Example + +```typescript +// src/app/api/copilotkit/[[...slug]]/route.ts +import { CopilotRuntime, createCopilotEndpoint, InMemoryAgentRunner } from "@copilotkitnext/runtime"; +import { BasicAgent } from "@copilotkitnext/agent"; +import { handle } from "hono/vercel"; + +const agent = new BasicAgent({ + model: "anthropic/claude-sonnet-4.5", + prompt: "You are a helpful AI assistant.", + temperature: 1.0, +}); + +const runtime = new CopilotRuntime({ + agents: { default: agent }, + runner: new InMemoryAgentRunner(), +}); + +const app = createCopilotEndpoint({ + runtime, + basePath: "/api/copilotkit", +}); + +export const GET = handle(app); +export const POST = handle(app); +``` + +## Context Window + +All Claude models support **200K tokens** context window - excellent for long documents and conversations. + +## Key Differences from OpenAI + +- **Temperature range**: 0-1 (vs OpenAI's 0-2) +- **Top K sampling**: Available (not in OpenAI) +- **Penalties**: No frequency/presence penalties +- **Context**: 200K tokens (vs OpenAI's 128K) + +## Next Steps + +- [Add tools](/guides/frontend-actions) to your agent +- [Configure shared state](/guides/shared-state) +- Try [OpenAI](/integrations/basicagent/openai) or [Gemini](/integrations/basicagent/gemini) + diff --git a/apps/docs/integrations/basicagent/gemini.mdx b/apps/docs/integrations/basicagent/gemini.mdx new file mode 100644 index 00000000..1bc713d0 --- /dev/null +++ b/apps/docs/integrations/basicagent/gemini.mdx @@ -0,0 +1,112 @@ +--- +title: Google Gemini +description: Use Google Gemini models with BasicAgent +icon: "google" +--- + +## Overview + +Connect to Google's Gemini models using `BasicAgent`. Supports Gemini Pro and Flash models with multimodal capabilities. + +## Prerequisites + +- Google AI API key ([Get one here](https://makersuite.google.com/app/apikey)) + +## Setup + +### 1. Environment Variables + +```bash +GOOGLE_API_KEY=... +``` + +### 2. Create Agent + +```typescript +import { BasicAgent } from "@copilotkitnext/agent"; + +const agent = new BasicAgent({ + model: "google/gemini-2.0-flash", + prompt: "You are a helpful AI assistant.", + temperature: 0.7, +}); +``` + +## Available Models + +```typescript +// Gemini 2.0 Flash (recommended - fast and capable) +model: "google/gemini-2.0-flash" + +// Gemini 2.5 Pro (most capable) +model: "google/gemini-2.5-pro" + +// Gemini 1.5 Flash +model: "google/gemini-1.5-flash" + +// Gemini 1.5 Pro +model: "google/gemini-1.5-pro" +``` + +## Configuration + +```typescript +const agent = new BasicAgent({ + model: "google/gemini-2.0-flash", + temperature: 0.7, // 0-2 (higher = more random) + maxOutputTokens: 8192, + topP: 0.95, + topK: 40, +}); +``` + +## Example + +```typescript +// src/app/api/copilotkit/[[...slug]]/route.ts +import { CopilotRuntime, createCopilotEndpoint, InMemoryAgentRunner } from "@copilotkitnext/runtime"; +import { BasicAgent } from "@copilotkitnext/agent"; +import { handle } from "hono/vercel"; + +const agent = new BasicAgent({ + model: "google/gemini-2.0-flash", + prompt: "You are a helpful AI assistant.", + temperature: 0.7, +}); + +const runtime = new CopilotRuntime({ + agents: { default: agent }, + runner: new InMemoryAgentRunner(), +}); + +const app = createCopilotEndpoint({ + runtime, + basePath: "/api/copilotkit", +}); + +export const GET = handle(app); +export const POST = handle(app); +``` + +## Context Window + +| Model | Context Window | +|-------|----------------| +| Gemini 2.5 Pro | 2M tokens | +| Gemini 2.0 Flash | 1M tokens | +| Gemini 1.5 Pro | 2M tokens | +| Gemini 1.5 Flash | 1M tokens | + +## Features + +- **Massive context**: Up to 2M tokens +- **Multimodal**: Native image and video understanding +- **Fast inference**: Flash models optimized for speed +- **Cost effective**: Competitive pricing + +## Next Steps + +- [Add tools](/guides/frontend-actions) to your agent +- [Configure shared state](/guides/shared-state) +- Try [OpenAI](/integrations/basicagent/openai) or [Anthropic](/integrations/basicagent/anthropic) + diff --git a/apps/docs/integrations/basicagent/openai.mdx b/apps/docs/integrations/basicagent/openai.mdx new file mode 100644 index 00000000..b7b8e3c1 --- /dev/null +++ b/apps/docs/integrations/basicagent/openai.mdx @@ -0,0 +1,115 @@ +--- +title: OpenAI +description: Use OpenAI models with BasicAgent +icon: "openai" +--- + +## Overview + +Connect to OpenAI's GPT models using `BasicAgent`. Supports GPT-4, GPT-4o, and reasoning models. + +## Prerequisites + +- OpenAI API key ([Get one here](https://platform.openai.com/api-keys)) + +## Setup + +### 1. Environment Variables + +```bash +OPENAI_API_KEY=sk-... +``` + +### 2. Create Agent + +```typescript +import { BasicAgent } from "@copilotkitnext/agent"; + +const agent = new BasicAgent({ + model: "openai/gpt-4o", + prompt: "You are a helpful AI assistant.", + temperature: 0.7, +}); +``` + +## Available Models + +```typescript +// GPT-4o (recommended) +model: "openai/gpt-4o" + +// GPT-4o mini (faster, cheaper) +model: "openai/gpt-4o-mini" + +// GPT-4.1 +model: "openai/gpt-4.1" + +// GPT-4.1 mini +model: "openai/gpt-4.1-mini" + +// GPT-4.1 nano +model: "openai/gpt-4.1-nano" + +// O-series (reasoning) +model: "openai/o3-mini" +model: "openai/o4-mini" +``` + +## Configuration + +```typescript +const agent = new BasicAgent({ + model: "openai/gpt-4o", + temperature: 0.7, // 0-2 (higher = more random) + maxOutputTokens: 1000, + topP: 1, + frequencyPenalty: 0, // -2.0 to 2.0 + presencePenalty: 0, // -2.0 to 2.0 + stopSequences: [], + seed: 42, // For deterministic output +}); +``` + +## Example + +```typescript +// src/app/api/copilotkit/[[...slug]]/route.ts +import { CopilotRuntime, createCopilotEndpoint, InMemoryAgentRunner } from "@copilotkitnext/runtime"; +import { BasicAgent } from "@copilotkitnext/agent"; +import { handle } from "hono/vercel"; + +const agent = new BasicAgent({ + model: "openai/gpt-4o", + prompt: "You are a helpful AI assistant.", + temperature: 0.7, +}); + +const runtime = new CopilotRuntime({ + agents: { default: agent }, + runner: new InMemoryAgentRunner(), +}); + +const app = createCopilotEndpoint({ + runtime, + basePath: "/api/copilotkit", +}); + +export const GET = handle(app); +export const POST = handle(app); +``` + +## Context Window + +| Model | Context Window | +|-------|----------------| +| GPT-4o | 128K tokens | +| GPT-4o mini | 128K tokens | +| GPT-4.1 | 128K tokens | +| O-series | 200K tokens | + +## Next Steps + +- [Add tools](/guides/frontend-actions) to your agent +- [Configure shared state](/guides/shared-state) +- Try [Anthropic](/integrations/basicagent/anthropic) or [Gemini](/integrations/basicagent/gemini) + diff --git a/apps/docs/integrations/basicagent/others.mdx b/apps/docs/integrations/basicagent/others.mdx new file mode 100644 index 00000000..9c09463d --- /dev/null +++ b/apps/docs/integrations/basicagent/others.mdx @@ -0,0 +1,103 @@ +--- +title: Any Model +description: Connect BasicAgent to Groq, Mistral, Perplexity, or any custom provider +icon: "sparkles" +--- + +## Overview + +BasicAgent can talk to *any* model provider that exposes a chat-completion style API. Beyond OpenAI, Anthropic, and Gemini, teams commonly wire up Groq (for ultra-fast inference on open models), Mistral, Perplexity, or even internal gateways. All of these follow the same configuration pattern—set the `model` identifier, supply credentials through environment variables, and pass provider-specific settings through the agent options. + +## Groq Example + +Groq offers blazing-fast inference for Llama, Mixtral, and Gemma models. Here’s how you can configure BasicAgent to use Groq’s API: + +```bash +# .env +GROQ_API_KEY=... # Get one at https://console.groq.com/ +``` + +```typescript +// src/app/api/copilotkit/[[...slug]]/route.ts +import { CopilotRuntime, createCopilotEndpoint, InMemoryAgentRunner } from "@copilotkitnext/runtime"; +import { BasicAgent } from "@copilotkitnext/agent"; +import { handle } from "hono/vercel"; + +const agent = new BasicAgent({ + model: "groq/llama-3.3-70b", + prompt: "You are a helpful AI assistant.", + temperature: 0.7, + maxOutputTokens: 8192, +}); + +const runtime = new CopilotRuntime({ + agents: { default: agent }, + runner: new InMemoryAgentRunner(), +}); + +const app = createCopilotEndpoint({ + runtime, + basePath: "/api/copilotkit", +}); + +export const GET = handle(app); +export const POST = handle(app); +``` + +### Groq Model Identifiers + +```typescript +// Llama models +model: "groq/llama-3.3-70b" +model: "groq/llama-3.1-70b" +model: "groq/llama-3.1-8b" + +// Mixtral +model: "groq/mixtral-8x7b" + +// Gemma +model: "groq/gemma-2-9b" +``` + +## Mistral Example + +Mistral’s platform exposes multiple models and supports function calling. Supply the Mistral key and set the model string: + +```bash +MISTRAL_API_KEY=... +``` + +```typescript +const agent = new BasicAgent({ + model: "mistral/mistral-large-latest", + temperature: 0.5, + maxOutputTokens: 2048, +}); +``` + +## Perplexity or Custom Gateways + +Any other provider can be configured similarly. Set `model` to the identifier expected by your gateway and expose the API key via environment variables. + +```typescript +const agent = new BasicAgent({ + model: "perplexity/sonar-medium-online", + temperature: 0.4, + tools: [...], +}); +``` + +If your provider requires custom headers or query parameters, use an SDK or wrap the service in your own endpoint, then point BasicAgent at that adapter. + +## Tips + +- **Model Strings**: BasicAgent accepts any string identifier (the type is `string & {}` under the hood), so you can point it at internal gateways or self-hosted adapters without adding new TypeScript definitions. +- **Environment Variables**: Keep provider keys in `.env` files and reference them in your runtime code. BasicAgent does not manage secrets for you. +- **Retries & Timeouts**: Use the `maxRetries`, `temperature`, `maxOutputTokens`, and other BasicAgent options to tune behaviour per provider. +- **Tool Support**: Some providers (like Perplexity) only support text responses. Tools will be ignored unless the provider supports function calling. + +## Next Steps + +- Review the main [BasicAgent guide](/integrations/basicagent) for shared configuration options +- Jump to [OpenAI](/integrations/basicagent/openai), [Anthropic](/integrations/basicagent/anthropic), or [Gemini](/integrations/basicagent/gemini) for detailed tutorials +- Check out [Custom Integrations](/integrations/custom) to wrap internal gateways or bespoke providers diff --git a/apps/docs/integrations/crewai.mdx b/apps/docs/integrations/crewai.mdx new file mode 100644 index 00000000..8fb3ad8b --- /dev/null +++ b/apps/docs/integrations/crewai.mdx @@ -0,0 +1,124 @@ +--- +title: CrewAI Integration +description: Integrate CopilotKit with CrewAI agents +icon: "users" +--- + +## Overview + +CrewAI is a framework for orchestrating role-playing, autonomous AI agents. CopilotKit integrates with CrewAI **Enterprise** agents (Crews and Flows) through Copilot Cloud or by using the `@ag-ui/crewai` package for TypeScript/JavaScript projects. + +This guide shows you how to connect your CrewAI agents to CopilotKit. + +## Prerequisites + +- Node.js 18+ +- CrewAI Enterprise account (for Python Crews/Flows) OR a TypeScript/JavaScript project +- OpenAI API key + +## Option 1: Using Copilot Cloud (Python Crews/Flows) + +If you're using CrewAI Enterprise with Python Crews or Flows, the easiest way to integrate with CopilotKit is through Copilot Cloud. + +### 1. Set Up Copilot Cloud + +1. Go to [Copilot Cloud](https://cloud.copilotkit.ai) and sign in +2. Add your OpenAI API key to the "Provide OpenAI API Key" section +3. Click "Add Remote Endpoint" and fill in the details of your CrewAI Crew or Flow + - **Note:** If your Agent Name contains multiple words, use underscores (`_`) as separators +4. Click "Save Endpoint" +5. Copy your Copilot Cloud Public API Key + +### 2. Connect to the Frontend + +In your React or Angular application, connect using `CopilotKitProvider` with your Cloud API key: + +```typescript +// React example +import { CopilotKitProvider } from "@copilotkitnext/react"; + +function App() { + return ( + + {/* Your app components */} + + ); +} +``` + +## Option 2: Self-Hosted with TypeScript/JavaScript + +If you're building CrewAI-style multi-agent systems in TypeScript/JavaScript, you can use the `@ag-ui/crewai` package. + +### 1. Install Dependencies + +```bash +pnpm add @copilotkitnext/runtime @ag-ui/crewai ai +``` + +### 2. Configure Your Runtime Endpoint + +Create a runtime endpoint that registers your CrewAI agents: + +```typescript +// src/app/api/copilotkit/[[...slug]]/route.ts +import { CopilotRuntime, createCopilotEndpoint, InMemoryAgentRunner } from "@copilotkitnext/runtime"; +import { CrewAIAgent } from "@ag-ui/crewai"; +import { handle } from "hono/vercel"; + +// Define your CrewAI agent +const agent = new CrewAIAgent({ + // Your CrewAI configuration here + // This will depend on your specific CrewAI setup +}); + +const runtime = new CopilotRuntime({ + agents: { + default: agent, + }, + runner: new InMemoryAgentRunner(), +}); + +const app = createCopilotEndpoint({ + runtime, + basePath: "/api/copilotkit", +}); + +export const GET = handle(app); +export const POST = handle(app); +``` + +### 3. Connect to the Frontend + +```typescript +// React example +import { CopilotKitProvider } from "@copilotkitnext/react"; + +function App() { + return ( + + {/* Your app components */} + + ); +} +``` + +## Python Integration with ag-ui-crewai + +For Python-based CrewAI projects, you can use the `ag-ui-crewai` package to handle AG-UI event streaming: + +```bash +pip install ag-ui-crewai +``` + +This package provides helpers to wrap your CrewAI Crews and Flows so they emit AG-UI events automatically. + +## Next Steps + +- Learn about [Frontend Actions](/guides/frontend-actions) +- Explore [Shared State](/guides/shared-state) +- Implement [Human-in-the-Loop](/guides/human-in-the-loop) +- Check out the [CrewAI Enterprise documentation](https://docs.crewai.com/enterprise/introduction) diff --git a/apps/docs/integrations/custom.mdx b/apps/docs/integrations/custom.mdx new file mode 100644 index 00000000..bc9a4b95 --- /dev/null +++ b/apps/docs/integrations/custom.mdx @@ -0,0 +1,517 @@ +--- +title: Custom Integration +description: Build your own custom agent integration with CopilotKit +icon: "code" +--- + +## Overview + +CopilotKit is designed to work with any agent framework or custom agent implementation. This guide shows you how to integrate your own custom agents, whether you're building from scratch or using a framework not yet covered in our integrations. + +## Agent Interface + +Every agent in CopilotKit implements a simple async generator interface: + +```typescript +interface AgentConfig { + model: string; + async *run(context: AgentContext): AsyncGenerator; +} + +interface AgentContext { + messages: Message[]; + tools: Tool[]; + state?: any; + setState?: (state: any) => void; + executeTools: (toolName: string, args: any) => Promise; + forwardedProps?: Record; +} + +interface MessageChunk { + role: "user" | "assistant" | "system" | "tool"; + content: string; + name?: string; +} +``` + +## Basic Custom Agent + +Here's a minimal custom agent: + +```typescript +// app/api/copilotkit/route.ts +import { createCopilotRuntimeHandler } from "@copilotkitnext/runtime"; + +export const POST = createCopilotRuntimeHandler({ + agents: { + custom: { + model: "custom-agent-v1", + async *run({ messages, tools, executeTools }) { + // Your custom agent logic here + + // 1. Process the messages + const latestMessage = messages[messages.length - 1]; + + // 2. Generate a response + const response = await yourCustomAILogic(latestMessage.content); + + // 3. Check if tools need to be called + if (shouldCallTool(response)) { + const toolResult = await executeTools("toolName", { + /* args */ + }); + + // Process tool result and continue + const finalResponse = await processToolResult(toolResult); + + yield { + role: "assistant", + content: finalResponse, + }; + } else { + // 4. Yield the response + yield { + role: "assistant", + content: response, + }; + } + }, + }, + }, +}); +``` + +## Streaming Custom Agent + +Implement streaming for better UX: + +```typescript +async *run({ messages, tools }) { + const stream = await yourStreamingAPI({ + messages, + tools, + }); + + for await (const chunk of stream) { + yield { + role: "assistant", + content: chunk.text, + }; + } +} +``` + +## Custom Agent with External API + +Integrate with an external API: + +```typescript +async *run({ messages, tools, executeTools }) { + const apiUrl = process.env.CUSTOM_AGENT_URL; + const apiKey = process.env.CUSTOM_AGENT_KEY; + + const response = await fetch(`${apiUrl}/chat`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${apiKey}`, + }, + body: JSON.stringify({ + messages, + tools: tools.map(tool => ({ + name: tool.name, + description: tool.description, + parameters: tool.parameters, + })), + }), + }); + + const reader = response.body?.getReader(); + const decoder = new TextDecoder(); + + if (!reader) throw new Error('No response body'); + + while (true) { + const { done, value } = await reader.read(); + if (done) break; + + const text = decoder.decode(value); + yield { + role: 'assistant', + content: text, + }; + } +} +``` + +## Tool Calling + +Implement tool calling in your custom agent: + +```typescript +async *run({ messages, tools, executeTools }) { + // Your agent decides which tool to call + const toolDecision = await yourAgentDecision(messages, tools); + + if (toolDecision.shouldCallTool) { + // Execute the tool + const result = await executeTools( + toolDecision.toolName, + toolDecision.arguments + ); + + // Add tool result to conversation + yield { + role: "tool", + name: toolDecision.toolName, + content: JSON.stringify(result), + }; + + // Continue conversation with tool result + const followUp = await yourAgentContinue(messages, result); + + yield { + role: "assistant", + content: followUp, + }; + } else { + // Regular response + const response = await yourAgentResponse(messages); + yield { + role: "assistant", + content: response, + }; + } +} +``` + +## State Management + +Integrate with CopilotKit's shared state: + +```typescript +async *run({ messages, tools, state, setState }) { + // Read current state + const currentData = state?.data || {}; + + // Your agent logic + const response = await processWithState(messages, currentData); + + // Update state + setState({ + data: { + ...currentData, + lastUpdate: new Date().toISOString(), + processedCount: (currentData.processedCount || 0) + 1, + }, + }); + + yield { + role: "assistant", + content: response, + }; +} +``` + +## Error Handling + +Implement robust error handling: + +```typescript +async *run({ messages, tools, executeTools }) { + try { + const response = await yourAgentLogic(messages, tools); + + yield { + role: "assistant", + content: response, + }; + } catch (error) { + console.error('Agent error:', error); + + // Return a user-friendly error message + yield { + role: "assistant", + content: "I encountered an error processing your request. Please try again.", + }; + + // Optionally, log to your error tracking service + if (process.env.NODE_ENV === 'production') { + await logError(error); + } + } +} +``` + +## Advanced Examples + +### Multi-Step Reasoning Agent + +```typescript +async *run({ messages, tools, executeTools }) { + // Step 1: Analyze the request + yield { + role: "assistant", + content: "Let me think about this...", + }; + + const analysis = await analyzeRequest(messages); + + // Step 2: Gather information + if (analysis.needsToolUse) { + yield { + role: "assistant", + content: `I'll need to ${analysis.toolDescription}`, + }; + + const toolResult = await executeTools( + analysis.toolName, + analysis.toolArgs + ); + + // Step 3: Synthesize response + yield { + role: "assistant", + content: "Based on what I found...", + }; + + const finalResponse = await synthesize(analysis, toolResult); + + yield { + role: "assistant", + content: finalResponse, + }; + } else { + const directResponse = await respond(analysis); + yield { + role: "assistant", + content: directResponse, + }; + } +} +``` + +### Agent with Memory + +```typescript +import { Redis } from 'ioredis'; + +const redis = new Redis(process.env.REDIS_URL); + +async *run({ messages, tools, forwardedProps }) { + const userId = forwardedProps?.userId as string; + + // Load conversation history from memory + const history = await redis.get(`conversation:${userId}`); + const pastMessages = history ? JSON.parse(history) : []; + + // Include history in processing + const allMessages = [...pastMessages, ...messages]; + const response = await yourAgentLogic(allMessages, tools); + + // Save to memory + await redis.set( + `conversation:${userId}`, + JSON.stringify([...allMessages, { role: 'assistant', content: response }]) + ); + + yield { + role: "assistant", + content: response, + }; +} +``` + +### Agent with Rate Limiting + +```typescript +import { Ratelimit } from '@upstash/ratelimit'; +import { Redis } from '@upstash/redis'; + +const redis = new Redis({ + url: process.env.UPSTASH_REDIS_URL!, + token: process.env.UPSTASH_REDIS_TOKEN!, +}); + +const ratelimit = new Ratelimit({ + redis, + limiter: Ratelimit.slidingWindow(10, '1 m'), // 10 requests per minute +}); + +async *run({ messages, forwardedProps }) { + const userId = forwardedProps?.userId as string || 'anonymous'; + + // Check rate limit + const { success } = await ratelimit.limit(userId); + + if (!success) { + yield { + role: "assistant", + content: "You've reached the rate limit. Please wait a moment before trying again.", + }; + return; + } + + // Normal agent logic + const response = await yourAgentLogic(messages); + + yield { + role: "assistant", + content: response, + }; +} +``` + +## Testing Your Custom Agent + +Create tests for your custom agent: + +```typescript +import { describe, it, expect } from 'vitest'; + +describe('Custom Agent', () => { + it('should respond to messages', async () => { + const agent = createCustomAgent(); + + const results = []; + for await (const chunk of agent.run({ + messages: [{ role: 'user', content: 'Hello' }], + tools: [], + executeTools: async () => ({}), + })) { + results.push(chunk); + } + + expect(results).toHaveLength(1); + expect(results[0].role).toBe('assistant'); + expect(results[0].content).toBeTruthy(); + }); + + it('should execute tools', async () => { + const agent = createCustomAgent(); + const mockExecuteTools = vi.fn().mockResolvedValue({ result: 'success' }); + + const results = []; + for await (const chunk of agent.run({ + messages: [{ role: 'user', content: 'Use the tool' }], + tools: [{ name: 'testTool', description: 'Test', parameters: {} }], + executeTools: mockExecuteTools, + })) { + results.push(chunk); + } + + expect(mockExecuteTools).toHaveBeenCalled(); + }); +}); +``` + +## Best Practices + +### 1. Always Stream Responses + +Provide immediate feedback: + +```typescript +async *run({ messages }) { + // Bad: Wait for full response + const response = await getLongResponse(messages); + yield { role: 'assistant', content: response }; + + // Good: Stream chunks + for await (const chunk of getStreamingResponse(messages)) { + yield { role: 'assistant', content: chunk }; + } +} +``` + +### 2. Handle Context Window Limits + +Manage message history: + +```typescript +async *run({ messages }) { + // Keep only last N messages + const recentMessages = messages.slice(-10); + + const response = await yourAgentLogic(recentMessages); + yield { role: 'assistant', content: response }; +} +``` + +### 3. Validate Tool Parameters + +Ensure tool calls are valid: + +```typescript +async *run({ messages, tools, executeTools }) { + const toolCall = extractToolCall(messages); + + if (toolCall) { + // Validate parameters + const tool = tools.find(t => t.name === toolCall.name); + if (!tool) { + yield { + role: 'assistant', + content: `Tool "${toolCall.name}" not found.`, + }; + return; + } + + // Execute with validated parameters + const result = await executeTools(toolCall.name, toolCall.args); + // Continue... + } +} +``` + +### 4. Log for Debugging + +Add comprehensive logging: + +```typescript +async *run({ messages, tools }) { + console.log('[Agent] Starting with', messages.length, 'messages'); + + try { + const response = await yourAgentLogic(messages, tools); + console.log('[Agent] Generated response:', response.substring(0, 100)); + + yield { role: 'assistant', content: response }; + } catch (error) { + console.error('[Agent] Error:', error); + throw error; + } +} +``` + +## Examples + + + + Basic custom agent implementation + + + Integrate external AI API + + + Agent with persistent memory + + + Complex reasoning agent + + + +## Next Steps + + + + Add interactive tools + + + Sync state with agents + + + Understand the architecture + + + diff --git a/apps/docs/integrations/langgraph.mdx b/apps/docs/integrations/langgraph.mdx new file mode 100644 index 00000000..f92fb2e3 --- /dev/null +++ b/apps/docs/integrations/langgraph.mdx @@ -0,0 +1,116 @@ +--- +title: LangGraph Integration +description: Integrate CopilotKit with LangGraph agents +icon: "diagram-project" +--- + +## Overview + +LangGraph is a powerful framework for building stateful, multi-actor applications with LLMs. CopilotKit integrates seamlessly with LangGraph agents using the `@ag-ui/langgraph` integration package. + +This guide shows you how to connect your LangGraph agents to CopilotKit. + +## Prerequisites + +- Node.js 18+ +- A deployed LangGraph agent (or running locally) +- LangSmith API key (if using LangGraph Platform) + +## Setup + +### 1. Install Dependencies + +First, install the necessary packages: + +```bash +pnpm add @copilotkitnext/runtime @ag-ui/langgraph ai +``` + +### 2. Configure Your Runtime Endpoint + +Create a runtime endpoint (e.g., `src/app/api/copilotkit/[[...slug]]/route.ts` for Next.js App Router) and use the `LangGraphAgent` class to connect to your deployed LangGraph agent. + +```typescript +// src/app/api/copilotkit/[[...slug]]/route.ts +import { CopilotRuntime, createCopilotEndpoint, InMemoryAgentRunner } from "@copilotkitnext/runtime"; +import { LangGraphAgent } from "@ag-ui/langgraph"; +import { handle } from "hono/vercel"; + +// Connect to your LangGraph deployment +const agent = new LangGraphAgent({ + deploymentUrl: "https://your-langgraph-deployment-url.com", // Your LangGraph agent URL + langsmithApiKey: process.env.LANGSMITH_API_KEY, // Only needed for LangGraph Platform deployments + graphId: "my_agent", // Usually the same as your agent name +}); + +const runtime = new CopilotRuntime({ + agents: { + default: agent, // Register your LangGraph agent + }, + runner: new InMemoryAgentRunner(), +}); + +const app = createCopilotEndpoint({ + runtime, + basePath: "/api/copilotkit", +}); + +export const GET = handle(app); +export const POST = handle(app); +``` + +### 3. Connect to the Frontend + +In your React or Angular application, connect to this runtime endpoint using `CopilotKitProvider`: + +```typescript +// React example +import { CopilotKitProvider } from "@copilotkitnext/react"; + +function App() { + return ( + + {/* Your app components */} + + ); +} +``` + +## LangGraphAgent Configuration + +The `LangGraphAgent` class accepts the following configuration options: + +- `deploymentUrl` (required): The URL of your deployed LangGraph agent +- `langsmithApiKey` (optional): Your LangSmith API key (only required for LangGraph Platform deployments) +- `graphId` (required): The ID of your graph, usually the same as your agent name +- `headers` (optional): Additional HTTP headers to include in requests + +## Python Integration + +If you're building your LangGraph agent in Python, you can use the `ag_ui_langgraph` package to handle AG-UI event streaming automatically: + +```bash +pip install ag-ui-langgraph +``` + +Then in your Python code: + +```python +from langgraph.graph import StateGraph +from ag_ui_langgraph import LangGraphAgent + +# Define your LangGraph workflow +workflow = StateGraph(...) +# ... build your graph ... + +# Wrap it with AG-UI support +agent = LangGraphAgent(workflow) + +# The agent will automatically handle AG-UI event streaming +``` + +## Next Steps + +- Learn about [Frontend Actions](/guides/frontend-actions) +- Explore [Shared State](/guides/shared-state) +- Implement [Human-in-the-loop](/guides/human-in-the-loop) diff --git a/apps/docs/integrations/mastra.mdx b/apps/docs/integrations/mastra.mdx new file mode 100644 index 00000000..c58bbbd2 --- /dev/null +++ b/apps/docs/integrations/mastra.mdx @@ -0,0 +1,149 @@ +--- +title: Mastra Integration +description: Integrate CopilotKit with Mastra agents +icon: "wand-magic-sparkles" +--- + +## Overview + +Mastra is a modern framework for building AI agents with powerful orchestration capabilities. CopilotKit integrates seamlessly with Mastra agents using the `@ag-ui/mastra` integration package. + +This guide shows you how to connect your Mastra agents to CopilotKit. + +## Prerequisites + +- Node.js 18+ +- A Mastra instance with defined agents +- OpenAI API key (or your preferred LLM provider) + +## Setup + +### 1. Install Dependencies + +First, install the necessary packages: + +```bash +pnpm add @copilotkitnext/runtime @ag-ui/mastra @mastra/client-js ai +``` + +### 2. Create Your Mastra Instance + +First, set up your Mastra instance with your agents: + +```typescript +// src/mastra/index.ts +import { Mastra } from "@mastra/core"; +import { createAgent } from "@mastra/core/agents"; + +export const mastra = new Mastra({ + agents: { + myAgent: createAgent({ + name: "My Agent", + instructions: "You are a helpful AI assistant.", + model: { + provider: "openai", + name: "gpt-4o", + toolChoice: "auto", + }, + // ... other agent configuration + }), + }, +}); +``` + +### 3. Configure Your Runtime Endpoint + +Create a runtime endpoint (e.g., `src/app/api/copilotkit/[[...slug]]/route.ts` for Next.js App Router) and use the `MastraAgent` helper to connect your Mastra agents. + +```typescript +// src/app/api/copilotkit/[[...slug]]/route.ts +import { CopilotRuntime, createCopilotEndpoint, InMemoryAgentRunner } from "@copilotkitnext/runtime"; +import { MastraAgent } from "@ag-ui/mastra"; +import { mastra } from "@/mastra"; // Import your Mastra instance +import { handle } from "hono/vercel"; + +// Automatically get all agents from your Mastra instance +const agents = MastraAgent.getLocalAgents({ mastra }); + +const runtime = new CopilotRuntime({ + agents, // Register all your Mastra agents + runner: new InMemoryAgentRunner(), +}); + +const app = createCopilotEndpoint({ + runtime, + basePath: "/api/copilotkit", +}); + +export const GET = handle(app); +export const POST = handle(app); +``` + +### 4. Connect to the Frontend + +In your React or Angular application, connect to this runtime endpoint using `CopilotKitProvider`. If you have multiple agents, specify which one to use: + +```typescript +// React example +import { CopilotKitProvider } from "@copilotkitnext/react"; + +function App() { + return ( + + {/* Your app components */} + + ); +} +``` + +## Using Mastra Client (Remote Agents) + +If you're running Mastra agents remotely, you can use the `MastraClient` to connect to them: + +```typescript +// src/app/api/copilotkit/[[...slug]]/route.ts +import { CopilotRuntime, createCopilotEndpoint, InMemoryAgentRunner } from "@copilotkitnext/runtime"; +import { MastraAgent } from "@ag-ui/mastra"; +import { MastraClient } from "@mastra/client-js"; +import { handle } from "hono/vercel"; + +// Connect to a remote Mastra instance +const mastraClient = new MastraClient({ + url: "https://your-mastra-deployment.com", + apiKey: process.env.MASTRA_API_KEY, +}); + +// Get agents from the remote instance +const agents = MastraAgent.getRemoteAgents({ mastraClient }); + +const runtime = new CopilotRuntime({ + agents, + runner: new InMemoryAgentRunner(), +}); + +const app = createCopilotEndpoint({ + runtime, + basePath: "/api/copilotkit", +}); + +export const GET = handle(app); +export const POST = handle(app); +``` + +## MastraAgent Helpers + +The `MastraAgent` class provides two helper methods: + +- `MastraAgent.getLocalAgents({ mastra })`: Automatically registers all agents from a local Mastra instance +- `MastraAgent.getRemoteAgents({ mastraClient })`: Automatically registers all agents from a remote Mastra instance + +Both methods return an object where keys are agent names and values are agent instances compatible with CopilotRuntime. + +## Next Steps + +- Learn about [Frontend Actions](/guides/frontend-actions) +- Explore [Shared State](/guides/shared-state) +- Implement [Human-in-the-Loop](/guides/human-in-the-loop) diff --git a/apps/docs/integrations/overview.mdx b/apps/docs/integrations/overview.mdx new file mode 100644 index 00000000..588a9793 --- /dev/null +++ b/apps/docs/integrations/overview.mdx @@ -0,0 +1,266 @@ +--- +title: Agent Integrations +description: Connect CopilotKit with any agent framework or LLM +icon: "plug" +--- + +## Overview + +CopilotKit is designed to work with any agent framework or LLM provider. The integration happens at the **runtime layer**, which means your frontend code remains the same regardless of which agent framework you use. + +This architecture gives you: +- **Framework flexibility** - Switch agent frameworks without changing frontend code +- **Multi-agent support** - Use different frameworks for different agents in the same app +- **Simple integration** - Most integrations are just runtime configuration + +## How Agent Integrations Work + +``` +┌─────────────────────────────────────────┐ +│ Frontend (React/Angular) │ +│ - CopilotChat component │ +│ - Frontend tools │ +│ - Shared state │ +└────────────────┬────────────────────────┘ + │ + │ HTTP/WebSocket + │ +┌────────────────▼────────────────────────┐ +│ CopilotRuntime │ +│ - Handles requests │ +│ - Routes to agents │ +│ - Manages tool calls │ +└────────────────┬────────────────────────┘ + │ + ┌────────┴────────┐ + │ │ +┌───────▼──────┐ ┌──────▼────────┐ +│ Agent 1 │ │ Agent 2 │ +│ (LangGraph) │ │ (OpenAI) │ +└──────────────┘ └───────────────┘ +``` + +## Integration Points + +### 1. Runtime Configuration + +The main integration point is in your runtime endpoint where you configure your agents: + +```typescript +// app/api/copilotkit/route.ts (Next.js example) +import { createCopilotRuntimeHandler } from "@copilotkitnext/runtime"; + +export const POST = createCopilotRuntimeHandler({ + agents: { + assistant: { + // Your agent configuration here + }, + }, +}); +``` + +### 2. Agent Implementation + +Each agent framework has a specific way to implement the agent: + +- **Direct LLM** (OpenAI, Anthropic): Call the API directly +- **LangGraph**: Connect to LangGraph graph +- **Mastra**: Use Mastra agent instance +- **CrewAI**: Connect to CrewAI crew +- **Custom**: Implement your own agent interface + +### 3. Frontend (Same for All) + +Your frontend code is identical regardless of agent framework: + +```tsx + + + +``` + +## Available Integrations + + + + Direct integration with OpenAI's GPT models + + + Direct integration with Anthropic's Claude models + + + Connect to LangGraph agents and graphs + + + Integrate with Mastra agent framework + + + Connect to CrewAI crews and agents + + + Integrate with LlamaIndex agents + + + Build your own custom agent integration + + + +## Quick Comparison + +| Framework | Best For | Complexity | Streaming | Multi-Agent | +|-----------|----------|------------|-----------|-------------| +| **OpenAI** | Simple chatbots, quick prototypes | Low | ✅ | ✅ | +| **Anthropic** | Long context, complex reasoning | Low | ✅ | ✅ | +| **LangGraph** | Complex workflows, state machines | Medium | ✅ | ✅ | +| **Mastra** | Modern TypeScript agents | Medium | ✅ | ✅ | +| **CrewAI** | Multi-agent collaboration | Medium | ✅ | ✅ | +| **LlamaIndex** | RAG, document Q&A | Medium | ✅ | ✅ | +| **Custom** | Specific requirements | Varies | ✅ | ✅ | + +## Choosing an Integration + +### Use Direct LLM (OpenAI/Anthropic) when: +- You're building a simple chatbot +- You want to get started quickly +- You don't need complex agent logic +- You want full control over the LLM interaction + +### Use LangGraph when: +- You need complex, stateful workflows +- You want graph-based agent orchestration +- You're building multi-step reasoning systems +- You need human-in-the-loop checkpoints + +### Use Mastra when: +- You prefer TypeScript for agent logic +- You want a modern, lightweight framework +- You need good observability and debugging +- You're building production applications + +### Use CrewAI when: +- You need multiple specialized agents +- You want role-based agent collaboration +- You're building complex multi-agent systems +- You prefer Python for agent logic + +### Use LlamaIndex when: +- You're building RAG applications +- You need document Q&A capabilities +- You want to query over knowledge bases +- You need advanced retrieval strategies + +## Integration Features + +All integrations support these CopilotKit features: + + + + All agent frameworks can call frontend tools + + + Bidirectional state synchronization works with any framework + + + Request user approval regardless of agent framework + + + Render dynamic UI components from any agent + + + Real-time streaming responses + + + Execute tools and return results + + + +## Multi-Agent Setup + +You can use multiple agent frameworks in the same application: + +```typescript +export const POST = createCopilotRuntimeHandler({ + agents: { + // OpenAI for general chat + chatbot: { + model: "gpt-4", + async *run({ messages }) { + // OpenAI implementation + }, + }, + + // LangGraph for complex workflow + workflow: { + async *run({ messages }) { + // LangGraph implementation + }, + }, + + // Mastra for data analysis + analyst: { + async *run({ messages }) { + // Mastra implementation + }, + }, + }, +}); +``` + +Then use different agents in your frontend: + +```tsx +// General chatbot +const chatAgent = useAgent("chatbot"); + +// Complex workflow agent +const workflowAgent = useAgent("workflow"); + +// Data analysis agent +const analystAgent = useAgent("analyst"); +``` + +## Environment Variables + +Most integrations require API keys. Store them in `.env`: + +```bash +# OpenAI +OPENAI_API_KEY=sk-... + +# Anthropic +ANTHROPIC_API_KEY=sk-ant-... + +# LangGraph (if using LangSmith) +LANGSMITH_API_KEY=lsv2_... + +# Your custom keys +CUSTOM_API_KEY=... +``` + +## Next Steps + +Choose an integration to get started: + + + + Quick start + + + Advanced workflows + + + TypeScript agents + + + +## Need Help? + + + + Ask about integrations + + + See integration examples + + + diff --git a/apps/docs/introduction.mdx b/apps/docs/introduction.mdx index 704ae384..ae423240 100644 --- a/apps/docs/introduction.mdx +++ b/apps/docs/introduction.mdx @@ -1,64 +1,158 @@ --- -title: CopilotKit VNext Documentation -description: "CopilotKit VNext Documentation" +title: Introduction to CopilotKit +description: "The next generation framework for building AI-powered applications with React and Angular" +icon: "sparkles" --- -## API Reference +## What is CopilotKit? -### Core +CopilotKit is a powerful, framework-agnostic toolkit for building AI-powered applications. It provides a seamless way to integrate intelligent AI agents into your React and Angular applications, enabling you to create context-aware, interactive AI experiences. - - Core CopilotKit class - +CopilotKit connects your application's logic, state, and user context to AI agents, giving you the tools to build, deploy, and monitor AI-assisted features that feel intuitive, helpful, and deeply integrated into your user experience. - - Proxied runtime agent for CopilotKit - +## Why CopilotKit? - - Frontend tool utilities - + + + Works seamlessly with React and Angular, with consistent APIs across both frameworks + + + Built from the ground up to support agent-driven user experiences and real-time interactions + + + Full TypeScript support with comprehensive type definitions for all APIs + + + Bring your own LLMs, tools, and agents - no vendor lock-in + + -### React +## Key Features -#### Providers +### Agentic Chat UI +Create intelligent chat interfaces powered by AI agents that can execute tools, maintain context, and provide interactive experiences. - - Main provider for CopilotKit React integration + + Build conversational interfaces that go beyond simple text exchange - - Configuration provider for CopilotChat +### Frontend Actions +Enable AI agents to directly interact with and update your application's user interface through declarative frontend tools. + + + Connect your agent's decision-making to your frontend's interactive elements -#### Components +### Shared State +Create a two-way connection between your UI and agent state, enabling real-time synchronization and collaborative experiences. - - Chat component for CopilotKit + + Synchronize application state between your UI and AI agents -#### Hooks +### Human in the Loop +Allow agents to request human input or approval during execution, making AI systems more reliable and trustworthy. - - Main hook for CopilotKit functionality + + Build AI systems that combine automation with human judgment - - Hook for agent interactions - +### Generative UI +Create dynamic, AI-driven user interfaces that adapt and respond to user interactions and agent state in real-time. - - Hook for agent context management + + Build adaptive interfaces that evolve with user needs - - Hook for frontend tools - +## Get Started + + + + Get started with CopilotKit in your React application + + + Get started with CopilotKit in your Angular application + + + +## Architecture + +CopilotKit is thoughtfully architected to scale with you, your teams, and your product. The framework consists of several key components: + +- **Core**: Framework-agnostic core functionality for managing agents, tools, and state +- **React Package**: React-specific components, hooks, and providers +- **Angular Package**: Angular-specific components, services, and directives +- **Runtime**: Server-side runtime for handling agent execution and tool calls - - Hook for human-in-the-loop functionality + + Understand how CopilotKit works under the hood - - Hook for rendering tool calls +## API Reference + +### Core + + + + Core CopilotKit class + + + Proxied runtime agent + + + Frontend tool utilities + + + +### React + +#### Providers + + + + Main provider for React integration + + + Configuration provider for CopilotChat + + + +#### Components + + + Chat component for CopilotKit + +#### Hooks + + + + Main hook for CopilotKit functionality + + + Hook for agent interactions + + + Hook for agent context management + + + Hook for frontend tools + + + Hook for human-in-the-loop functionality + + + Hook for rendering tool calls + + + +## Community & Support + + + + Join our Discord community for help and discussions + + + View the source code and contribute + + diff --git a/apps/docs/quickstart/angular.mdx b/apps/docs/quickstart/angular.mdx new file mode 100644 index 00000000..123a8bbe --- /dev/null +++ b/apps/docs/quickstart/angular.mdx @@ -0,0 +1,398 @@ +--- +title: Angular Quickstart +description: Get started with CopilotKit in your Angular application +icon: "angular" +--- + +## Prerequisites + +Before you begin, make sure you have: + +- Node.js 18+ installed +- Angular 16+ application (or create one with Angular CLI) +- An OpenAI API key (or another LLM provider) + +## Installation + +Install CopilotKit packages using your preferred package manager: + + +```bash npm +npm install @copilotkitnext/core @copilotkitnext/angular @copilotkitnext/runtime +``` + +```bash pnpm +pnpm add @copilotkitnext/core @copilotkitnext/angular @copilotkitnext/runtime +``` + +```bash yarn +yarn add @copilotkitnext/core @copilotkitnext/angular @copilotkitnext/runtime +``` + + +You'll also need to install Zod for schema validation: + + +```bash npm +npm install zod +``` + +```bash pnpm +pnpm add zod +``` + +```bash yarn +yarn add zod +``` + + +## Step 1: Set Up the Runtime + +First, create a runtime endpoint in your backend. This example uses Express: + +```typescript +// server/index.ts +import express from 'express'; +import { createCopilotRuntimeHandler } from '@copilotkitnext/runtime'; +import { OpenAI } from 'openai'; + +const app = express(); +const openai = new OpenAI({ + apiKey: process.env.OPENAI_API_KEY, +}); + +app.use(express.json()); + +app.post('/api/copilotkit', createCopilotRuntimeHandler({ + agents: { + assistant: { + model: 'gpt-4', + async *run({ messages, tools }) { + const response = await openai.chat.completions.create({ + model: 'gpt-4', + messages, + tools, + stream: true, + }); + + for await (const chunk of response) { + yield chunk; + } + }, + }, + }, +})); + +app.listen(3000, () => { + console.log('Runtime server running on http://localhost:3000'); +}); +``` + + +For other frameworks or deployment options, check out our [Runtime Setup Guide](/concepts/runtime-setup). + + +## Step 2: Import the Module + +Import the `CopilotKitModule` in your Angular application: + +```typescript +// app.module.ts +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { CopilotKitModule } from '@copilotkitnext/angular'; + +import { AppComponent } from './app.component'; + +@NgModule({ + declarations: [AppComponent], + imports: [ + BrowserModule, + CopilotKitModule.forRoot({ + runtimeUrl: 'http://localhost:3000/api/copilotkit', + }), + ], + providers: [], + bootstrap: [AppComponent], +}) +export class AppModule {} +``` + +For standalone components (Angular 14+): + +```typescript +// app.config.ts +import { ApplicationConfig } from '@angular/core'; +import { provideCopilotKit } from '@copilotkitnext/angular'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideCopilotKit({ + runtimeUrl: 'http://localhost:3000/api/copilotkit', + }), + ], +}; +``` + +## Step 3: Add the Chat Component + +Add the `copilot-chat` component to your template: + +```typescript +// app.component.ts +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + template: ` +
+

My AI-Powered App

+ + +
+ +
+ + + +
+ `, + styles: [` + .container { + padding: 2rem; + } + `], +}) +export class AppComponent {} +``` + +## Step 4: Add Frontend Tools + +Create frontend tools that your agent can use to interact with your UI: + +```typescript +// todo-list.component.ts +import { Component, OnInit } from '@angular/core'; +import { FrontendToolService } from '@copilotkitnext/angular'; +import { z } from 'zod'; + +@Component({ + selector: 'app-todo-list', + template: ` +
+

Todo List

+
    +
  • + {{ todo }} + +
  • +
+ +
+ `, +}) +export class TodoListComponent implements OnInit { + todos: string[] = []; + + constructor(private frontendToolService: FrontendToolService) {} + + ngOnInit() { + // Register tool for adding todos + this.frontendToolService.registerTool({ + name: 'addTodo', + description: 'Add a new todo item to the list', + parameters: z.object({ + task: z.string().describe('The task to add'), + }), + handler: async ({ task }) => { + this.todos.push(task); + return `Added "${task}" to the todo list`; + }, + }); + + // Register tool for removing todos + this.frontendToolService.registerTool({ + name: 'removeTodo', + description: 'Remove a todo item from the list', + parameters: z.object({ + index: z.number().describe('The index of the todo to remove'), + }), + handler: async ({ index }) => { + const task = this.todos[index]; + this.todos.splice(index, 1); + return `Removed "${task}" from the todo list`; + }, + }); + } + + removeTodo(index: number) { + this.todos.splice(index, 1); + } +} +``` + +Now you can ask the agent to "Add a todo: Buy groceries" and it will use the `addTodo` tool! + +## Step 5: Configure the Chat (Optional) + +Customize the chat interface using the configuration service: + +```typescript +// app.component.ts +import { Component, OnInit } from '@angular/core'; +import { CopilotChatConfigService } from '@copilotkitnext/angular'; + +@Component({ + selector: 'app-root', + template: ` +
+ +
+ `, +}) +export class AppComponent implements OnInit { + constructor(private chatConfig: CopilotChatConfigService) {} + + ngOnInit() { + this.chatConfig.setConfig({ + title: 'AI Assistant', + placeholder: 'Ask me anything...', + showWelcomeMessage: true, + welcomeMessage: 'Hello! I can help you manage your todos. Try asking me to add or remove tasks!', + }); + } +} +``` + +## Step 6: Use Shared State (Optional) + +Access and modify agent state from your components: + +```typescript +// task-progress.component.ts +import { Component, OnInit } from '@angular/core'; +import { AgentContextService } from '@copilotkitnext/angular'; + +@Component({ + selector: 'app-task-progress', + template: ` +
+

Current Task: {{ state.currentTask }}

+ +

Status: {{ state.status }}

+ + +
+ `, +}) +export class TaskProgressComponent implements OnInit { + state: any; + + constructor(private agentContext: AgentContextService) {} + + ngOnInit() { + this.agentContext.getState('taskAgent').subscribe((state) => { + this.state = state; + }); + } + + markHighPriority() { + this.agentContext.setState('taskAgent', { priority: 'high' }); + } +} +``` + +## Next Steps + +Congratulations! You've set up CopilotKit in your Angular application. Here's what to explore next: + + + + Learn more about building conversational interfaces + + + Explore advanced frontend tool patterns + + + Synchronize state between UI and agents + + + Add approval workflows to your agents + + + +## Common Issues + +### Module Not Found + +If you see module import errors, make sure: + +1. You've installed all required packages +2. Your `tsconfig.json` has the correct module resolution settings +3. You've imported `CopilotKitModule` or used `provideCopilotKit` + +### Runtime Connection Failed + +If you see connection errors, make sure: + +1. Your runtime endpoint is running and accessible +2. The `runtimeUrl` matches your endpoint URL +3. CORS is properly configured for cross-origin requests + +### Tools Not Being Called + +If your agent isn't using your frontend tools: + +1. Ensure tool descriptions are clear and specific +2. Check that parameter schemas are well-defined +3. Verify the agent has the right context to know when to use the tool +4. Make sure tools are registered in `ngOnInit` or constructor + +### Change Detection Issues + +If UI updates aren't reflected: + +1. Use `ChangeDetectorRef` to manually trigger change detection +2. Consider using `NgZone` for async operations +3. Ensure you're updating component properties correctly + +```typescript +import { ChangeDetectorRef } from '@angular/core'; + +constructor( + private frontendToolService: FrontendToolService, + private cdr: ChangeDetectorRef +) {} + +handler: async ({ task }) => { + this.todos.push(task); + this.cdr.detectChanges(); // Trigger change detection + return `Added "${task}"`; +} +``` + +## Example Projects + + + + Simple todo list with AI assistance + + + Interactive dashboard with data visualization + + + +## Need Help? + + + + Join our Discord for help and discussions + + + Report bugs or request features + + + + diff --git a/apps/docs/quickstart/react.mdx b/apps/docs/quickstart/react.mdx new file mode 100644 index 00000000..f68e11ba --- /dev/null +++ b/apps/docs/quickstart/react.mdx @@ -0,0 +1,284 @@ +--- +title: React Quickstart +description: Get started with CopilotKit in your React application +icon: "react" +--- + +## Prerequisites + +Before you begin, make sure you have: + +- Node.js 18+ installed +- A React application (or create one with Vite, Next.js, or Create React App) +- An OpenAI API key (or another LLM provider) + +## Installation + +Install CopilotKit packages using your preferred package manager: + + +```bash npm +npm install @copilotkitnext/core @copilotkitnext/react @copilotkitnext/runtime +``` + +```bash pnpm +pnpm add @copilotkitnext/core @copilotkitnext/react @copilotkitnext/runtime +``` + +```bash yarn +yarn add @copilotkitnext/core @copilotkitnext/react @copilotkitnext/runtime +``` + + +You'll also need to install Zod for schema validation: + + +```bash npm +npm install zod +``` + +```bash pnpm +pnpm add zod +``` + +```bash yarn +yarn add zod +``` + + +## Step 1: Set Up the Runtime + +First, create a runtime endpoint in your backend. This example uses Next.js App Router: + +```typescript +// app/api/copilotkit/route.ts +import { createCopilotRuntimeHandler } from "@copilotkitnext/runtime"; +import { OpenAI } from "openai"; + +const openai = new OpenAI({ + apiKey: process.env.OPENAI_API_KEY, +}); + +export const POST = createCopilotRuntimeHandler({ + agents: { + assistant: { + model: "gpt-4", + async *run({ messages, tools }) { + const response = await openai.chat.completions.create({ + model: "gpt-4", + messages, + tools, + stream: true, + }); + + for await (const chunk of response) { + yield chunk; + } + }, + }, + }, +}); +``` + + +For other frameworks like Express or Fastify, check out our [Runtime Setup Guide](/concepts/runtime-setup). + + +## Step 2: Add the Provider + +Wrap your application with the `CopilotKitProvider`: + +```tsx +// app/layout.tsx or src/App.tsx +import { CopilotKitProvider } from "@copilotkitnext/react"; + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + + + {children} + + + + ); +} +``` + +## Step 3: Add the Chat Component + +Add the `CopilotChat` component to your page: + +```tsx +// app/page.tsx or src/App.tsx +"use client"; // For Next.js App Router + +import { CopilotChat } from "@copilotkitnext/react"; + +export default function Home() { + return ( +
+

My AI-Powered App

+ + {/* Your app content */} +
+ {/* ... */} +
+ + {/* CopilotKit Chat */} + +
+ ); +} +``` + +## Step 4: Add Frontend Tools + +Create frontend tools that your agent can use to interact with your UI: + +```tsx +"use client"; + +import { useFrontendTool } from "@copilotkitnext/react"; +import { z } from "zod"; +import { useState } from "react"; + +export default function TodoList() { + const [todos, setTodos] = useState([]); + + // Define a frontend tool for adding todos + useFrontendTool({ + name: "addTodo", + description: "Add a new todo item to the list", + parameters: z.object({ + task: z.string().describe("The task to add"), + }), + handler: async ({ task }) => { + setTodos((prev) => [...prev, task]); + return `Added "${task}" to the todo list`; + }, + }); + + // Define a frontend tool for removing todos + useFrontendTool({ + name: "removeTodo", + description: "Remove a todo item from the list", + parameters: z.object({ + index: z.number().describe("The index of the todo to remove"), + }), + handler: async ({ index }) => { + const task = todos[index]; + setTodos((prev) => prev.filter((_, i) => i !== index)); + return `Removed "${task}" from the todo list`; + }, + }); + + return ( +
+

Todo List

+
    + {todos.map((todo, index) => ( +
  • {todo}
  • + ))} +
+ +
+ ); +} +``` + +Now you can ask the agent to "Add a todo: Buy groceries" and it will use the `addTodo` tool! + +## Step 5: Configure the Chat (Optional) + +Customize the chat interface using `CopilotChatConfigurationProvider`: + +```tsx +import { CopilotChatConfigurationProvider } from "@copilotkitnext/react"; + +export default function App() { + return ( + + + + + + ); +} +``` + +## Next Steps + +Congratulations! You've set up CopilotKit in your React application. Here's what to explore next: + + + + Learn more about building conversational interfaces + + + Explore advanced frontend tool patterns + + + Synchronize state between UI and agents + + + Add approval workflows to your agents + + + +## Common Issues + +### Runtime Connection Failed + +If you see connection errors, make sure: + +1. Your runtime endpoint is running and accessible +2. The `runtimeUrl` prop matches your endpoint URL +3. CORS is properly configured if running on different domains + +### Tools Not Being Called + +If your agent isn't using your frontend tools: + +1. Ensure tool descriptions are clear and specific +2. Check that parameter schemas are well-defined +3. Verify the agent has the right context to know when to use the tool + +### TypeScript Errors + +Make sure you have the latest type definitions: + +```bash +npm install --save-dev @types/react @types/node +``` + +## Example Projects + + + + Simple todo list with AI assistance + + + Interactive dashboard with data visualization + + + +## Need Help? + + + + Join our Discord for help and discussions + + + Report bugs or request features + + + + diff --git a/apps/docs/reference/angular-agent-context.mdx b/apps/docs/reference/angular-agent-context.mdx new file mode 100644 index 00000000..9caaf4c7 --- /dev/null +++ b/apps/docs/reference/angular-agent-context.mdx @@ -0,0 +1,52 @@ +--- +title: Angular Agent Context Utilities +description: connectAgentContext function and copilotkitAgentContext directive +--- + +These utilities push Angular state into the CopilotKit agent context so models receive additional background +information. + +## connectAgentContext + +```ts +import { connectAgentContext } from "@copilotkitnext/angular"; + +connectAgentContext({ + description: "Active ticket", + value: JSON.stringify(ticket), +}); +``` + +- Accepts a `Context` object or a `Signal`. +- Automatically removes the context when the calling injector is destroyed. +- Throws if called outside an injector—pass `{ injector }` in places like standalone functions. + +### Passing a Signal + +```ts +const userContext = computed(() => ({ + description: "User info", + value: JSON.stringify(authStore.user()), +})); + +connectAgentContext(userContext); +``` + +## `copilotkitAgentContext` Directive + +Template-based alternative for binding context: + +```html +
+``` + +### Inputs + +- `[copilotkitAgentContext]` – Pass a full context object. +- `description` / `value` – Alternate syntax when you want to provide fields separately. + +The directive adds the context on init, updates it when inputs change, and removes it on destroy. diff --git a/apps/docs/reference/angular-copilot-chat.mdx b/apps/docs/reference/angular-copilot-chat.mdx new file mode 100644 index 00000000..0dff2056 --- /dev/null +++ b/apps/docs/reference/angular-copilot-chat.mdx @@ -0,0 +1,48 @@ +--- +title: +description: Angular component that renders the Copilot chat interface +--- + +`` is the primary Angular component for embedding CopilotKit. It mirrors the React `CopilotChat` +component—connecting to an agent, streaming messages, displaying suggestions, and exposing slots for customization. + +## Basic Usage + +```html + +``` + +## Inputs + +| Input | Type | Description | +| ------------- | ----------------------------------- | --------------------------------------------------- | +| `agentId` | `string` | Target agent (defaults to the value from provider). | +| `threadId` | `string` | Conversation thread ID (auto-generated if omitted). | +| `labels` | `Partial` | Customize UI strings (placeholders, buttons). | +| `chatView` | `SlotValue` | Override the entire chat view implementation. | +| `isModalDefaultOpen` | `boolean` | Whether popup/sidebar surfaces start open. | + +All additional attributes/inputs are forwarded to the underlying `CopilotChatView`. + +## Events + +- `copilotMessageSent` – Fires after a user message is submitted. +- `copilotSuggestionSelected` – Fires when the user clicks a suggestion. + +## Customization + +Override slots to tailor layout: + +```html + +``` + +You can also combine `` with `registerFrontendTool`, `registerRenderToolCall`, and Angular directives to +deliver a fully customized experience. diff --git a/apps/docs/reference/angular-copilotkit-service.mdx b/apps/docs/reference/angular-copilotkit-service.mdx new file mode 100644 index 00000000..a863eca0 --- /dev/null +++ b/apps/docs/reference/angular-copilotkit-service.mdx @@ -0,0 +1,48 @@ +--- +title: CopilotKit (Angular service) +description: Root injectable service that bridges CopilotKitCore into Angular apps +--- + +The `CopilotKit` service wraps `CopilotKitCore` and exposes Angular-friendly helpers for registering tools, HITL +handlers, and renderers. + +## Injecting the Service + +```ts +import { Component, inject } from "@angular/core"; +import { CopilotKit } from "@copilotkitnext/angular"; + +@Component({ + selector: "app-root", + template: ``, +}) +export class AppComponent { + private readonly copilotKit = inject(CopilotKit); + + ngOnInit() { + console.log(this.copilotKit.core.runtimeUrl); + } +} +``` + +## Key Properties + +- `core` – Underlying `CopilotKitCore` instance. +- `agents` – Signal listing currently registered agents. +- `toolCallRenderConfigs` – Signal of registered tool call renderers. +- `clientToolCallRenderConfigs` – Signal of registered frontend tool renderers. +- `humanInTheLoopToolRenderConfigs` – Signal of registered HITL renderers. + +## Helper Methods + +| Method | Description | +| ------------------------------- | -------------------------------------------------------- | +| `addFrontendTool(config)` | Registers a frontend tool (injects dependencies). | +| `addRenderToolCall(config)` | Registers a tool call renderer. | +| `addHumanInTheLoop(config)` | Registers a HITL renderer and adds it as a frontend tool.| +| `removeTool(name, agentId?)` | Removes a tool/renderer (works for frontend + HITL). | +| `getAgent(agentId)` | Retrieves an agent instance. | +| `updateRuntime(options)` | Update runtime URL, headers, properties, or agents. | + +These methods are used by the helper functions (`registerFrontendTool`, `registerHumanInTheLoop`, etc.), but you can +call them directly when you need lower-level control. diff --git a/apps/docs/reference/angular-directives.mdx b/apps/docs/reference/angular-directives.mdx new file mode 100644 index 00000000..8269efb9 --- /dev/null +++ b/apps/docs/reference/angular-directives.mdx @@ -0,0 +1,42 @@ +--- +title: Angular Directives +description: copilotkitAgentContext, stickToBottom, and tooltip directives +--- + +CopilotKit ships a few utility directives to simplify Angular integration. + +## `copilotkitAgentContext` + +See [Agent Context Utilities](/reference/angular-agent-context) for full details. This directive syncs template values to +the agent context. + +```html +
+``` + +## `stickToBottom` + +Wrapper around `use-stick-to-bottom` that keeps scrollable chat regions pinned to the bottom while new messages stream +in. + +```html +
+ +
+``` + +Combine with `copilotkitAgentContext` or the provided chat components for fully reactive layouts. + +## `tooltip` + +`tooltip` is a lightweight directive backing the built-in chat toolbar tooltips. Apply it to any element: + +```html + +``` + +Useful if you build custom toolbars and want consistent tooltip styling without pulling in another library. diff --git a/apps/docs/reference/angular-inject-agent-store.mdx b/apps/docs/reference/angular-inject-agent-store.mdx new file mode 100644 index 00000000..6cfe3239 --- /dev/null +++ b/apps/docs/reference/angular-inject-agent-store.mdx @@ -0,0 +1,50 @@ +--- +title: injectAgentStore +description: Angular signal that tracks agent state, messages, and run status +--- + +`injectAgentStore(agentId)` returns a reactive `Signal` that stays in sync with a CopilotKit +agent. It automatically subscribes to agent updates and tears down the subscription when the host injector is +destroyed. + +## Basic Usage + +```ts +import { Component, computed, inject } from "@angular/core"; +import { injectAgentStore } from "@copilotkitnext/angular"; + +@Component({ + standalone: true, + template: ` +
+

Messages: {{ agent.messages.length }}

+

Running: {{ store()?.isRunning() }}

+
+ `, +}) +export class AgentStateComponent { + readonly store = injectAgentStore("assistant"); +} +``` + +## AgentStore + +`AgentStore` exposes three read-only signals plus the underlying `AbstractAgent`: + +| Property | Type | Description | +| ------------ | ------------------------ | --------------------------------------- | +| `agent` | `AbstractAgent` | The underlying agent instance. | +| `messages()` | `Message[]` | Reactive list of messages. | +| `state()` | `unknown` | Shared state snapshot. | +| `isRunning()`| `boolean` | Whether the agent is currently running. | + +## Dynamic Agent IDs + +Pass a computed signal when the agent ID changes: + +```ts +const activeAgentId = computed(() => uiStore.selectedAgentId()); +const store = injectAgentStore(activeAgentId); +``` + +Each time the ID changes, `injectAgentStore` cleans up the previous subscription and wires the new agent. diff --git a/apps/docs/reference/angular-provide-copilotkit.mdx b/apps/docs/reference/angular-provide-copilotkit.mdx new file mode 100644 index 00000000..fd5158d5 --- /dev/null +++ b/apps/docs/reference/angular-provide-copilotkit.mdx @@ -0,0 +1,60 @@ +--- +title: provideCopilotKit +description: Angular provider for configuring CopilotKit runtime options +--- + +`provideCopilotKit` registers CopilotKit configuration at the Angular DI level. It’s the first step when wiring +CopilotKit into an Angular app. + +## Basic Usage (Stand-alone Config) + +```ts +// app.config.ts +import { ApplicationConfig } from "@angular/core"; +import { provideCopilotKit } from "@copilotkitnext/angular"; + +export const appConfig: ApplicationConfig = { + providers: [ + provideCopilotKit({ + runtimeUrl: "http://localhost:3000/api/copilotkit", + headers: { Authorization: `Bearer ${import.meta.env.NG_APP_API_KEY}` }, + }), + ], +}; +``` + +## Options + +| Option | Type | Description | +| ---------------- | ---------------------------------- | ----------------------------------------------- | +| `runtimeUrl` | `string` | Copilot runtime endpoint. | +| `headers` | `Record` | Default headers for runtime requests. | +| `properties` | `Record` | Arbitrary properties forwarded to agents. | +| `agents` | `Record` | Pre-seeded agents (useful for SSR/demos). | +| `tools` | `ClientTool[]` | Frontend tools registered on startup. | +| `renderToolCalls`| `RenderToolCallConfig[]` | Tool call renderers registered on startup. | +| `frontendTools` | `FrontendToolConfig[]` | Client tools registered on startup. | +| `humanInTheLoop` | `HumanInTheLoopConfig[]` | HITL tools registered on startup. | + +## Accessing the Config + +Use `injectCopilotKitConfig()` inside injectors to read the config: + +```ts +import { injectCopilotKitConfig } from "@copilotkitnext/angular"; + +const config = injectCopilotKitConfig(); +console.log(config.runtimeUrl); +``` + +## Updating the Runtime at Runtime + +The `CopilotKit` service exposes `updateRuntime`: + +```ts +import { inject } from "@angular/core"; +import { CopilotKit } from "@copilotkitnext/angular"; + +const copilotKit = inject(CopilotKit); +copilotKit.updateRuntime({ runtimeUrl: newUrl }); +``` diff --git a/apps/docs/reference/angular-register-tools.mdx b/apps/docs/reference/angular-register-tools.mdx new file mode 100644 index 00000000..107597c8 --- /dev/null +++ b/apps/docs/reference/angular-register-tools.mdx @@ -0,0 +1,51 @@ +--- +title: Angular Tool Registration Helpers +description: registerFrontendTool, registerHumanInTheLoop, and registerRenderToolCall +--- + +These helpers let you register Angular components as CopilotKit tools and renderers using Angular DI. They automatically +clean up registrations when the host component is destroyed. + +## registerFrontendTool + +```ts +registerFrontendTool({ + name: "set_theme", + description: "Switch UI theme", + parameters: z.object({ theme: z.enum(["light", "dark"]) }), + component: ThemeToolComponent, + handler: async ({ theme }) => { + themeService.setTheme(theme); + }, +}); +``` + +- Injects `CopilotKit` and `Injector` to bind the handler with Angular DI context. +- Automatically removes the tool when the current `DestroyRef` triggers. + +## registerRenderToolCall + +```ts +registerRenderToolCall({ + name: "search_docs", + args: z.object({ query: z.string() }), + component: SearchToolRendererComponent, +}); +``` + +Registers an Angular component to render tool call output. Component receives a reactive `toolCall` signal with args, +status, and result. + +## registerHumanInTheLoop + +```ts +registerHumanInTheLoop({ + name: "approval", + description: "Approve or reject an action", + parameters: z.object({ action: z.string() }), + component: ApprovalHitlComponent, +}); +``` + +Registers a HITL component. CopilotKit injects a `respond` function so you can resolve the tool call with the selected +result. diff --git a/apps/docs/reference/basic-agent.mdx b/apps/docs/reference/basic-agent.mdx new file mode 100644 index 00000000..11595080 --- /dev/null +++ b/apps/docs/reference/basic-agent.mdx @@ -0,0 +1,104 @@ +--- +title: BasicAgent (Node runtime) +description: Configuration, methods, and helpers for the BasicAgent class +--- + +`BasicAgent` (from `@copilotkitnext/agent`) connects directly to hosted model providers such as OpenAI, Anthropic, and +Google Gemini. It implements the AG-UI `AbstractAgent` interface, streaming AG-UI events to clients while handling tool +execution and shared state. + +```ts +import { BasicAgent } from "@copilotkitnext/agent"; + +const agent = new BasicAgent({ + model: "openai/gpt-4o", + prompt: "You are a helpful assistant.", + maxOutputTokens: 2048, + temperature: 0.7, +}); + +runtime.registerAgent("assistant", agent); +``` + +## Configuration (`BasicAgentConfiguration`) + +| Option | Type | Description | +| --------------------- | ---------------------------------- | ------------------------------------------------------------------ | +| `model` | `BasicAgentModel | LanguageModel` | Target model (string identifier or preconfigured language model). | +| `prompt` | `string` | System prompt prepended to conversations. | +| `maxSteps` | `number` | Max tool-calling iterations (default `1`). | +| `toolChoice` | `ToolChoice` | Force/allow tool usage. | +| `maxOutputTokens` | `number` | Token limit for responses. | +| `temperature`, `topP`, `topK` | `number` | Sampling controls (forwarded to provider). | +| `presencePenalty`, `frequencyPenalty` | `number` | OpenAI-compatible penalties. | +| `stopSequences` | `string[]` | Stop sequences. | +| `seed` | `number` | Deterministic seed (provider permitting). | +| `maxRetries` | `number` | Provider retry limit. | +| `overridableProperties` | `OverridableProperty[]` | Allow properties to be overridden via `forwardedProps`. | +| `mcpServers` | `MCPClientConfig[]` | Model Context Protocol servers to proxy. | +| `tools` | `ToolDefinition[]` | Server-side tools available to the model. | + +### Overridable Properties + +Set `overridableProperties` to allow frontend code to modify certain fields via `forwardedProps` (e.g., adjust +temperature per request). + +```ts +const agent = new BasicAgent({ + model: "openai/gpt-4o", + temperature: 0.7, + overridableProperties: ["temperature", "maxOutputTokens"], +}); +``` + +## Methods + +| Method | Description | +| ------------------ | ----------------------------------------------------------- | +| `canOverride(property)` | Returns `true` if a property can be overridden. | +| `abortRun()` | Cancels the in-flight run (inherited from `AbstractAgent`). | +| `addMessage`, `setState`, `run` | Inherited methods for manipulating the agent. | + +Internally, `BasicAgent` uses Vercel’s `ai` SDK (`streamText`) to handle streaming completions/tool calls. + +## Model Helpers + +### `resolveModel(specifier)` + +Converts strings like `"openai/gpt-4o"`, `"anthropic/claude-3.5-haiku"`, or `"google/gemini-2.5-pro"` into +`LanguageModel` instances. Also accepts a preconstructed model and returns it untouched. + +```ts +const model = resolveModel("openai/gpt-4o"); +const agent = new BasicAgent({ model, maxOutputTokens: 1024 }); +``` + +Throws if the provider prefix is unknown or if required API keys are missing. + +## Tool Helpers + +### `defineTool` + +Creates a type-safe server-side tool definition. + +```ts +import { defineTool } from "@copilotkitnext/agent"; +import { z } from "zod"; + +const weatherTool = defineTool({ + name: "get_weather", + description: "Returns the current weather by location", + parameters: z.object({ location: z.string() }), +}); + +const agent = new BasicAgent({ + model: "openai/gpt-4o", + tools: [weatherTool], +}); +``` + +### Conversion Helpers + +`convertMessagesToVercelAISDKMessages`, `convertToolsToVercelAITools`, and +`convertToolDefinitionsToVercelAITools` are provided for advanced integrations where you need direct access to the +Vercel AI SDK representations. They are generally used internally but are exported for convenience. diff --git a/apps/docs/reference/copilot-chat-assistant-message.mdx b/apps/docs/reference/copilot-chat-assistant-message.mdx new file mode 100644 index 00000000..f5f9cca0 --- /dev/null +++ b/apps/docs/reference/copilot-chat-assistant-message.mdx @@ -0,0 +1,59 @@ +--- +title: CopilotChatAssistantMessage +description: Renders assistant responses with markdown, toolbar, and tool calls +--- + +`CopilotChatAssistantMessage` renders a single assistant message. It handles markdown rendering, toolbar actions (copy, +feedback, regenerate, read aloud), and embedded tool call output via `CopilotChatToolCallsView`. + +## Basic Usage + +```tsx +import { CopilotChatAssistantMessage } from "@copilotkitnext/react"; + + sendFeedback("up")} + onThumbsDown={() => sendFeedback("down")} + onReadAloud={readAloud} + onRegenerate={regenerate} +/> +``` + +## Props + +| Prop | Description | +| ------------------------ | ----------------------------------------------------------------- | +| `message` | The assistant `Message` to display. | +| `messages` | Full message list, used to resolve tool responses. | +| `isRunning` | Disables toolbar while the agent is streaming the latest message.| +| `onThumbsUp/Down` | Feedback callbacks (optional). | +| `onReadAloud` | Trigger a read-aloud action (optional). | +| `onRegenerate` | Request the agent to regenerate the reply (optional). | +| `additionalToolbarItems` | Extra toolbar JSX. | +| `toolbarVisible` | Force toolbar visibility (defaults to auto). | + +## Slots + +| Slot | Default Component | Purpose | +| ------------------ | ------------------------------------------------ | ------- | +| `markdownRenderer` | `CopilotChatAssistantMessage.MarkdownRenderer` | Parses and renders the assistant message body. | +| `toolbar` | `CopilotChatAssistantMessage.Toolbar` | Wrapper for action buttons beneath the message. | +| `copyButton` | `CopilotChatAssistantMessage.CopyButton` | Copy-to-clipboard button. | +| `thumbsUpButton` | `CopilotChatAssistantMessage.ThumbsUpButton` | Positive feedback control. | +| `thumbsDownButton` | `CopilotChatAssistantMessage.ThumbsDownButton` | Negative feedback control. | +| `readAloudButton` | `CopilotChatAssistantMessage.ReadAloudButton` | Trigger text-to-speech or other read-aloud behavior. | +| `regenerateButton` | `CopilotChatAssistantMessage.RegenerateButton` | Request another answer from the agent. | +| `toolCallsView` | `CopilotChatToolCallsView` | Displays tool call output associated with the message. | + +## Markdown Rendering + +The default renderer uses `streamdown` (Markdown + syntax highlighting + KaTeX). Override `markdownRenderer` to plug in +your own markdown implementation. + +## Toolbar Visibility + +- Toolbar hides when the assistant is still streaming the latest message. +- Messages without text content (tool-call-only replies) suppress the toolbar by default. + diff --git a/apps/docs/reference/copilot-chat-audio-recorder.mdx b/apps/docs/reference/copilot-chat-audio-recorder.mdx new file mode 100644 index 00000000..08eff09d --- /dev/null +++ b/apps/docs/reference/copilot-chat-audio-recorder.mdx @@ -0,0 +1,36 @@ +--- +title: CopilotChatAudioRecorder +description: Stub audio recorder used by CopilotChatInput +--- + +`CopilotChatAudioRecorder` renders the animated waveform and exposes a simple recorder interface for transcription mode. +The default implementation is a stub—perfect for UI demos and easy to swap out for a real recorder. + +## Basic Usage + +```tsx +import { CopilotChatAudioRecorder } from "@copilotkitnext/react"; + +; +``` + +## Imperative API + +The component forwards a ref with the following interface: + +```ts +interface AudioRecorderHandle { + state: "idle" | "recording" | "processing"; + start(): Promise; + stop(): Promise; + dispose(): void; +} +``` + +`CopilotChatInput` uses this handle to start/stop recording automatically when switching modes. The bundled recorder +returns an empty `Blob`—swap it with your own implementation for real audio capture. + +## Styling + +- Uses a `` element to draw a fake waveform animation. +- Accepts `className`/`style` props to customize size and appearance. diff --git a/apps/docs/reference/copilot-chat-input.mdx b/apps/docs/reference/copilot-chat-input.mdx new file mode 100644 index 00000000..860f6193 --- /dev/null +++ b/apps/docs/reference/copilot-chat-input.mdx @@ -0,0 +1,72 @@ +--- +title: CopilotChatInput +description: Composable chat input used by CopilotChat +--- + +`CopilotChatInput` powers the message composer in `CopilotChat`. It supports text entry, slash commands, optional tool +menus, transcription controls, and slot overrides for each UI element. + +## Basic Usage + +```tsx +import { CopilotChatInput } from "@copilotkitnext/react"; + +function Composer({ onSend }: { onSend: (value: string) => void }) { + return ( + {} }]} /> + ); +} +``` + +## Props + +| Prop | Type | Description | +| ----------------------- | -------------------------- | ------------------------------------------------------------------ | +| `mode` | `"input" | "transcribe" | "processing"` | Controls UI state (text entry, recording, or loading). | +| `toolsMenu` | `(ToolsMenuItem | "-")[]` | Menu entries shown via slash commands and the “+” button. | +| `onSubmitMessage` | `(value: string) => void` | Called when the user sends a message (Enter or send button). | +| `onStop` | `() => void` | Handler for stopping an in-flight run (only shown while running). | +| `isRunning` | `boolean` | Indicates whether the agent is processing. | +| `onStartTranscribe` | `() => void` | Callback when switching to transcription mode. | +| `onCancelTranscribe` | `() => void` | Callback when cancelling transcription. | +| `onFinishTranscribe` | `() => void` | Callback when finishing transcription. | +| `onAddFile` | `() => void` | Handler for the “Attach” button / slash command. | +| `value`, `onChange` | Controlled input support. | Provide to manage the text manually. | +| `autoFocus` | `boolean` | Focuses the input when the surrounding modal opens (default `true`).| + +The component also exposes slot overrides (e.g., `textArea`, `sendButton`, `audioRecorder`). Pass a render function via +`children` to customize layout while re-using built-in slots. + +## Slots + +| Slot | Default Component | Purpose | +| ------------------------ | ------------------------------------------- | ------- | +| `textArea` | `CopilotChatInput.TextArea` | Text input element (auto-expanding textarea). | +| `sendButton` | `CopilotChatInput.SendButton` | Primary send/stop button. | +| `startTranscribeButton` | `CopilotChatInput.StartTranscribeButton` | Action to enter transcription mode. | +| `cancelTranscribeButton` | `CopilotChatInput.CancelTranscribeButton` | Cancels transcription capture. | +| `finishTranscribeButton` | `CopilotChatInput.FinishTranscribeButton` | Finalizes transcription result. | +| `addMenuButton` | `CopilotChatInput.AddMenuButton` | “+” button exposing slash menu / attachments. | +| `audioRecorder` | `CopilotChatInput.AudioRecorder` | Waveform recorder shown during transcription. | + +Override a slot by passing a component in props: + +```tsx + ( + + )} +/> +``` + +## Slash Commands + +Provide a `toolsMenu` array to enable slash commands. Items can be nested by supplying `items` arrays; use `"-"` as a +divider placeholder. The input filters commands as the user types `/`. + +## Transcription Mode + +- Set `mode="transcribe"` to show recording controls. +- The built-in audio recorder starts/stops automatically via `onStartTranscribe`/`onCancelTranscribe`/`onFinishTranscribe`. diff --git a/apps/docs/reference/copilot-chat-message-view.mdx b/apps/docs/reference/copilot-chat-message-view.mdx new file mode 100644 index 00000000..ac72e2fa --- /dev/null +++ b/apps/docs/reference/copilot-chat-message-view.mdx @@ -0,0 +1,55 @@ +--- +title: CopilotChatMessageView +description: Message list component used inside CopilotChatView +--- + +`CopilotChatMessageView` renders the scrollable conversation history: user messages, assistant replies, tool calls, and +activity messages. It is the default message renderer used by `CopilotChatView`. + +## Basic Usage + +```tsx +import { CopilotChatMessageView } from "@copilotkitnext/react"; + +; +``` + +Typically you don’t call it directly—`CopilotChatView` wires it up for you—but supplying it manually allows for custom +layouts. + +## Props + +`CopilotChatMessageViewProps` includes: + +| Prop | Type | Description | +| --------------- | ----------------- | ---------------------------------------------------------- | +| `messages` | `Message[]` | Conversation history to display. | +| `assistantMessage` | Slot override | Replace the assistant message renderer (`CopilotChatAssistantMessage`). | +| `userMessage` | Slot override | Replace the user message renderer (`CopilotChatUserMessage`). | +| `cursor` | Slot override | Customize the animated typing cursor. | +| `className` | `string` | Additional CSS class. | +| `children` | Render prop | Optional render prop returning custom markup (receives `{ messageElements, messages, isRunning }`). | + +It also accepts props forwarded from `CopilotChatViewProps`, such as `labels`, `runState`, `suggestionView`, etc. + +## Customizing Messages + +Override slots to control how each message renders: + +```tsx + ( + + )} + userMessage={({ message }) => } +/>; +``` + +## Scroll Behavior + +- Maintains scroll position when new messages stream in. +- Exposes `onScrollTop` so you can load historical messages on demand. diff --git a/apps/docs/reference/copilot-chat-suggestion-pill.mdx b/apps/docs/reference/copilot-chat-suggestion-pill.mdx new file mode 100644 index 00000000..c4535558 --- /dev/null +++ b/apps/docs/reference/copilot-chat-suggestion-pill.mdx @@ -0,0 +1,29 @@ +--- +title: CopilotChatSuggestionPill +description: Button component used for chat suggestions +--- + +`CopilotChatSuggestionPill` renders an individual suggestion button. It’s the default `suggestion` slot for +`CopilotChatSuggestionView`, but you can also use it directly when building custom suggestion UIs. + +## Basic Usage + +```tsx +import { CopilotChatSuggestionPill } from "@copilotkitnext/react"; + + send("Summarize the conversation")}>Summarize; +``` + +## Props + +Extends `React.ButtonHTMLAttributes` with: + +| Prop | Type | Description | +| ---------- | ------------- | ----------------------------------------------- | +| `icon` | `ReactNode` | Optional leading icon displayed when not loading. | +| `isLoading`| `boolean` | Shows a spinner and disables the button. | + +## Styling + +- Includes focus states, hover styles, and disabled styling via Tailwind classes. +- Add your own styles via the `className` prop or slot overrides. diff --git a/apps/docs/reference/copilot-chat-suggestion-view.mdx b/apps/docs/reference/copilot-chat-suggestion-view.mdx new file mode 100644 index 00000000..cf2c1e4a --- /dev/null +++ b/apps/docs/reference/copilot-chat-suggestion-view.mdx @@ -0,0 +1,60 @@ +--- +title: CopilotChatSuggestionView +description: Renders the suggestion pill list beneath CopilotChat +--- + +`CopilotChatSuggestionView` displays the suggestion buttons generated by CopilotKit. It supports slot overrides for the +container and individual suggestion pills so you can customize presentation while preserving behavior. + +## Basic Usage + +```tsx +import { CopilotChatSuggestionView } from "@copilotkitnext/react"; + + send(suggestion.message)} +/> +``` + +## Props + +| Prop | Type | Description | +| ------------------ | -------------------------- | ---------------------------------------------------------------- | +| `suggestions` | `Suggestion[]` | Suggestions to render. | +| `loadingIndexes` | `ReadonlyArray` | Optional indexes currently loading (shows spinner). | +| `onSelectSuggestion` | `(suggestion, index) => void` | Called when the user clicks a suggestion pill. | +| `container` | Slot override | Replace the wrapping `div`. | +| `suggestion` | Slot override | Replace the individual suggestion pill component. | + +## Slots + +| Slot | Default | Purpose | +| ------------- | ----------------------------------- | ------- | +| `container` | `DefaultContainer` (flex wrapper `div`) | Controls layout/styling for the pill row. | +| `suggestion` | `CopilotChatSuggestionPill` | Renders each suggestion button element. | + +When `children` is a function, the component passes `{ container, suggestion, suggestions, onSelectSuggestion, loadingIndexes }` +so you can compose custom layouts while reusing the rendered elements. + +## Slot Overrides + +```tsx + ( +
+ {children} +
+ )} + suggestion={({ isLoading, children, ...rest }) => ( + + )} +/> +``` + +If `children` is a function, the component passes both the rendered container and a sample pill component so you can +compose custom layouts. diff --git a/apps/docs/reference/copilot-chat-toggle-button.mdx b/apps/docs/reference/copilot-chat-toggle-button.mdx new file mode 100644 index 00000000..3fb51046 --- /dev/null +++ b/apps/docs/reference/copilot-chat-toggle-button.mdx @@ -0,0 +1,33 @@ +--- +title: CopilotChatToggleButton +description: Floating button that toggles the Copilot chat surface +--- + +`CopilotChatToggleButton` is the floating action button that opens/closes Copilot chat in sidebar or popup layouts. It +works with `CopilotChatConfigurationProvider` to track modal state, but also falls back to internal state when no +provider is present. + +## Basic Usage + +```tsx +import { CopilotChatToggleButton } from "@copilotkitnext/react"; + +; +``` + +## Props + +Extends `React.ButtonHTMLAttributes` with two optional slot overrides: + +| Prop | Type | Description | +| ---------- | --------------------- | -------------------------------------------------------- | +| `openIcon` | `SlotValue` | Icon to show when the chat is closed. Defaults to bubble.| +| `closeIcon`| `SlotValue` | Icon to show when the chat is open. Defaults to “X”. | + +The component automatically sets `aria-label` using the chat labels from `CopilotChatConfigurationProvider`. + +## Behavior + +- Toggles `isModalOpen` via the configuration provider if available; otherwise manages its own boolean state. +- Renders both icons and cross-fades/rotates them for smooth transitions. +- Applies Tailwind-based styling for hover, focus, and disabled states (customize via `className`). diff --git a/apps/docs/reference/copilot-chat-tool-calls-view.mdx b/apps/docs/reference/copilot-chat-tool-calls-view.mdx new file mode 100644 index 00000000..39b8f6d3 --- /dev/null +++ b/apps/docs/reference/copilot-chat-tool-calls-view.mdx @@ -0,0 +1,33 @@ +--- +title: CopilotChatToolCallsView +description: Renders the output of tool calls within assistant messages +--- + +`CopilotChatToolCallsView` renders tool call results associated with an assistant message. It delegates the actual UI to +`useRenderToolCall`, so any registered tool call renderers are applied automatically. + +## Basic Usage + +```tsx +import { CopilotChatToolCallsView } from "@copilotkitnext/react"; + +function ToolCallSection({ message, messages }) { + return ; +} +``` + +This component is typically embedded inside `CopilotChatMessageView`, but you can use it in custom layouts if you need +to separate messages and tool output. + +## Props + +| Prop | Type | Description | +| --------- | ---------------- | ----------------------------------------------- | +| `message` | `AssistantMessage`| Assistant message containing `toolCalls`. | +| `messages`| `Message[]` | Optional list of all messages to resolve tool results. | + +## Behavior + +- Iterates through `message.toolCalls` and finds matching `ToolMessage` entries to supply to the renderer. +- Uses `useRenderToolCall()` to pick the appropriate renderer for each tool. +- Returns `null` if there are no tool calls. diff --git a/apps/docs/reference/copilot-chat-user-message.mdx b/apps/docs/reference/copilot-chat-user-message.mdx new file mode 100644 index 00000000..d419ff2d --- /dev/null +++ b/apps/docs/reference/copilot-chat-user-message.mdx @@ -0,0 +1,59 @@ +--- +title: CopilotChatUserMessage +description: Renders user-authored messages inside the chat transcript +--- + +`CopilotChatUserMessage` displays the user’s message bubble along with a toolbar for actions like copy, edit, and branch +navigation. As with other chat components, it supports slot overrides for granular customization. + +## Basic Usage + +```tsx +import { CopilotChatUserMessage } from "@copilotkitnext/react"; + + reopenComposer(message)} + onSwitchToBranch={({ branchIndex }) => loadBranch(branchIndex)} + branchIndex={currentBranch} + numberOfBranches={branchCount} +/> +``` + +## Props + +| Prop | Description | +| ---------------------- | ----------------------------------------------------------------- | +| `message` | `UserMessage` to render (string or structured content). | +| `onEditMessage` | Called when the user clicks “Edit”. | +| `branchIndex` | Current branch index (optional). | +| `numberOfBranches` | Total branches available (optional). | +| `onSwitchToBranch` | Callback for branch navigation arrow buttons. | +| `additionalToolbarItems` | Extra React nodes appended to the toolbar. | + +## Slots + +| Slot | Default Component | Purpose | +| ------------------ | ----------------------------------------------- | ------- | +| `messageRenderer` | `CopilotChatUserMessage.MessageRenderer` | Renders the user bubble (rich text / structured content). | +| `toolbar` | `CopilotChatUserMessage.Toolbar` | Container for action buttons under the message. | +| `copyButton` | `CopilotChatUserMessage.CopyButton` | Copies the message content. | +| `editButton` | `CopilotChatUserMessage.EditButton` | Invokes `onEditMessage`. | +| `branchNavigation` | `CopilotChatUserMessage.BranchNavigation` | UI for cycling through alternate branches. | + +Override slots via props to control presentation: + +```tsx + {content}} + copyButton={({ onClick }) => } +/> +``` + +If you provide `children`, the render prop receives `{ messageRenderer, toolbar, copyButton, editButton, branchNavigation, message, branchIndex, numberOfBranches, additionalToolbarItems }` so you can compose your own layout. + +## Branch Navigation + +If you supply `numberOfBranches > 1` and `onSwitchToBranch`, the component renders branch navigation arrows. This is +useful for multi-branch conversations where the user can switch between retries or alternative responses. diff --git a/apps/docs/reference/copilot-chat-view.mdx b/apps/docs/reference/copilot-chat-view.mdx new file mode 100644 index 00000000..96ef9dfc --- /dev/null +++ b/apps/docs/reference/copilot-chat-view.mdx @@ -0,0 +1,60 @@ +--- +title: CopilotChatView +description: Layout component that composes messages, suggestions, and the chat input +--- + +`CopilotChatView` arranges the standard Copilot chat UI: the scrollable message list, optional suggestion pills, and the +chat input/footer. `CopilotChat` uses it internally, but you can render it directly for custom shells. + +## Basic Usage + +```tsx +import { CopilotChatView } from "@copilotkitnext/react"; + + sendMessage(suggestion.message)} +/> +``` + +## Slots + +`CopilotChatView` is fully slot-driven via `WithSlots`. Each entry below lists the default component and suggested use: + +| Slot | Default Component | Purpose | +| ------------------------ | ------------------------------------- | ------- | +| `messageView` | `CopilotChatMessageView` | Renders the transcript (assistant/user/activity messages). | +| `scrollView` | `CopilotChatView.ScrollView` | Scroll container that manages stick-to-bottom behavior. | +| `scrollToBottomButton` | `CopilotChatView.ScrollToBottomButton`| Floating button shown when the user scrolls up. | +| `input` | `CopilotChatInput` | Composer UI with text field, tools, transcription controls. | +| `inputContainer` | `CopilotChatView.InputContainer` | Wrapper that positions the input and disclaimer. | +| `feather` | `CopilotChatView.Feather` | Decorative element rendered behind the chat (optional). | +| `disclaimer` | `CopilotChatView.Disclaimer` | Footer disclaimer text. | +| `suggestionView` | `CopilotChatSuggestionView` | Suggestion pill tray displayed above the input. | + +Override a slot to customize layout while reusing the rest of the view. + +## Key Props + +| Prop | Type | Description | +| ------------------------ | ----------------------------- | ------------------------------------------------------------------ | +| `messages` | `Message[]` | Conversation history. | +| `autoScroll` | `boolean` | Auto-stick to bottom (default `true`). | +| `inputProps` | `Partial` | Configure the embedded input. | +| `isRunning` | `boolean` | Indicates whether the agent is processing. | +| `suggestions` | `Suggestion[]` | Suggestions to show beneath the message list. | +| `suggestionLoadingIndexes` | `ReadonlyArray` | Indexes to display loading state for suggestions. | +| `onSelectSuggestion` | `(suggestion, index) => void` | Called when a suggestion is picked. | + +## Scroll Handling + +- Uses `use-stick-to-bottom` to maintain scroll position while messages stream in. +- Exposes `scrollToBottomButton` slot to customize the floating “Scroll to bottom” control. + +## Mobile Optimizations + +- The input container listens to keyboard height to avoid being obscured on mobile. +- Suggestion pills and footer spacing adjust automatically based on input height. diff --git a/apps/docs/reference/copilot-chat.mdx b/apps/docs/reference/copilot-chat.mdx index 656c6267..5639b1bc 100644 --- a/apps/docs/reference/copilot-chat.mdx +++ b/apps/docs/reference/copilot-chat.mdx @@ -89,13 +89,23 @@ CSS class name for the root container. ``` -### Component Slots - -CopilotChat supports slot customization for various parts of the UI: +## Component Slots + +| Slot | Default Component | Purpose | +| ---------------------- | ------------------------------- | ------- | +| `messageView` | `CopilotChatMessageView` | Transcript rendering (assistant/user/activity messages). | +| `suggestionView` | `CopilotChatSuggestionView` | Suggestion pill bar above the input. | +| `input` | `CopilotChatInput` | Composer UI (text area, send button, transcription). | +| `inputContainer` | `CopilotChatView.InputContainer`| Positions the input and disclaimer. | +| `scrollView` | `CopilotChatView.ScrollView` | Scrollable container with stick-to-bottom behavior. | +| `scrollToBottomButton` | `CopilotChatView.ScrollToBottomButton` | Floating button shown when scrolled up. | +| `feather` | `CopilotChatView.Feather` | Decorative background element. | +| `disclaimer` | `CopilotChatView.Disclaimer` | Footer text beneath the input. | ```tsx +``` diff --git a/apps/docs/reference/copilot-modal-header.mdx b/apps/docs/reference/copilot-modal-header.mdx new file mode 100644 index 00000000..6eb7ead1 --- /dev/null +++ b/apps/docs/reference/copilot-modal-header.mdx @@ -0,0 +1,44 @@ +--- +title: CopilotModalHeader +description: Header component used by popup and sidebar chat layouts +--- + +`CopilotModalHeader` renders the header bar for the popup/sidebar chat surfaces. It includes the title and close button +and integrates with `CopilotChatConfigurationProvider` to toggle modal state. + +## Basic Usage + +```tsx +import { CopilotModalHeader } from "@copilotkitnext/react"; + +; +``` + +## Props + +| Prop | Type | Description | +| ------ | --------- | ------------------------------------------------------------------------- | +| `title`| `string` | Optional title text. Defaults to labels from `CopilotChatConfigurationProvider`. | + +All other props are forwarded to the underlying `
` element. + +## Slots + +| Slot | Default Component | Purpose | +| -------------- | ----------------------------------------- | ------- | +| `titleContent` | `CopilotModalHeader.Title` | Renders the centered header title. | +| `closeButton` | `CopilotModalHeader.CloseButton` | Closes the modal/sidebar via configuration context. | + +```tsx +

{children}

} + closeButton={(props) => } +/> +``` + +When used as a render prop, `children` receives `{ titleContent, closeButton, title }` so you can lay out the header yourself. + +## Close Behavior + +Clicking the close button calls `setModalOpen(false)` on the surrounding configuration provider. If no provider is present, +the button simply toggles internal state (useful for isolated demos). diff --git a/apps/docs/reference/copilot-popup-view.mdx b/apps/docs/reference/copilot-popup-view.mdx new file mode 100644 index 00000000..d7c6f989 --- /dev/null +++ b/apps/docs/reference/copilot-popup-view.mdx @@ -0,0 +1,38 @@ +--- +title: CopilotPopupView +description: Modal chat view implementation used by CopilotPopup +--- + +`CopilotPopupView` is a modal-flavored `CopilotChatView`. It positions the chat window above a dimmed backdrop and +manages focus/escape handling. Use it when composing custom pop-up layouts. + +## Basic Usage + +```tsx +import { CopilotPopupView } from "@copilotkitnext/react"; + +function CustomPopupView(props: CopilotChatViewProps) { + return ( + Copilot} + width={400} + height={540} + clickOutsideToClose + /> + ); +} +``` + +## Props + +`CopilotPopupViewProps` extends `CopilotChatViewProps` with: + +| Prop | Type | Description | +| --------------------- | ---------- | ------------------------------------------------------------ | +| `header` | `ReactNode`| Optional header slot rendered at the top of the modal. | +| `width` | `number | string` | Modal width. | +| `height` | `number | string` | Modal height. | +| `clickOutsideToClose` | `boolean` | Whether clicking the backdrop closes the popup. Defaults true.| + +The component also consumes `CopilotChatConfigurationProvider` to read modal open state. diff --git a/apps/docs/reference/copilot-popup.mdx b/apps/docs/reference/copilot-popup.mdx new file mode 100644 index 00000000..85990bdb --- /dev/null +++ b/apps/docs/reference/copilot-popup.mdx @@ -0,0 +1,46 @@ +--- +title: CopilotPopup +description: Floating modal wrapper for CopilotChat +--- + +`CopilotPopup` renders `CopilotChat` inside a floating modal window. It’s useful when you want Copilot to appear as a +popup rather than a sidebar. + +## Basic Usage + +```tsx +import { CopilotPopup } from "@copilotkitnext/react"; + +function PopupExample() { + return ( + Copilot} + width={420} + height={560} + clickOutsideToClose + /> + ); +} +``` + +## Props + +`CopilotPopupProps` extends `CopilotChatProps` with: + +| Prop | Type | Description | +| -------------------- | ---------------------- | --------------------------------------------------------------- | +| `header` | `ReactNode` | Optional header content rendered above the chat view. | +| `defaultOpen` | `boolean` | Sets initial open state (defaults to `false`). | +| `width` | `number | string` | Popup width. | +| `height` | `number | string` | Popup height. | +| `clickOutsideToClose`| `boolean` | Close the popup when clicking the overlay (defaults to `true`). | + +All other props are forwarded to `CopilotChat` (agent configuration, labels, overrides, etc.). + +## Behavior + +- Uses `CopilotPopupView` under the hood to handle modal layout and overlay interactions. +- Passes `isModalDefaultOpen` to `CopilotChat`, so the pop-up honors configuration changes from + `CopilotChatConfigurationProvider`. diff --git a/apps/docs/reference/copilot-runtime.mdx b/apps/docs/reference/copilot-runtime.mdx new file mode 100644 index 00000000..a9071868 --- /dev/null +++ b/apps/docs/reference/copilot-runtime.mdx @@ -0,0 +1,77 @@ +--- +title: CopilotRuntime +description: Runtime orchestration, request handlers, and agent runners +--- + +`CopilotRuntime` glues agents, runners, middleware, and transcription together. Pair it with the Hono-based helper +`createCopilotEndpoint` to expose an HTTP API for React/Angular clients. + +## Constructing the Runtime + +```ts +import { CopilotRuntime } from "@copilotkitnext/runtime"; +import { BasicAgent } from "@copilotkitnext/agent"; + +const runtime = new CopilotRuntime({ + agents: { + assistant: new BasicAgent({ model: "openai/gpt-4o" }), + }, +}); +``` + +### Options (`CopilotRuntimeOptions`) + +| Option | Description | +| ------------------------- | ---------------------------------------------------------------- | +| `agents` (required) | Map or promise resolving to `{ [id]: AbstractAgent }`. | +| `runner` | Custom `AgentRunner` implementation (defaults to `InMemoryAgentRunner`). | +| `transcriptionService` | Optional audio transcription service (e.g., OpenAI Whisper). | +| `beforeRequestMiddleware` | Function or webhook URL executed before each request. | +| `afterRequestMiddleware` | Function or webhook URL executed after each response. | + +## Exposing an HTTP endpoint + +```ts +import { createCopilotEndpoint } from "@copilotkitnext/runtime"; +import { handle } from "hono/vercel"; + +const app = createCopilotEndpoint({ + runtime, + basePath: "/api/copilotkit", +}); + +export const GET = handle(app); +export const POST = handle(app); +``` + +Routes provided: + +- `POST /agent/:agentId/run` – Start a run and stream events. +- `POST /agent/:agentId/connect` – Subscribe to historic + live events. +- `POST /agent/:agentId/stop/:threadId` – Stop an in-flight run. +- `GET /info` – Runtime metadata (agents, version, runner info). +- `POST /transcribe` – Audio transcription (when a service is configured). + +All routes run through the optional middleware hooks; if a hook returns a `Response`, it short-circuits the handler. + +## Agent Runners + +`AgentRunner` abstracts the execution environment. The runtime ships with `InMemoryAgentRunner`, which stores run events +in memory per thread and supports reconnection. + +### `AgentRunner` interface + +```ts +abstract class AgentRunner { + abstract run(request: AgentRunnerRunRequest): Observable; + abstract connect(request: AgentRunnerConnectRequest): Observable; + abstract isRunning(request: AgentRunnerIsRunningRequest): Promise; + abstract stop(request: AgentRunnerStopRequest): Promise; +} +``` + +### `InMemoryAgentRunner` + +Use the default runner for single-instance deployments. It keeps event history in process memory, compacting events for +efficient reconnects. To implement persistence or multi-instance scaling, provide your own runner that extends +`AgentRunner`. diff --git a/apps/docs/reference/copilot-sidebar-view.mdx b/apps/docs/reference/copilot-sidebar-view.mdx new file mode 100644 index 00000000..1233a2e5 --- /dev/null +++ b/apps/docs/reference/copilot-sidebar-view.mdx @@ -0,0 +1,47 @@ +--- +title: CopilotSidebarView +description: Sidebar chat layout component used by CopilotSidebar +--- + +`CopilotSidebarView` is a `CopilotChatView` implementation that renders the chat interface inside a slide-in sidebar. +You rarely use it directly; `CopilotSidebar` wires it up automatically. Use it when you need full control over the chat +view slot. + +## Basic Usage + +```tsx +import { CopilotSidebarView } from "@copilotkitnext/react"; +import { CopilotChat } from "@copilotkitnext/react"; + +function CustomSidebar(props: CopilotChatProps) { + return ( + ( + Support Copilot} + width={360} + /> + )} + /> + ); +} +``` + +## Props + +`CopilotSidebarViewProps` extends `CopilotChatViewProps` with: + +| Prop | Type | Description | +| ------- | --------------------------------- | ------------------------------------------------ | +| `header`| `SlotValue` | Optional header slot for the sidebar chrome. | +| `width` | `number | string` | Sidebar width (defaults to 480px). | + +The component also consumes `CopilotChatConfigurationProvider` state to determine whether the sidebar should be open. + +## Behavior + +- Handles responsive layout, safe-area insets, and body margin adjustments when opened. +- Renders `CopilotChatToggleButton` automatically. +- Uses `CopilotModalHeader` by default if no custom header is supplied. diff --git a/apps/docs/reference/copilot-sidebar.mdx b/apps/docs/reference/copilot-sidebar.mdx new file mode 100644 index 00000000..a3435ce0 --- /dev/null +++ b/apps/docs/reference/copilot-sidebar.mdx @@ -0,0 +1,47 @@ +--- +title: CopilotSidebar +description: Fixed sidebar wrapper around CopilotChat +--- + +`CopilotSidebar` renders `CopilotChat` inside a responsive, slide-in sidebar. It accepts the same props as +`CopilotChat` (minus `chatView`) plus a few sidebar-specific options. + +## Basic Usage + +```tsx +import { CopilotSidebar } from "@copilotkitnext/react"; + +function App() { + return ( + Copilot} + /> + ); +} +``` + +## Props + +`CopilotSidebar` extends `CopilotChatProps` with the following additions: + +| Prop | Type | Description | +| ------------ | ------------------- | ------------------------------------------------------------------------------ | +| `header` | `ReactNode` | Optional header slot rendered above the chat view. | +| `defaultOpen`| `boolean` | Controls whether the sidebar starts open. Defaults to `false`. | +| `width` | `number | string` | Sets the desktop sidebar width (pixel value or CSS width). Defaults to 480px. | + +All other props (e.g., `agentId`, `threadId`, `labels`, `messageView`, etc.) are forwarded to `CopilotChat`. + +## Behavior + +- Auto-injects `CopilotChatToggleButton` to open/close the sidebar on smaller viewports. +- Resizes responsively: full width on mobile, fixed width on desktop. +- Adjusts the document body margin so page content doesn’t shift under the sidebar when it opens. + +## Tips + +- Use alongside `CopilotChatConfigurationProvider` to share configuration between multiple chat surfaces. +- Combine with `CopilotSidebarView` if you need to supply a custom chat view while keeping the sidebar shell. diff --git a/apps/docs/reference/copilotkit-core-react.mdx b/apps/docs/reference/copilotkit-core-react.mdx new file mode 100644 index 00000000..c271bc30 --- /dev/null +++ b/apps/docs/reference/copilotkit-core-react.mdx @@ -0,0 +1,73 @@ +--- +title: CopilotKitCoreReact +description: React-ready extension of CopilotKitCore +--- + +`CopilotKitCoreReact` extends the base `CopilotKitCore` class with React-specific capabilities. It manages registries for +tool call renderers, custom message renderers, and activity renderers, exposing them to hooks such as +`useRenderToolCall`, `useRenderCustomMessages`, and `useRenderActivityMessage`. + +## Construction + +```ts +import { CopilotKitCoreReact } from "@copilotkitnext/react"; + +const core = new CopilotKitCoreReact({ + runtimeUrl: "/api/copilotkit", + renderToolCalls: [/* ReactToolCallRenderer[] */], + renderActivityMessages: [/* ReactActivityMessageRenderer[] */], + renderCustomMessages: [/* ReactCustomMessageRenderer[] */], +}); +``` + +All core options (`runtimeUrl`, headers, properties, agents, tools, etc.) are inherited from `CopilotKitCoreConfig`. + +## Additional Options + +| Option | Type | Description | +| ------------------------ | ----------------------------------- | --------------------------------------------------------- | +| `renderToolCalls` | `ReactToolCallRenderer[]` | Initial list of tool call renderers. | +| `renderActivityMessages` | `ReactActivityMessageRenderer[]` | Initial list of activity message renderers. | +| `renderCustomMessages` | `ReactCustomMessageRenderer[]` | Initial list of custom message renderers for chat bubbles.| + +## Key Getters + +- `renderToolCalls` – current array of tool call renderers. +- `renderActivityMessages` – current array of activity message renderers. +- `renderCustomMessages` – current array of custom message renderers. + +Each getter returns a read-only array so consumers don’t mutate the registry directly. + +## setRenderToolCalls + +```ts +core.setRenderToolCalls(renderers: ReactToolCallRenderer[]): void; +``` + +Replaces the tool call renderer list and notifies subscribers via +`CopilotKitCoreReactSubscriber.onRenderToolCallsChanged`. + +## Subscriptions + +`CopilotKitCoreReact` overrides `subscribe`/`unsubscribe` so you can register +`CopilotKitCoreReactSubscriber` objects that listen for render registry changes in addition to the base events: + +```ts +const unsubscribe = core.subscribe({ + onRenderToolCallsChanged: ({ renderToolCalls }) => { + console.log("Tool renderers updated", renderToolCalls.length); + }, +}); + +// Later +unsubscribe(); +``` + +## When to Use + +- When you need to instantiate CopilotKit outside of the standard provider (e.g., custom testing setups, advanced + multi-core scenarios). +- When you want to programmatically adjust renderers while still using the React hook ecosystem. + +Most applications rely on `CopilotKitProvider`, which creates a `CopilotKitCoreReact` instance internally. This document +is useful if you need direct access to the core for lower-level integrations. diff --git a/apps/docs/reference/copilotkit-inspector.mdx b/apps/docs/reference/copilotkit-inspector.mdx new file mode 100644 index 00000000..771fa364 --- /dev/null +++ b/apps/docs/reference/copilotkit-inspector.mdx @@ -0,0 +1,43 @@ +--- +title: CopilotKitInspector +description: React wrapper around the CopilotKit Web Inspector +--- + +`CopilotKitInspector` renders the Web Inspector custom element provided by `@copilotkitnext/web-inspector`. Drop it into +your app (typically behind a dev-only flag) to inspect conversations, state snapshots, and tool calls in real time. + +## Basic Usage + +```tsx +import { CopilotKitInspector } from "@copilotkitnext/react"; +import { useCopilotKit } from "@copilotkitnext/react"; + +function InspectorPanel() { + const { copilotkit } = useCopilotKit(); + + return ( + + ); +} +``` + +## Props + +All props other than `core` are forwarded to the underlying Web Component (``). Commonly used +attributes include `class`, `style`, and the element’s own configuration options. + +### core + +`CopilotKitCore | null` + +The CopilotKit core instance to visualize. Pass `null` (default) to allow the inspector to attach to the global +singleton. + +## Notes + +- The component automatically defines the Web Component (`defineWebInspector()`) on import, so you only need to render + it once. +- Use `React.forwardRef` to access the underlying `WebInspectorElement` if you need to call imperative APIs. +- The inspector is framework-agnostic—this wrapper simply makes it easy to integrate with React apps. diff --git a/apps/docs/reference/define-tool-call-renderer.mdx b/apps/docs/reference/define-tool-call-renderer.mdx new file mode 100644 index 00000000..2065fe99 --- /dev/null +++ b/apps/docs/reference/define-tool-call-renderer.mdx @@ -0,0 +1,67 @@ +--- +title: defineToolCallRenderer +description: Helper for declaring type-safe tool call renderers in React +--- + +`defineToolCallRenderer` creates a `ReactToolCallRenderer` entry with strong typing for tool arguments and render props. +Use it to register custom UI for specific tools (or wildcard renderers) within CopilotChat. + +## Basic Example + +```tsx +import { defineToolCallRenderer } from "@copilotkitnext/react"; +import { z } from "zod"; + +const WeatherToolRenderer = defineToolCallRenderer({ + name: "get_weather", + args: z.object({ location: z.string() }), + render: ({ args, status, result }) => ( +
+ {args.location} + Status: {status} + {result &&
{result}
} +
+ ), +}); + +copilotkit.addToolCallRenderer(WeatherToolRenderer); +``` + +## Wildcard Renderer + +When `name: "*"`, the helper defaults the argument schema to `z.any()` and accepts any tool call. + +```tsx +const Wildcard = defineToolCallRenderer({ + name: "*", + render: ({ name, args }) => ( +
+ {name} +
{JSON.stringify(args, null, 2)}
+
+ ), +}); +``` + +## Why Use the Helper? + +- Infers the render prop types (`args`, `status`, `result`) from the supplied Zod schema. +- Ensures tool names and agent scoping are passed through correctly. +- Avoids manual casting when registering renderers with CopilotKit. + +## Agent-Specific Renderers + +Optionally scope a renderer to a particular agent by supplying `agentId`: + +```tsx +const SupportRenderer = defineToolCallRenderer({ + name: "create_ticket", + agentId: "support", + args: z.object({ subject: z.string(), priority: z.enum(["low", "high"]) }), + render: ({ args, status }) => ( +
+ {args.subject} ({args.priority}) +
+ ), +}); +``` diff --git a/apps/docs/reference/use-configure-suggestions.mdx b/apps/docs/reference/use-configure-suggestions.mdx new file mode 100644 index 00000000..b4887a8b --- /dev/null +++ b/apps/docs/reference/use-configure-suggestions.mdx @@ -0,0 +1,88 @@ +--- +title: useConfigureSuggestions +description: Register static or dynamic chat suggestions for an agent +--- + +`useConfigureSuggestions` wires CopilotKit suggestion definitions into the runtime. You can provide static button +suggestions, fetch dynamic suggestions from your own API, or disable suggestions entirely—all scoped to a specific +agent if needed. + +## Basic Usage (Static Suggestions) + +```tsx +import { useConfigureSuggestions } from "@copilotkitnext/react"; + +function StaticSuggestions() { + useConfigureSuggestions({ + type: "static", + suggestions: [ + { id: "summarize", message: "Summarize the conversation" }, + { id: "next-steps", message: "Propose next steps" }, + ], + }); + + return null; +} +``` + +## Dynamic Suggestions + +Dynamic configs let CopilotKit call back into your code whenever suggestions are needed. + +```tsx +useConfigureSuggestions({ + type: "dynamic", + instructions: "Suggest follow-up actions for the conversation", + providerAgentId: "assistant", // optional, defaults to the chat agent +}); +``` + +The runtime will ask your agent to generate suggestions using the provided instructions. Use +`copilotkit.reloadSuggestions()` (e.g., via `useSuggestions`) whenever the context changes. + +## Parameters + +### config + +`DynamicSuggestionsConfig | StaticSuggestionsConfig | null` + +- `type: "static"` – Provide an array of suggestion objects `{ id, message, title?, isLoading? }`. +- `type: "dynamic"` – Provide `instructions`, optional `consumerAgentId`, and optional `providerAgentId`. The agent + referenced by `providerAgentId` generates suggestions. +- `available: "disabled"` – Pass `null` or set `available` to disable suggestions. + +### options.deps + +`ReadonlyArray` **optional** + +An array of dependencies that should trigger a reload when they change. Equivalent to a dependency list passed to +`useEffect`. + +```tsx +useConfigureSuggestions(config, { deps: [customerId, ticketId] }); +``` + +## Behavior + +- Registers the suggestions config with CopilotKit and automatically tears it down when the hook unmounts. +- Automatically reloads suggestions when the configuration changes (deep comparison) or when dependencies change. +- If `consumerAgentId` is omitted or `"*"`, the configuration applies to whatever agent is active in the surrounding + `CopilotChatConfigurationProvider`. +- When the configuration targets a single agent, only that agent’s suggestions are reloaded. + +## Disabling Suggestions + +```tsx +useConfigureSuggestions({ available: "disabled", type: "static", suggestions: [] }); +``` + +This clears existing suggestions and prevents the runtime from generating new ones. + +## Tips + +- Pair `useConfigureSuggestions` with `useSuggestions` inside the same component tree to both register and consume + suggestions. +- Use the `deps` option when your config depends on user input (e.g., ticket ID). CopilotKit will reload suggestions + whenever those values change. +- Dynamic configs run on the agent; static configs are great for deterministic helper buttons such as “Summarize,” + “Create follow-up email,” etc. diff --git a/apps/docs/reference/use-render-activity-message.mdx b/apps/docs/reference/use-render-activity-message.mdx new file mode 100644 index 00000000..93aa3826 --- /dev/null +++ b/apps/docs/reference/use-render-activity-message.mdx @@ -0,0 +1,66 @@ +--- +title: useRenderActivityMessage +description: Render custom components for activity messages in CopilotChat +--- + +`useRenderActivityMessage` returns a memoized function that chooses the correct activity renderer for an +`ActivityMessage`. Activity messages represent structured status updates streamed by the agent (e.g., “Searching…”, +“Tool call succeeded”). + +## Basic Usage + +```tsx +import { useRenderActivityMessage } from "@copilotkitnext/react"; +import type { ActivityMessage } from "@ag-ui/core"; + +function ActivityFeed({ message }: { message: ActivityMessage }) { + const renderActivity = useRenderActivityMessage(); + const element = renderActivity(message); + + if (!element) { + return null; + } + + return
{element}
; +} +``` + +## How Renderers Are Selected + +`useRenderActivityMessage` inspects the registered activity renderers (`copilotkit.renderActivityMessages`) and picks the +best match in this order: + +1. Renderer with the same `activityType` **and** matching `agentId`. +2. Renderer with the same `activityType` and no `agentId`. +3. Catch-all renderer where `activityType === "*"`. + +If no renderer matches, the hook returns `null`. + +## Validating Content + +- Activity renderers define a Zod schema (`content`) for their payload. +- The hook calls `safeParse`. If parsing fails, CopilotKit logs a warning and returns `null` to avoid rendering invalid + data. + +## Example Registration + +```tsx +copilotkit.addActivityMessageRenderer({ + activityType: "retrieval", + content: z.object({ query: z.string(), sourceCount: z.number() }), + render: ({ content }) => ( +
+ 🔍 Searching "{content.query}" ({content.sourceCount} sources) +
+ ), +}); +``` + +## Tips + +- The returned function is stable (memoized with `useCallback`), so it’s safe to use inside lists without causing extra + renders. +- Renderers can access the resolved agent via the `agent` prop. Use this to read additional context (e.g., current + shared state). +- Combine with `CopilotChatToolCallsView` or `CopilotChatMessageView` to enrich the assistant experience with structured + status updates. diff --git a/apps/docs/reference/use-render-custom-messages.mdx b/apps/docs/reference/use-render-custom-messages.mdx new file mode 100644 index 00000000..39599bbb --- /dev/null +++ b/apps/docs/reference/use-render-custom-messages.mdx @@ -0,0 +1,109 @@ +--- +title: useRenderCustomMessages +description: Render custom React components alongside chat messages +--- + +`useRenderCustomMessages` returns a renderer function that lets you inject custom React components before or after any +chat message. The hook pulls the registered renderers from the current CopilotKit instance and scopes them to the active +agent/thread. + +## Basic Usage + +```tsx +import { useRenderCustomMessages } from "@copilotkitnext/react"; +import type { Message } from "@ag-ui/core"; + +function CustomMessageWrapper({ message }: { message: Message }) { + const renderCustomMessage = useRenderCustomMessages(); + + if (!renderCustomMessage) { + return null; + } + + return ( +
+ {/* Render before the message */} + {renderCustomMessage({ message, position: "before" })} + +

{message.content}

+ + {/* Render after the message */} + {renderCustomMessage({ message, position: "after" })} +
+ ); +} +``` + +## Return Value + +- Returns a function `(params) => ReactNode | null` that accepts `{ message, position }`. +- Returns `null` if no custom message renderers are registered or if the current chat configuration is unavailable. + +### `position` + +`"before" | "after"` + +Indicates whether you’re rendering content before or after the message bubble. Custom renderers can choose to render on +one or both positions. + +## Renderer Selection + +The hook filters the registered custom message renderers by: + +1. Agent ID – renderers tied to the active agent take priority. +2. Global renderers – renderers without an `agentId` act as fallbacks. + +The first renderer that returns a truthy React element wins. + +## Additional Data Provided to Renderers + +When you register a custom message renderer (via `copilotkit.addCustomMessageRenderer`) the render component receives a +rich set of props, including: + +- `runId` and run-scoped `stateSnapshot` +- `messageIndex` and `messageIndexInRun` +- `numberOfMessagesInRun` +- `agentId` + +`useRenderCustomMessages` passes these values through so your renderer can understand the surrounding context. + +## Example: Inline Tool Output + +```tsx +function ToolCallInspector({ message }: { message: Message }) { + const render = useRenderCustomMessages(); + if (!render) return null; + + return ( +
+ {render({ message, position: "after" })} +
+ ); +} +``` + +With a matching renderer registration: + +```tsx +copilotkit.addCustomMessageRenderer({ + name: "tool-debug", + agentId: "assistant", + render: ({ message, stateSnapshot }) => { + if (!message.toolCalls?.length) return null; + return ( +
+ Tool call details +
{JSON.stringify({ message, stateSnapshot }, null, 2)}
+
+ ); + }, +}); +``` + +## Tips + +- Call the hook inside components rendered within `CopilotChat` (or any component that has access to the + `CopilotChatConfigurationProvider`). +- The hook throws if it cannot find the agent referenced by the chat configuration. Ensure your provider and runtime are + configured before rendering custom content. +- Combine with the `WildcardToolCallRender` component to render arbitrary tool output when no specific renderer matches. diff --git a/apps/docs/reference/use-suggestions.mdx b/apps/docs/reference/use-suggestions.mdx new file mode 100644 index 00000000..51e6dcd5 --- /dev/null +++ b/apps/docs/reference/use-suggestions.mdx @@ -0,0 +1,106 @@ +--- +title: useSuggestions +description: React hook for accessing AI chat suggestions +--- + +`useSuggestions` exposes the live set of CopilotKit chat suggestions for an agent. It keeps UI state in sync with the +CopilotKit runtime, provides helpers to reload or clear suggestions, and tracks the loading state for you. + +## Basic Usage + +```tsx +import { useSuggestions } from "@copilotkitnext/react"; + +function SuggestionList() { + const { suggestions, isLoading, reloadSuggestions, clearSuggestions } = useSuggestions(); + + if (isLoading) { + return

Loading suggestions…

; + } + + if (!suggestions.length) { + return ( +
+

No suggestions yet.

+ +
+ ); + } + + return ( +
+
    + {suggestions.map((suggestion) => ( +
  • {suggestion.title ?? suggestion.message}
  • + ))} +
+ +
+ ); +} +``` + +## Parameters + +### agentId + +`string` **optional** + +By default the hook resolves the agent ID from the nearest `CopilotChatConfigurationProvider` (falling back to +`"default"`). Pass `agentId` when you want to read suggestions for a specific agent regardless of the active chat +configuration. + +```tsx +const { suggestions } = useSuggestions({ agentId: "support" }); +``` + +## Return Value + +The hook returns an object with four fields: + +| Field | Type | Description | +| ------------------ | ------------------ | -------------------------------------------------------------- | +| `suggestions` | `Suggestion[]` | The current list of suggestions for the agent. | +| `isLoading` | `boolean` | `true` while suggestions are being generated or refreshed. | +| `reloadSuggestions`| `() => void` | Requests a fresh set of suggestions from the runtime. | +| `clearSuggestions` | `() => void` | Clears the suggestions cached for the agent. | + +## Behavior + +- Subscribes to CopilotKit suggestion events (`onSuggestionsChanged`, `onSuggestionsStartedLoading`, + `onSuggestionsFinishedLoading`, `onSuggestionsConfigChanged`). +- Re-computes the agent ID when the surrounding chat configuration changes. +- Keeps local state in sync with the runtime cache so components re-render whenever suggestions update. + +## Refreshing Suggestions + +`reloadSuggestions` triggers CopilotKit to regenerate suggestions. The runtime emits loading events which the hook uses +to toggle `isLoading`. + +```tsx +const { isLoading, reloadSuggestions } = useSuggestions(); + +return ( + +); +``` + +## Clearing Suggestions + +`clearSuggestions` removes any cached suggestions for the agent. This is useful for flows where suggestions should be +reset after a user takes an action. + +```tsx +const { clearSuggestions } = useSuggestions({ agentId: "assistant" }); + +return ; +``` + +## Tips + +- When used alongside `useConfigureSuggestions`, the hook automatically reflects any dynamic or static suggestion + configuration you register. +- Because the hook subscribes to updates, place it in components that need live data. For static reads (for example, + logging) call `copilotkit.getSuggestions(agentId)` directly. diff --git a/apps/docs/reference/wildcard-tool-call-render.mdx b/apps/docs/reference/wildcard-tool-call-render.mdx new file mode 100644 index 00000000..c25feeb8 --- /dev/null +++ b/apps/docs/reference/wildcard-tool-call-render.mdx @@ -0,0 +1,31 @@ +--- +title: WildcardToolCallRender +description: Default renderer for tool calls without a custom component +--- + +`WildcardToolCallRender` is a ready-to-use component that displays any tool call in CopilotChat. It is registered as a +catch‑all (`name: "*"`) renderer and shows the tool name, execution status, arguments, and optional result in an +expandable card. + +## Basic Usage + +```tsx +import { WildcardToolCallRender } from "@copilotkitnext/react"; + +copilotkit.addToolCallRenderer(WildcardToolCallRender); +``` + +Once registered, any tool call without a more specific renderer appears in the chat with expandable “Arguments” and +“Result” sections—perfect for debugging or exposing raw tool output. + +## Features + +- Works for **any** tool (`name: "*"`). +- Indicates status (`inProgress`, `executing`, `complete`) with color-coded badges. +- Displays tool arguments and serialized results inside scrollable code blocks. +- Allows users to collapse/expand the details. + +## Customization + +Use it as-is for a quick inspector, or copy the component from the source to create your own variant (e.g., styling, +filters). Because it’s built with `defineToolCallRenderer`, it benefits from strong typing over the renderer props. diff --git a/apps/docs/troubleshooting/common-issues.mdx b/apps/docs/troubleshooting/common-issues.mdx new file mode 100644 index 00000000..78886871 --- /dev/null +++ b/apps/docs/troubleshooting/common-issues.mdx @@ -0,0 +1,469 @@ +--- +title: Common Issues +description: Solutions to common problems when using CopilotKit +icon: "circle-question" +--- + +## Installation Issues + +### Package Not Found + +**Problem:** Error installing `@copilotkitnext/*` packages + +**Solution:** +1. Ensure you're using the correct package names: + - `@copilotkitnext/core` + - `@copilotkitnext/react` + - `@copilotkitnext/angular` + - `@copilotkitnext/runtime` + +2. Clear your package manager cache: +```bash +# npm +npm cache clean --force + +# pnpm +pnpm store prune + +# yarn +yarn cache clean +``` + +3. Delete `node_modules` and reinstall: +```bash +rm -rf node_modules package-lock.json +npm install +``` + +### TypeScript Errors + +**Problem:** TypeScript compilation errors after installation + +**Solution:** +1. Ensure you have compatible TypeScript version (4.5+): +```bash +npm install --save-dev typescript@latest +``` + +2. Update your `tsconfig.json`: +```json +{ + "compilerOptions": { + "moduleResolution": "node", + "esModuleInterop": true, + "skipLibCheck": true + } +} +``` + +## Runtime Connection Issues + +### Cannot Connect to Runtime + +**Problem:** Frontend cannot connect to the runtime endpoint + +**Symptoms:** +- "Failed to connect to runtime" error +- Chat component not loading +- No response from agents + +**Solutions:** + +1. **Verify Runtime URL** +```tsx +// Make sure the URL is correct + +``` + +2. **Check CORS Configuration** +```typescript +// In your runtime setup +app.use(cors({ + origin: 'http://localhost:5173', // Your frontend URL + credentials: true, +})); +``` + +3. **Verify Runtime is Running** +```bash +# Check if the runtime server is running +curl http://localhost:3000/api/copilotkit/health +``` + +4. **Check Network Tab** +Open browser DevTools → Network tab to see the actual error + +### WebSocket Connection Failed + +**Problem:** WebSocket connection fails or disconnects + +**Solutions:** + +1. **Check Proxy Configuration** (for Vite/Next.js) +```javascript +// vite.config.js +export default { + server: { + proxy: { + '/api': { + target: 'http://localhost:3000', + ws: true, // Enable WebSocket proxying + }, + }, + }, +}; +``` + +2. **Verify WebSocket Support** +Ensure your hosting platform supports WebSockets (some serverless platforms don't) + +3. **Check Firewall/Network** +Corporate firewalls may block WebSocket connections + +## Agent Issues + +### Agent Not Responding + +**Problem:** Agent doesn't respond to messages + +**Solutions:** + +1. **Verify Agent Configuration** +```typescript +// Make sure agent is properly configured +export const POST = createCopilotRuntimeHandler({ + agents: { + assistant: { // Agent name must match + model: "gpt-4", + async *run({ messages, tools }) { + // Implementation + }, + }, + }, +}); +``` + +2. **Check API Keys** +```bash +# Verify your .env file +OPENAI_API_KEY=sk-... +``` + +3. **Check Console for Errors** +Look for error messages in both browser and server console + +4. **Verify Agent Name** +```tsx +// Agent name in useAgent must match runtime configuration +const agent = useAgent("assistant"); // Must match "assistant" in runtime +``` + +### Agent Using Wrong Tools + +**Problem:** Agent calls incorrect tools or doesn't use available tools + +**Solutions:** + +1. **Improve Tool Descriptions** +```tsx +useFrontendTool({ + name: "addTodo", + description: "Add a new todo item to the user's todo list. Use this when the user asks to add, create, or remember a task.", + // More specific description helps the agent +}); +``` + +2. **Add Parameter Descriptions** +```tsx +parameters: z.object({ + task: z.string().describe("The task description that the user wants to add"), + priority: z.enum(["low", "medium", "high"]).describe("The priority level of the task"), +}) +``` + +3. **Provide Context** +```tsx + +``` + +## Frontend Tool Issues + +### Tools Not Being Called + +**Problem:** Frontend tools are registered but agent doesn't call them + +**Solutions:** + +1. **Check Tool Registration** +```tsx +// Make sure tool is registered before chat component renders +useFrontendTool({ + name: "myTool", + // ... +}); +``` + +2. **Verify Tool is in Scope** +```tsx +// Tool must be registered in a component that's rendered +function MyComponent() { + useFrontendTool({ /* ... */ }); + return ; // Chat must be child of component with tool +} +``` + +3. **Check Tool Name Conflicts** +Ensure no duplicate tool names across frontend and backend + +### Tool Handler Not Executing + +**Problem:** Tool is called but handler doesn't execute + +**Solutions:** + +1. **Check for Errors in Handler** +```tsx +handler: async (args) => { + try { + // Your logic + return "Success"; + } catch (error) { + console.error("Tool error:", error); + return `Error: ${error.message}`; + } +} +``` + +2. **Verify Parameter Schema** +```tsx +// Make sure parameters match what agent sends +parameters: z.object({ + id: z.string(), // Not z.number() if agent sends string +}) +``` + +3. **Return a Value** +```tsx +handler: async (args) => { + doSomething(args); + return "Done"; // Always return something +} +``` + +## React-Specific Issues + +### Hooks Not Working + +**Problem:** CopilotKit hooks throw errors + +**Solutions:** + +1. **Ensure Provider is Present** +```tsx +// Hooks must be used inside CopilotKitProvider + + {/* Can use hooks here */} + +``` + +2. **Check Hook Rules** +```tsx +// ✅ Good: Hook at component top level +function MyComponent() { + useFrontendTool({ /* ... */ }); + return
...
; +} + +// ❌ Bad: Hook inside condition +function MyComponent() { + if (condition) { + useFrontendTool({ /* ... */ }); // Error! + } +} +``` + +### State Not Updating + +**Problem:** UI doesn't update when agent changes state + +**Solutions:** + +1. **Use State Hook Correctly** +```tsx +const { state, setState } = useAgentContext("agent"); + +// ✅ Good: Update state immutably +setState({ ...state, newValue: 123 }); + +// ❌ Bad: Mutate state directly +state.newValue = 123; // Won't trigger re-render +``` + +2. **Check Dependencies** +```tsx +useEffect(() => { + // React to state changes +}, [state]); // Include state in dependencies +``` + +## Angular-Specific Issues + +### Module Import Errors + +**Problem:** Cannot import CopilotKit module + +**Solutions:** + +1. **Import in App Module** +```typescript +import { CopilotKitModule } from '@copilotkitnext/angular'; + +@NgModule({ + imports: [ + CopilotKitModule.forRoot({ + runtimeUrl: 'http://localhost:3000/api/copilotkit', + }), + ], +}) +export class AppModule {} +``` + +2. **For Standalone Components** +```typescript +import { provideCopilotKit } from '@copilotkitnext/angular'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideCopilotKit({ + runtimeUrl: 'http://localhost:3000/api/copilotkit', + }), + ], +}; +``` + +### Change Detection Issues + +**Problem:** UI doesn't update after agent actions + +**Solutions:** + +1. **Trigger Change Detection** +```typescript +import { ChangeDetectorRef } from '@angular/core'; + +constructor(private cdr: ChangeDetectorRef) {} + +handler: async (args) => { + this.data = newData; + this.cdr.detectChanges(); // Manually trigger + return "Updated"; +} +``` + +2. **Use NgZone** +```typescript +import { NgZone } from '@angular/core'; + +constructor(private zone: NgZone) {} + +handler: async (args) => { + this.zone.run(() => { + this.data = newData; // Run inside Angular zone + }); + return "Updated"; +} +``` + +## Performance Issues + +### Slow Response Times + +**Problem:** Agent responses are slow + +**Solutions:** + +1. **Use Streaming** +```typescript +// Enable streaming in your runtime +async *run({ messages, tools }) { + const response = await openai.chat.completions.create({ + stream: true, // Enable streaming + // ... + }); + + for await (const chunk of response) { + yield chunk; + } +} +``` + +2. **Optimize Tool Handlers** +```tsx +handler: async (args) => { + // ✅ Good: Fast operation + return quickOperation(args); + + // ❌ Bad: Slow synchronous operation + const result = slowSyncOperation(args); + return result; +} +``` + +3. **Reduce Context Size** +```tsx +// Don't send unnecessary data + +``` + +### Memory Leaks + +**Problem:** Application memory usage grows over time + +**Solutions:** + +1. **Clean Up Subscriptions** +```tsx +useEffect(() => { + const subscription = agent.subscribe(/* ... */); + + return () => { + subscription.unsubscribe(); // Clean up + }; +}, []); +``` + +2. **Memoize Components** +```tsx +const MemoizedComponent = memo(MyComponent); +``` + +## Getting More Help + +If you're still experiencing issues: + + + + Get help from the community + + + Report bugs or request features + + + Learn advanced debugging techniques + + + Understand how CopilotKit works + + + + diff --git a/apps/docs/troubleshooting/debugging.mdx b/apps/docs/troubleshooting/debugging.mdx new file mode 100644 index 00000000..09d08c16 --- /dev/null +++ b/apps/docs/troubleshooting/debugging.mdx @@ -0,0 +1,500 @@ +--- +title: Debugging Guide +description: Advanced debugging techniques for CopilotKit +icon: "bug" +--- + +## Enable Debug Mode + +CopilotKit includes built-in debugging tools to help you troubleshoot issues. + +### Frontend Debugging + +Enable debug logging in your provider: + +```tsx + + {children} + +``` + +This will log: +- Agent messages and responses +- Tool calls and results +- State changes +- Connection events + +### Runtime Debugging + +Enable debug logging in your runtime: + +```typescript +export const POST = createCopilotRuntimeHandler({ + debug: true, // Enable debug mode + agents: { + // ... + }, +}); +``` + +## Browser DevTools + +### Console Logging + +Filter CopilotKit logs in the console: + +``` +[CopilotKit] Agent message: ... +[CopilotKit] Tool call: addTodo +[CopilotKit] State update: ... +``` + +Use console filters to focus on specific events: +- `[CopilotKit]` - All CopilotKit logs +- `[CopilotKit:Agent]` - Agent-specific logs +- `[CopilotKit:Tool]` - Tool execution logs +- `[CopilotKit:State]` - State changes + +### Network Tab + +Monitor runtime communication: + +1. Open DevTools → Network tab +2. Filter by "copilotkit" or your runtime URL +3. Inspect request/response payloads +4. Check for errors or slow requests + +**What to look for:** +- Request status codes (should be 200) +- Response times +- WebSocket connection status +- Error messages in responses + +### React DevTools + +For React applications, use React DevTools: + +1. Install React DevTools extension +2. Inspect component tree +3. Check CopilotKitProvider context +4. Monitor state changes in real-time + +## Debugging Tools + +### Tool Call Inspector + +Log all tool calls with detailed information: + +```tsx +useFrontendTool({ + name: "myTool", + description: "...", + parameters: schema, + handler: async (args) => { + console.log("Tool called:", { + name: "myTool", + args, + timestamp: new Date().toISOString(), + }); + + try { + const result = await performAction(args); + console.log("Tool result:", result); + return result; + } catch (error) { + console.error("Tool error:", error); + throw error; + } + }, +}); +``` + +### State Change Tracker + +Monitor state changes: + +```tsx +function StateDebugger() { + const { state } = useAgentContext("agent"); + + useEffect(() => { + console.log("State changed:", { + timestamp: new Date().toISOString(), + state: JSON.stringify(state, null, 2), + }); + }, [state]); + + return null; +} +``` + +### Message Inspector + +Log all agent messages: + +```tsx +function MessageDebugger() { + const agent = useAgent("assistant"); + + useEffect(() => { + const unsubscribe = agent.onMessage((message) => { + console.log("Agent message:", { + role: message.role, + content: message.content, + timestamp: new Date().toISOString(), + }); + }); + + return unsubscribe; + }, [agent]); + + return null; +} +``` + +## Common Debugging Scenarios + +### Debugging Tool Execution + +**Problem:** Tool is called but doesn't work as expected + +**Debug Steps:** + +1. **Log the arguments:** +```tsx +handler: async (args) => { + console.log("Received args:", JSON.stringify(args, null, 2)); + // Check if args match your expectations +} +``` + +2. **Validate the schema:** +```tsx +parameters: z.object({ + id: z.string(), +}).passthrough() // Allow extra properties for debugging +``` + +3. **Test the handler directly:** +```tsx +// In browser console +window.testTool = async (args) => { + return await yourToolHandler(args); +}; + +// Then test: +await window.testTool({ id: "123" }); +``` + +### Debugging State Synchronization + +**Problem:** State not syncing between UI and agent + +**Debug Steps:** + +1. **Log state updates:** +```tsx +const { state, setState } = useAgentContext("agent"); + +const debugSetState = (newState) => { + console.log("Setting state:", { + old: state, + new: newState, + }); + setState(newState); +}; +``` + +2. **Check state subscription:** +```tsx +useEffect(() => { + console.log("State subscription active"); + return () => console.log("State subscription cleaned up"); +}, []); +``` + +3. **Verify state shape:** +```tsx +useEffect(() => { + console.log("Current state:", { + type: typeof state, + keys: Object.keys(state || {}), + values: state, + }); +}, [state]); +``` + +### Debugging Agent Responses + +**Problem:** Agent not responding or giving unexpected responses + +**Debug Steps:** + +1. **Log the full conversation:** +```tsx +const agent = useAgent("assistant"); + +useEffect(() => { + console.log("Conversation history:", agent.messages); +}, [agent.messages]); +``` + +2. **Check context:** +```tsx + console.log("Context changed:", ctx)} +> +``` + +3. **Inspect runtime logs:** +```typescript +// In your runtime +async *run({ messages, tools, context }) { + console.log("Runtime received:", { + messageCount: messages.length, + toolCount: tools.length, + context, + }); + + // Your agent logic +} +``` + +## Performance Debugging + +### Measure Render Performance + +Use React Profiler: + +```tsx +import { Profiler } from 'react'; + +function onRenderCallback( + id, + phase, + actualDuration, + baseDuration, + startTime, + commitTime +) { + console.log(`${id} (${phase}) took ${actualDuration}ms`); +} + + + + +``` + +### Measure Tool Execution Time + +```tsx +handler: async (args) => { + const start = performance.now(); + + try { + const result = await yourLogic(args); + const duration = performance.now() - start; + console.log(`Tool executed in ${duration}ms`); + return result; + } catch (error) { + const duration = performance.now() - start; + console.error(`Tool failed after ${duration}ms:`, error); + throw error; + } +} +``` + +### Monitor Memory Usage + +```typescript +// Log memory usage periodically +setInterval(() => { + if (performance.memory) { + console.log("Memory usage:", { + used: `${(performance.memory.usedJSHeapSize / 1048576).toFixed(2)} MB`, + total: `${(performance.memory.totalJSHeapSize / 1048576).toFixed(2)} MB`, + limit: `${(performance.memory.jsHeapSizeLimit / 1048576).toFixed(2)} MB`, + }); + } +}, 10000); // Every 10 seconds +``` + +## Runtime Debugging + +### Server-Side Logging + +Add comprehensive logging to your runtime: + +```typescript +export const POST = createCopilotRuntimeHandler({ + agents: { + assistant: { + async *run({ messages, tools, context }) { + console.log("[Runtime] Request received:", { + messageCount: messages.length, + toolCount: tools.length, + context, + }); + + try { + const response = await openai.chat.completions.create({ + model: "gpt-4", + messages, + tools, + stream: true, + }); + + let chunkCount = 0; + for await (const chunk of response) { + chunkCount++; + console.log(`[Runtime] Chunk ${chunkCount}:`, chunk); + yield chunk; + } + + console.log(`[Runtime] Completed with ${chunkCount} chunks`); + } catch (error) { + console.error("[Runtime] Error:", error); + throw error; + } + }, + }, + }, + onError: (error) => { + console.error("[Runtime] Handler error:", { + message: error.message, + stack: error.stack, + }); + }, +}); +``` + +### Request/Response Logging + +Log all HTTP requests and responses: + +```typescript +app.use((req, res, next) => { + console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`); + + const originalSend = res.send; + res.send = function (data) { + console.log(`[${new Date().toISOString()}] Response:`, { + status: res.statusCode, + data: typeof data === 'string' ? data.substring(0, 100) : data, + }); + return originalSend.call(this, data); + }; + + next(); +}); +``` + +## Testing Tools + +### Unit Testing Tools + +Test tool handlers in isolation: + +```typescript +import { describe, it, expect } from 'vitest'; + +describe('addTodo tool', () => { + it('should add todo to list', async () => { + const handler = createAddTodoHandler(); + const result = await handler({ task: 'Test task' }); + + expect(result).toContain('Added'); + expect(result).toContain('Test task'); + }); + + it('should handle errors', async () => { + const handler = createAddTodoHandler(); + + await expect( + handler({ task: '' }) + ).rejects.toThrow('Task cannot be empty'); + }); +}); +``` + +### Integration Testing + +Test full agent interactions: + +```typescript +import { render, screen, waitFor } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +describe('CopilotChat integration', () => { + it('should execute tool when requested', async () => { + const mockHandler = vi.fn().mockResolvedValue('Success'); + + render( + + + + ); + + const input = screen.getByPlaceholderText('Type a message...'); + await userEvent.type(input, 'Add a todo{enter}'); + + await waitFor(() => { + expect(mockHandler).toHaveBeenCalled(); + }); + }); +}); +``` + +## Debugging Checklist + +When debugging an issue, go through this checklist: + +- [ ] Check browser console for errors +- [ ] Check server/runtime logs +- [ ] Verify network requests in DevTools +- [ ] Confirm runtime is running and accessible +- [ ] Validate tool schemas and descriptions +- [ ] Check agent configuration +- [ ] Verify API keys and credentials +- [ ] Test with debug mode enabled +- [ ] Isolate the issue (frontend vs runtime) +- [ ] Create minimal reproduction case + +## Getting Help + +If you're still stuck after debugging: + + + + Share your debugging findings with the community + + + Create a detailed bug report + + + Check solutions to common problems + + + Understand the system architecture + + + +## Best Practices + +1. **Always use debug mode during development** +2. **Log important events and state changes** +3. **Test tools in isolation first** +4. **Monitor network requests** +5. **Keep runtime logs accessible** +6. **Use TypeScript for better error messages** +7. **Write tests for critical functionality** +8. **Document known issues and workarounds** + +