@copilotkit/react-core 1.71.0 → 1.71.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/{copilotkit-B4Jb1QEy.cjs → copilotkit-BkVEkUS0.cjs} +5 -2
  2. package/dist/copilotkit-BkVEkUS0.cjs.map +1 -0
  3. package/dist/{copilotkit-snbJkMqQ.mjs → copilotkit-D5BTo0YG.mjs} +5 -2
  4. package/dist/copilotkit-D5BTo0YG.mjs.map +1 -0
  5. package/dist/index.cjs +1 -1
  6. package/dist/index.mjs +1 -1
  7. package/dist/index.umd.js +4 -1
  8. package/dist/index.umd.js.map +1 -1
  9. package/dist/v2/headless.cjs +4 -1
  10. package/dist/v2/headless.cjs.map +1 -1
  11. package/dist/v2/headless.mjs +4 -1
  12. package/dist/v2/headless.mjs.map +1 -1
  13. package/dist/v2/index.cjs +1 -1
  14. package/dist/v2/index.mjs +1 -1
  15. package/dist/v2/index.umd.js +4 -1
  16. package/dist/v2/index.umd.js.map +1 -1
  17. package/package.json +8 -9
  18. package/dist/copilotkit-B4Jb1QEy.cjs.map +0 -1
  19. package/dist/copilotkit-snbJkMqQ.mjs.map +0 -1
  20. package/skills/react-core/SKILL.md +0 -110
  21. package/skills/react-core/references/agent-access.md +0 -398
  22. package/skills/react-core/references/attachments.md +0 -311
  23. package/skills/react-core/references/capabilities.md +0 -138
  24. package/skills/react-core/references/chat-components.md +0 -246
  25. package/skills/react-core/references/client-side-tools.md +0 -358
  26. package/skills/react-core/references/custom-message-renderers.md +0 -223
  27. package/skills/react-core/references/debug-mode.md +0 -140
  28. package/skills/react-core/references/human-in-the-loop.md +0 -312
  29. package/skills/react-core/references/provider-setup.md +0 -358
  30. package/skills/react-core/references/rendering-activity-messages.md +0 -201
  31. package/skills/react-core/references/rendering-tool-calls.md +0 -319
  32. package/skills/react-core/references/suggestions.md +0 -211
  33. package/skills/react-core/references/switching-agents-recipes.md +0 -161
  34. package/skills/react-core/references/switching-agents.md +0 -240
  35. package/skills/react-core/references/threads.md +0 -289
@@ -1,211 +0,0 @@
1
- # CopilotKit Suggestions (React)
2
-
3
- This skill builds on `copilotkit/provider-setup` and
4
- `copilotkit/chat-components`. Suggestions render via
5
- `CopilotChatSuggestionView` which `<CopilotChat>` mounts automatically.
6
-
7
- Two sides:
8
-
9
- - `useConfigureSuggestions(config, deps?)` — register dynamic (LLM) or
10
- static suggestions.
11
- - `useSuggestions({ agentId })` — read current suggestions + trigger
12
- reload / clear.
13
-
14
- ## Setup
15
-
16
- ### Dynamic suggestions (LLM-generated)
17
-
18
- ```tsx
19
- "use client";
20
- import { useConfigureSuggestions } from "@copilotkit/react-core/v2";
21
- import { useMemo } from "react";
22
-
23
- export function DynamicSuggestionsHost({ page }: { page: string }) {
24
- const instructions = useMemo(
25
- () => `Suggest 3 follow-up questions about the "${page}" page.`,
26
- [page],
27
- );
28
-
29
- useConfigureSuggestions(
30
- {
31
- instructions,
32
- minSuggestions: 2,
33
- maxSuggestions: 4,
34
- available: "always",
35
- },
36
- [page],
37
- );
38
-
39
- return null;
40
- }
41
- ```
42
-
43
- ### Static suggestions
44
-
45
- ```tsx
46
- "use client";
47
- import { useConfigureSuggestions } from "@copilotkit/react-core/v2";
48
-
49
- export function StaticStarters() {
50
- useConfigureSuggestions({
51
- suggestions: [
52
- { title: "Summarize this page", message: "Summarize the current page." },
53
- { title: "Explain like I'm 5", message: "Explain this in simple terms." },
54
- ],
55
- available: "before-first-message",
56
- });
57
- return null;
58
- }
59
- ```
60
-
61
- ## Core Patterns
62
-
63
- ### Read and refresh suggestions from any component
64
-
65
- ```tsx
66
- import { useSuggestions } from "@copilotkit/react-core/v2";
67
-
68
- export function RefreshButton() {
69
- const { suggestions, reloadSuggestions, clearSuggestions, isLoading } =
70
- useSuggestions({ agentId: "default" });
71
- return (
72
- <div>
73
- <button onClick={reloadSuggestions} disabled={isLoading}>
74
- {isLoading ? "Loading…" : "Refresh"}
75
- </button>
76
- <button onClick={clearSuggestions}>Clear</button>
77
- <span>{suggestions.length} suggestions</span>
78
- </div>
79
- );
80
- }
81
- ```
82
-
83
- ### Feature-flag the suggestions config
84
-
85
- ```tsx
86
- const enabled = useFeatureFlag("suggestions");
87
- useConfigureSuggestions(
88
- enabled ? { instructions: "Suggest 3 follow-ups" } : null,
89
- );
90
- ```
91
-
92
- ### Agent-scoped dynamic suggestions
93
-
94
- ```tsx
95
- useConfigureSuggestions({
96
- instructions: "Suggest follow-ups for the research agent.",
97
- consumerAgentId: "research",
98
- });
99
- ```
100
-
101
- ## Common Mistakes
102
-
103
- ### MEDIUM — Using `available: "disabled"` expecting reload to still fire
104
-
105
- Wrong:
106
-
107
- ```tsx
108
- useConfigureSuggestions({
109
- instructions: "Suggest 3 follow-ups",
110
- available: "disabled",
111
- });
112
- // Then calling reloadSuggestions() — no-op
113
- ```
114
-
115
- Correct:
116
-
117
- ```tsx
118
- const enabled = useFeatureFlag("suggestions");
119
- useConfigureSuggestions(
120
- enabled ? { instructions: "Suggest 3 follow-ups" } : null,
121
- );
122
- ```
123
-
124
- `available: "disabled"` is normalized to a `null` config — the same as
125
- passing `null`/`undefined`. Reloads become no-ops. Pass `null` (or gate on
126
- a condition) when you want to fully disable suggestions.
127
-
128
- Source: `packages/react-core/src/v2/hooks/use-configure-suggestions.tsx:59-62`
129
-
130
- ### MEDIUM — Inline config object without `deps`
131
-
132
- Wrong:
133
-
134
- ```tsx
135
- useConfigureSuggestions({ instructions: `about ${currentPage}` });
136
- // Config re-serialized every render — reload may or may not fire depending on cache equality
137
- ```
138
-
139
- Correct:
140
-
141
- ```tsx
142
- useConfigureSuggestions({ instructions: `about ${currentPage}` }, [
143
- currentPage,
144
- ]);
145
- ```
146
-
147
- `useConfigureSuggestions` uses a serialized-config cache keyed off the
148
- JSON-stringified value. Without `deps`, React invariance + inline objects
149
- produce unstable identities that thrash the cache. Always pass `deps` that
150
- cover the values interpolated into the config.
151
-
152
- Source: `packages/react-core/src/v2/hooks/use-configure-suggestions.tsx:166-171`
153
-
154
- ### MEDIUM — Calling `reloadSuggestions` mid-run
155
-
156
- Wrong:
157
-
158
- ```tsx
159
- <button onClick={() => reloadSuggestions()}>Refresh</button>
160
- // Fires during agent streaming → competes with the running agent
161
- ```
162
-
163
- Correct:
164
-
165
- ```tsx
166
- import { useAgent, UseAgentUpdate } from "@copilotkit/react-core/v2";
167
-
168
- const { agent } = useAgent({
169
- agentId: "default",
170
- updates: [UseAgentUpdate.OnRunStatusChanged],
171
- });
172
- const isRunning = agent.isRunning;
173
- <button
174
- disabled={isRunning}
175
- onClick={() => {
176
- if (!isRunning) reloadSuggestions();
177
- }}
178
- >
179
- Refresh
180
- </button>;
181
- ```
182
-
183
- The internal auto-reload skips when `isRunning`, but the user-triggered
184
- `reloadSuggestions()` does not guard itself. Guard the caller, or the
185
- suggestion generation races the active agent run.
186
-
187
- Source: `packages/react-core/src/v2/hooks/use-configure-suggestions.tsx:121-124`
188
-
189
- ### MEDIUM — Expecting `maxSuggestions` above 3 without setting it
190
-
191
- Wrong:
192
-
193
- ```tsx
194
- useConfigureSuggestions({ instructions: "…" });
195
- // Then surprised the UI only shows 3 pills even when the LLM returned 8
196
- ```
197
-
198
- Correct:
199
-
200
- ```tsx
201
- useConfigureSuggestions({
202
- instructions: "…",
203
- minSuggestions: 1,
204
- maxSuggestions: 6,
205
- });
206
- ```
207
-
208
- `minSuggestions` and `maxSuggestions` default to 1 and 3 respectively. Set
209
- them explicitly when you want a different count.
210
-
211
- Source: `packages/core/src/types.ts` (DynamicSuggestionsConfig defaults)
@@ -1,161 +0,0 @@
1
- # Agent Switcher Recipes
2
-
3
- Three copy-paste patterns for multi-agent UIs. All subscribe to
4
- `copilotkit.subscribe({ onAgentsChanged })` for live agent discovery — there
5
- is no `useAgents()` hook.
6
-
7
- ## Recipe 1 — Dropdown switcher
8
-
9
- ```tsx
10
- "use client";
11
- import { CopilotChat, useCopilotKit } from "@copilotkit/react-core/v2";
12
- import { useEffect, useState } from "react";
13
-
14
- export function DropdownAgentSwitcher() {
15
- const { copilotkit } = useCopilotKit();
16
- const [agentIds, setAgentIds] = useState<string[]>(() =>
17
- Object.keys(copilotkit.agents ?? {}),
18
- );
19
- const [activeAgent, setActiveAgent] = useState<string>(
20
- () => Object.keys(copilotkit.agents ?? {})[0] ?? "default",
21
- );
22
-
23
- useEffect(() => {
24
- const sub = copilotkit.subscribe({
25
- onAgentsChanged: ({ agents }) => {
26
- setAgentIds(Object.keys(agents ?? {}));
27
- },
28
- });
29
- return () => sub.unsubscribe();
30
- }, [copilotkit]);
31
-
32
- return (
33
- <div className="flex flex-col gap-3">
34
- <select
35
- value={activeAgent}
36
- onChange={(e) => setActiveAgent(e.target.value)}
37
- >
38
- {agentIds.map((id) => (
39
- <option key={id} value={id}>
40
- {id}
41
- </option>
42
- ))}
43
- </select>
44
- <CopilotChat key={activeAgent} agentId={activeAgent} />
45
- </div>
46
- );
47
- }
48
- ```
49
-
50
- ## Recipe 2 — Tabs switcher
51
-
52
- ```tsx
53
- "use client";
54
- import { CopilotChat, useCopilotKit } from "@copilotkit/react-core/v2";
55
- import { useEffect, useRef, useState } from "react";
56
-
57
- export function TabsAgentSwitcher() {
58
- const { copilotkit } = useCopilotKit();
59
- const [agentIds, setAgentIds] = useState<string[]>(() =>
60
- Object.keys(copilotkit.agents ?? {}),
61
- );
62
- const [activeAgent, setActiveAgent] = useState<string>(
63
- () => agentIds[0] ?? "default",
64
- );
65
-
66
- // Hold activeAgent in a ref so the subscribe effect only re-binds when
67
- // `copilotkit` changes. Depending on `activeAgent` would tear down and
68
- // re-establish the subscription on every tab click.
69
- const activeAgentRef = useRef(activeAgent);
70
- useEffect(() => {
71
- activeAgentRef.current = activeAgent;
72
- }, [activeAgent]);
73
-
74
- useEffect(() => {
75
- const sub = copilotkit.subscribe({
76
- onAgentsChanged: ({ agents }) => {
77
- const ids = Object.keys(agents ?? {});
78
- setAgentIds(ids);
79
- if (!ids.includes(activeAgentRef.current) && ids.length > 0) {
80
- setActiveAgent(ids[0]);
81
- }
82
- },
83
- });
84
- return () => sub.unsubscribe();
85
- }, [copilotkit]);
86
-
87
- return (
88
- <div>
89
- <div role="tablist" className="flex gap-2 border-b">
90
- {agentIds.map((id) => (
91
- <button
92
- key={id}
93
- role="tab"
94
- aria-selected={id === activeAgent}
95
- onClick={() => setActiveAgent(id)}
96
- >
97
- {id}
98
- </button>
99
- ))}
100
- </div>
101
- <CopilotChat key={activeAgent} agentId={activeAgent} />
102
- </div>
103
- );
104
- }
105
- ```
106
-
107
- ## Recipe 3 — Keyboard shortcut switcher
108
-
109
- Cycles through agents with `Cmd/Ctrl + Shift + A`.
110
-
111
- ```tsx
112
- "use client";
113
- import { CopilotChat, useCopilotKit } from "@copilotkit/react-core/v2";
114
- import { useEffect, useState } from "react";
115
-
116
- export function KeyboardAgentSwitcher() {
117
- const { copilotkit } = useCopilotKit();
118
- const [agentIds, setAgentIds] = useState<string[]>(() =>
119
- Object.keys(copilotkit.agents ?? {}),
120
- );
121
- const [activeAgent, setActiveAgent] = useState<string>(
122
- () => agentIds[0] ?? "default",
123
- );
124
-
125
- useEffect(() => {
126
- const sub = copilotkit.subscribe({
127
- onAgentsChanged: ({ agents }) => setAgentIds(Object.keys(agents ?? {})),
128
- });
129
- return () => sub.unsubscribe();
130
- }, [copilotkit]);
131
-
132
- useEffect(() => {
133
- function onKey(e: KeyboardEvent) {
134
- const isCombo = (e.metaKey || e.ctrlKey) && e.shiftKey && e.key === "A";
135
- if (!isCombo || agentIds.length === 0) return;
136
- e.preventDefault();
137
- const idx = agentIds.indexOf(activeAgent);
138
- const next = agentIds[(idx + 1) % agentIds.length];
139
- setActiveAgent(next);
140
- }
141
- window.addEventListener("keydown", onKey);
142
- return () => window.removeEventListener("keydown", onKey);
143
- }, [agentIds, activeAgent]);
144
-
145
- return (
146
- <div>
147
- <div className="text-xs opacity-60">
148
- Active: {activeAgent} — press ⌘/Ctrl+Shift+A to cycle
149
- </div>
150
- <CopilotChat key={activeAgent} agentId={activeAgent} />
151
- </div>
152
- );
153
- }
154
- ```
155
-
156
- ## Key rules across all three recipes
157
-
158
- - Use `copilotkit.subscribe({ onAgentsChanged })` — there is no `useAgents()` hook.
159
- - Always `key={activeAgent}` on `<CopilotChat>` so thread state doesn't leak when swapping agents in the same slot.
160
- - Keep that `key` on `<CopilotChat>` and nowhere higher. A `key` discards every bit of state beneath it, so on a wrapper or a layout provider it silently wipes app state too.
161
- - Clean up the subscription with `sub.unsubscribe()` in the effect cleanup.
@@ -1,240 +0,0 @@
1
- # CopilotKit Switching Agents (React)
2
-
3
- This skill builds on `copilotkit/agent-access`, `copilotkit/client-side-tools`,
4
- and `copilotkit/rendering-tool-calls`.
5
-
6
- Three main patterns:
7
-
8
- 1. **Parallel panels** — one `useAgent({ agentId })` per surface.
9
- 2. **Slot swap** — `<CopilotChat key={agentId} agentId={agentId} />`.
10
- 3. **Discovery** — subscribe to `onAgentsChanged` (no `useAgents()` hook).
11
-
12
- ## Setup
13
-
14
- ```tsx
15
- "use client";
16
- import { CopilotChat } from "@copilotkit/react-core/v2";
17
- import { useState } from "react";
18
-
19
- export function AgentSwitcherChat() {
20
- const [activeAgent, setActiveAgent] = useState("research");
21
-
22
- return (
23
- <div>
24
- <div>
25
- <button onClick={() => setActiveAgent("research")}>Research</button>
26
- <button onClick={() => setActiveAgent("coding")}>Coding</button>
27
- </div>
28
-
29
- {/* key={activeAgent} forces remount so thread state doesn't leak */}
30
- <CopilotChat key={activeAgent} agentId={activeAgent} />
31
- </div>
32
- );
33
- }
34
- ```
35
-
36
- ## Core Patterns
37
-
38
- ### Side-by-side chat panels
39
-
40
- ```tsx
41
- <div className="grid grid-cols-2 gap-4">
42
- <CopilotChat agentId="research" threadId="research-main" />
43
- <CopilotChat agentId="coding" threadId="coding-main" />
44
- </div>
45
- ```
46
-
47
- ### Agent-scoped tool
48
-
49
- ```tsx
50
- import { useFrontendTool } from "@copilotkit/react-core/v2";
51
- import { z } from "zod";
52
-
53
- useFrontendTool({
54
- name: "saveFindings",
55
- agentId: "research", // ← only the research agent sees this tool
56
- parameters: z.object({ summary: z.string() }),
57
- handler: async ({ summary }) => {
58
- await fetch("/api/findings", { method: "POST", body: summary });
59
- },
60
- });
61
- ```
62
-
63
- ### Agent-scoped renderer
64
-
65
- ```tsx
66
- import { useRenderTool } from "@copilotkit/react-core/v2";
67
- import { z } from "zod";
68
-
69
- useRenderTool({
70
- name: "search",
71
- agentId: "research", // ← only applies to research's "search" tool
72
- parameters: z.object({ q: z.string() }),
73
- render: ({ status, parameters, result }) => {
74
- if (status === "inProgress") return <div>Preparing...</div>;
75
- if (status === "executing") return <div>Searching {parameters.q}</div>;
76
- return <div>{result}</div>;
77
- },
78
- });
79
- ```
80
-
81
- ### Discover available agents (no `useAgents` hook)
82
-
83
- ```tsx
84
- "use client";
85
- import { useCopilotKit } from "@copilotkit/react-core/v2";
86
- import { useEffect, useState } from "react";
87
-
88
- export function useAvailableAgents() {
89
- const { copilotkit } = useCopilotKit();
90
- const [ids, setIds] = useState<string[]>(() =>
91
- Object.keys(copilotkit.agents ?? {}),
92
- );
93
-
94
- useEffect(() => {
95
- const subscription = copilotkit.subscribe({
96
- onAgentsChanged: ({ agents }) => {
97
- setIds(Object.keys(agents ?? {}));
98
- },
99
- });
100
- return () => subscription.unsubscribe();
101
- }, [copilotkit]);
102
-
103
- return ids;
104
- }
105
- ```
106
-
107
- ## Common Mistakes
108
-
109
- ### HIGH — Switching `agentId` on a persisted `<CopilotChat>` without `key`
110
-
111
- Wrong:
112
-
113
- ```tsx
114
- <CopilotChat agentId={activeAgent} />
115
- ```
116
-
117
- Correct:
118
-
119
- ```tsx
120
- <CopilotChat key={activeAgent} agentId={activeAgent} />
121
- ```
122
-
123
- Without remount via `key`, prior thread state and in-flight runs leak into
124
- the new agent's view. The remount pattern gives each agent a clean slate.
125
-
126
- Keep the `key` on `<CopilotChat>` itself. It discards all state below it, so
127
- hoisting it onto a wrapper or a layout-level provider also destroys app
128
- state that has nothing to do with the agent — correlation maps, in-flight
129
- request records, refs — with no error and no warning. If a component
130
- dispatches requests and matches the responses back, it must sit outside the
131
- keyed subtree. See "Keying a subtree on the active thread id above app
132
- state" in `references/threads.md` for the thread-switching version of the
133
- same trap.
134
-
135
- Source: `examples/v2/react-router/app/routes/_index.tsx:38-39`
136
-
137
- ### MEDIUM — Omitting `agentId` when multiple agents share a tool name
138
-
139
- Wrong:
140
-
141
- ```tsx
142
- // Both research and coding agents have a "search" tool — unscoped wins globally
143
- useRenderToolCall({
144
- name: "search",
145
- args: z.object({ q: z.string() }),
146
- render,
147
- });
148
- ```
149
-
150
- Correct:
151
-
152
- ```tsx
153
- useRenderTool({
154
- name: "search",
155
- agentId: "research",
156
- parameters: z.object({ q: z.string() }),
157
- render: researchSearchRender,
158
- });
159
- useRenderTool({
160
- name: "search",
161
- agentId: "coding",
162
- parameters: z.object({ q: z.string() }),
163
- render: codingSearchRender,
164
- });
165
- ```
166
-
167
- Unscoped renderers apply to every agent. When two agents have a tool with
168
- the same name and only one has a renderer, the unscoped renderer wins
169
- globally and the other agent never gets its intended renderer.
170
-
171
- Source: `packages/react-core/src/v2/hooks/use-render-tool-call.tsx:145-154`
172
-
173
- ### MEDIUM — Tools registered without `agentId` leak across panels
174
-
175
- Wrong:
176
-
177
- ```tsx
178
- useFrontendTool({
179
- name: "saveFindings",
180
- parameters: z.object({ summary: z.string() }),
181
- handler,
182
- });
183
- // Both research and coding agents now see saveFindings.
184
- ```
185
-
186
- Correct:
187
-
188
- ```tsx
189
- useFrontendTool({
190
- name: "saveFindings",
191
- agentId: "research",
192
- parameters: z.object({ summary: z.string() }),
193
- handler,
194
- });
195
- ```
196
-
197
- Omitting `agentId` attaches the tool to every agent. In a multi-agent UI
198
- this leaks the handler across panels. Scope tools explicitly when they
199
- should only apply to one agent.
200
-
201
- Source: `packages/react-core/src/v2/hooks/use-frontend-tool.tsx`
202
-
203
- ### MEDIUM — Using `useAgents()` (does not exist)
204
-
205
- Wrong:
206
-
207
- ```tsx
208
- import { useAgents } from "@copilotkit/react-core/v2"; // not exported
209
- const agents = useAgents();
210
- ```
211
-
212
- Correct:
213
-
214
- ```tsx
215
- import { useCopilotKit } from "@copilotkit/react-core/v2";
216
- import { useEffect, useState } from "react";
217
-
218
- function useAvailableAgents() {
219
- const { copilotkit } = useCopilotKit();
220
- const [ids, setIds] = useState<string[]>(() =>
221
- Object.keys(copilotkit.agents ?? {}),
222
- );
223
- useEffect(() => {
224
- const sub = copilotkit.subscribe({
225
- onAgentsChanged: ({ agents }) => setIds(Object.keys(agents ?? {})),
226
- });
227
- return () => sub.unsubscribe();
228
- }, [copilotkit]);
229
- return ids;
230
- }
231
- ```
232
-
233
- There is no `useAgents` hook in v2. Discover agents by subscribing to
234
- `onAgentsChanged` on the core client.
235
-
236
- Source: `packages/react-core/src/v2/hooks/index.ts` (no `useAgents` export)
237
-
238
- ## References
239
-
240
- - [Agent switcher recipes](switching-agents-recipes.md) — dropdown, tabs, keyboard shortcuts