@copilotkit/runtime 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 (37) hide show
  1. package/dist/agent/index.cjs +1 -1
  2. package/dist/agent/index.cjs.map +1 -1
  3. package/dist/agent/index.d.cts.map +1 -1
  4. package/dist/agent/index.d.mts.map +1 -1
  5. package/dist/agent/index.mjs +1 -1
  6. package/dist/agent/index.mjs.map +1 -1
  7. package/dist/package.cjs +3 -3
  8. package/dist/package.mjs +3 -3
  9. package/package.json +4 -5
  10. package/skills/runtime/SKILL.md +0 -98
  11. package/skills/runtime/references/agent-runners-custom.md +0 -161
  12. package/skills/runtime/references/agent-runners-in-memory.md +0 -79
  13. package/skills/runtime/references/agent-runners-sqlite.md +0 -90
  14. package/skills/runtime/references/agent-runners.md +0 -336
  15. package/skills/runtime/references/built-in-agent-factory-modes.md +0 -232
  16. package/skills/runtime/references/built-in-agent-helper-utilities.md +0 -123
  17. package/skills/runtime/references/built-in-agent-model-identifiers.md +0 -58
  18. package/skills/runtime/references/built-in-agent.md +0 -523
  19. package/skills/runtime/references/intelligence-mode.md +0 -364
  20. package/skills/runtime/references/middleware.md +0 -376
  21. package/skills/runtime/references/server-side-tools.md +0 -414
  22. package/skills/runtime/references/setup-endpoint.md +0 -503
  23. package/skills/runtime/references/transcription.md +0 -287
  24. package/skills/runtime/references/wiring-a2a.md +0 -40
  25. package/skills/runtime/references/wiring-adk.md +0 -45
  26. package/skills/runtime/references/wiring-ag2.md +0 -41
  27. package/skills/runtime/references/wiring-agno.md +0 -40
  28. package/skills/runtime/references/wiring-aws-strands.md +0 -59
  29. package/skills/runtime/references/wiring-crewai-crews.md +0 -51
  30. package/skills/runtime/references/wiring-crewai-flows.md +0 -45
  31. package/skills/runtime/references/wiring-external-agents.md +0 -348
  32. package/skills/runtime/references/wiring-langgraph.md +0 -49
  33. package/skills/runtime/references/wiring-llamaindex.md +0 -39
  34. package/skills/runtime/references/wiring-mastra.md +0 -70
  35. package/skills/runtime/references/wiring-mcp-apps-middleware.md +0 -73
  36. package/skills/runtime/references/wiring-ms-agent-framework.md +0 -41
  37. package/skills/runtime/references/wiring-pydantic-ai.md +0 -45
@@ -1,336 +0,0 @@
1
- # CopilotKit Agent Runners
2
-
3
- `AgentRunner` is the abstraction that owns thread run state — active runs, the event stream
4
- replay, and stop semantics. Pick one per `CopilotRuntime` instance.
5
-
6
- - `InMemoryAgentRunner` — default; process-global in-memory Map; lost on restart.
7
- - `SqliteAgentRunner` — file-backed; requires `better-sqlite3` peer.
8
- - `IntelligenceAgentRunner` — auto-wired by `CopilotIntelligenceRuntime`. You do NOT
9
- construct this directly and you cannot pass `runner` alongside `intelligence`.
10
- - Custom — subclass `AgentRunner` for Redis / Postgres / any backend.
11
-
12
- ## Setup
13
-
14
- Default (in-memory, dev only):
15
-
16
- ```typescript
17
- import { CopilotRuntime } from "@copilotkit/runtime/v2";
18
-
19
- // Equivalent to passing `runner: new InMemoryAgentRunner()`
20
- const runtime = new CopilotRuntime({
21
- agents: {
22
- /* ... */
23
- } as any,
24
- });
25
- ```
26
-
27
- Production (file-backed SQLite):
28
-
29
- ```typescript
30
- import { CopilotRuntime } from "@copilotkit/runtime/v2";
31
- import { SqliteAgentRunner } from "@copilotkit/sqlite-runner";
32
-
33
- const runtime = new CopilotRuntime({
34
- agents: {
35
- /* ... */
36
- } as any,
37
- runner: new SqliteAgentRunner({ dbPath: "./data/threads.db" }),
38
- });
39
- ```
40
-
41
- Installation for the SQLite runner (the `better-sqlite3` peer is required):
42
-
43
- ```bash
44
- pnpm add @copilotkit/sqlite-runner better-sqlite3
45
- ```
46
-
47
- ## Core Patterns
48
-
49
- ### The AgentRunner contract
50
-
51
- ```typescript
52
- import { AgentRunner } from "@copilotkit/runtime/v2";
53
- import type {
54
- AgentRunnerRunRequest,
55
- AgentRunnerConnectRequest,
56
- AgentRunnerIsRunningRequest,
57
- AgentRunnerStopRequest,
58
- } from "@copilotkit/runtime/v2";
59
- import { Observable } from "rxjs";
60
- import type { BaseEvent } from "@ag-ui/client";
61
-
62
- class MyRunner extends AgentRunner {
63
- run(request: AgentRunnerRunRequest): Observable<BaseEvent> {
64
- // Start a new run for request.threadId. Throw `new Error("Thread already running")`
65
- // if a run is in flight. Stream events from agent.run(request.input).
66
- return new Observable<BaseEvent>();
67
- }
68
- connect(request: AgentRunnerConnectRequest): Observable<BaseEvent> {
69
- // Replay events for an active run, or historic runs for request.threadId.
70
- return new Observable<BaseEvent>();
71
- }
72
- async isRunning(request: AgentRunnerIsRunningRequest): Promise<boolean> {
73
- return false;
74
- }
75
- async stop(request: AgentRunnerStopRequest): Promise<boolean | undefined> {
76
- return true;
77
- }
78
- }
79
- ```
80
-
81
- ### Handle double-submit on the client
82
-
83
- By default, both `InMemoryAgentRunner` and `SqliteAgentRunner` throw
84
- `"Thread already running"` on concurrent `run()` calls for the same `threadId`.
85
- `"throw"` is the default, but it is not the only option: constructing
86
- `InMemoryAgentRunner` with `onConcurrentRun: "supersede"` makes it abort the
87
- in-flight run (the same path `stop()` takes) and start the new one instead of
88
- throwing — the superseded run's partial output is discarded rather than persisted
89
- to history. `SqliteAgentRunner` has no such option and always throws. When the
90
- throw does happen, how it surfaces to the client depends on the runtime mode:
91
-
92
- - **Intelligence mode** — CopilotKit Intelligence returns HTTP `409` when a lock is
93
- held. The client core maps this to `CopilotKitCoreErrorCode.AGENT_THREAD_LOCKED`
94
- and fires `onError({ code: "agent_thread_locked", ... })`. Handle this in
95
- `<CopilotKit onError>` (the `CopilotKit` provider from `@copilotkit/react-core/v2`).
96
- - **SSE mode** (default, in-memory / SQLite runners) — the runner throws
97
- synchronously and the handler returns a plain `500` JSON body like
98
- `{ "error": "Failed to run agent", "message": "Thread already running" }`.
99
- There is no typed `agent_thread_locked` code — match on the message text or
100
- just guard on the client with a busy flag.
101
-
102
- ```tsx
103
- // client — Intelligence mode (typed code)
104
- import { CopilotKit } from "@copilotkit/react-core/v2";
105
-
106
- <CopilotKit
107
- onError={({ code }) => {
108
- if (code === "agent_thread_locked") {
109
- alert("Agent is busy — wait for the current response to finish.");
110
- }
111
- }}
112
- />;
113
- ```
114
-
115
- ```tsx
116
- // client — any mode: guard with a busy flag so double-submit is impossible
117
- import { useAgent } from "@copilotkit/react-core/v2";
118
- import { useState } from "react";
119
-
120
- function Composer() {
121
- const agent = useAgent({ agentId: "default" });
122
- const [busy, setBusy] = useState(false);
123
-
124
- async function send(text: string) {
125
- if (busy) return;
126
- setBusy(true);
127
- try {
128
- await agent?.addMessage({ role: "user", content: text });
129
- } finally {
130
- setBusy(false);
131
- }
132
- }
133
-
134
- return null;
135
- }
136
- ```
137
-
138
- ## Common Mistakes
139
-
140
- ### HIGH Shipping InMemoryAgentRunner to production
141
-
142
- Wrong:
143
-
144
- ```typescript
145
- // production:
146
- new CopilotRuntime({ agents: { default: agent } });
147
- ```
148
-
149
- Correct:
150
-
151
- ```typescript
152
- import { SqliteAgentRunner } from "@copilotkit/sqlite-runner";
153
-
154
- new CopilotRuntime({
155
- agents: { default: agent },
156
- runner: new SqliteAgentRunner({ dbPath: "./data/threads.db" }),
157
- });
158
- // Or upgrade to Intelligence mode for managed durability.
159
- ```
160
-
161
- The default runner is `new InMemoryAgentRunner()`. It keeps state in a process-global,
162
- bounded store — threads are lost on restart, evicted past the memory limits, and
163
- horizontally-scaled instances see divergent state. See `agent-runners-in-memory.md`
164
- for the bounds and how to tune them.
165
-
166
- Source: `packages/runtime/src/v2/runtime/runner/in-memory.ts`.
167
-
168
- ### HIGH Setting runner alongside intelligence option
169
-
170
- Wrong:
171
-
172
- ```typescript
173
- new CopilotRuntime({
174
- agents,
175
- intelligence,
176
- runner: new SqliteAgentRunner({ dbPath: "./data/threads.db" }),
177
- });
178
- ```
179
-
180
- Correct:
181
-
182
- ```typescript
183
- new CopilotRuntime({
184
- agents,
185
- intelligence,
186
- identifyUser: (req) => ({
187
- id: req.headers.get("x-user-id")!,
188
- name: req.headers.get("x-user-name") ?? "Anonymous",
189
- }),
190
- });
191
- ```
192
-
193
- `CopilotIntelligenceRuntimeOptions` does not declare a `runner` field — Intelligence mode
194
- auto-wires `IntelligenceAgentRunner` pointed at the Intelligence service socket. Excess-property checks will
195
- flag a `runner:` key on an Intelligence-shaped options object as a type error, and a caller who
196
- evades that check (JS, `as any`, or a non-literal options object) gets a `throw` at construction
197
- rather than a silently ignored runner.
198
-
199
- Source: `packages/runtime/src/v2/runtime/core/runtime.ts` — `runner?` is declared only on
200
- `CopilotSseRuntimeOptions` (:239); the Intelligence constructor guard is at :512 and the
201
- auto-wired runner at :582.
202
-
203
- ### HIGH Forgetting the better-sqlite3 peer
204
-
205
- Wrong:
206
-
207
- ```bash
208
- pnpm add @copilotkit/sqlite-runner
209
- ```
210
-
211
- Correct:
212
-
213
- ```bash
214
- pnpm add @copilotkit/sqlite-runner better-sqlite3
215
- ```
216
-
217
- `@copilotkit/sqlite-runner` imports `better-sqlite3` at the top of its module, so if the peer
218
- is missing, `import { SqliteAgentRunner } from "@copilotkit/sqlite-runner"` itself fails at
219
- module load with `Cannot find module 'better-sqlite3'` — long before the constructor runs.
220
- (The constructor has a friendlier multi-line install hint as a belt-and-suspenders fallback,
221
- but in practice you will see the bare module-resolution error first.) It is a peer dependency,
222
- not a direct dep.
223
-
224
- Source: `packages/sqlite-runner/src/sqlite-runner.ts:18`, `:55-66`.
225
-
226
- ### HIGH Default SqliteAgentRunner with :memory: dbPath
227
-
228
- Wrong:
229
-
230
- ```typescript
231
- new SqliteAgentRunner();
232
- ```
233
-
234
- Correct:
235
-
236
- ```typescript
237
- new SqliteAgentRunner({ dbPath: "./data/threads.db" });
238
- ```
239
-
240
- The default `dbPath` is `":memory:"` — SQLite's in-memory mode. Data is lost at restart,
241
- defeating the reason to use the file-backed runner.
242
-
243
- Source: `packages/sqlite-runner/src/sqlite-runner.ts:48-54`.
244
-
245
- ### MEDIUM Concurrent run() on the same threadId
246
-
247
- Wrong:
248
-
249
- ```tsx
250
- // Double-click send button → two POST /agent/:id/run to the same thread
251
- <button onClick={() => agent.addMessage({ role: "user", content })}>
252
- Send
253
- </button>
254
- ```
255
-
256
- Correct:
257
-
258
- ```tsx
259
- const [busy, setBusy] = useState(false);
260
- <button
261
- disabled={busy}
262
- onClick={async () => {
263
- setBusy(true);
264
- try {
265
- await agent.addMessage({ role: "user", content });
266
- } finally {
267
- setBusy(false);
268
- }
269
- }}
270
- >
271
- Send
272
- </button>;
273
- ```
274
-
275
- By default both runners throw `"Thread already running"` on concurrent runs, so
276
- debouncing on the client is still the right baseline. In Intelligence mode you can
277
- additionally handle `code === "agent_thread_locked"` in `<CopilotKit onError>`; SSE
278
- mode surfaces only a generic 500 with that message.
279
-
280
- Throwing is the default (`onConcurrentRun: "throw"`), not the only behavior:
281
- constructing `InMemoryAgentRunner` with `onConcurrentRun: "supersede"` aborts the
282
- in-flight run (the `stop()` path) and starts the new one instead of throwing,
283
- discarding the superseded run's partial output rather than persisting it. That
284
- suits a UX where a fast follow-up should displace a still-running (or wedged) turn.
285
- Unlike the process-global memory limits, `onConcurrentRun` is per-runner-instance —
286
- it affects only the runner you pass it to. `SqliteAgentRunner` has no such option
287
- and always throws.
288
-
289
- Source: the `throw new Error("Thread already running")` in `InMemoryAgentRunner.run()`,
290
- `packages/runtime/src/v2/runtime/runner/in-memory.ts`;
291
- `packages/core/src/intelligence-agent.ts:368-369`.
292
-
293
- ### HIGH In-memory runner + horizontal scaling
294
-
295
- Wrong:
296
-
297
- ```typescript
298
- // 3 Fly.io / Cloud Run instances, each with its own InMemoryAgentRunner
299
- new CopilotRuntime({ agents });
300
- ```
301
-
302
- Correct:
303
-
304
- ```typescript
305
- // Sticky-session one instance per thread (so every run for a thread lands on the
306
- // same process), OR move to Intelligence mode for managed multi-instance durability.
307
- new CopilotRuntime({ agents }); // + route by threadId at the load balancer
308
- ```
309
-
310
- `InMemoryAgentRunner`'s store is a process-global singleton — multi-instance deploys see
311
- totally different thread state per worker, making reconnects and `GET /connect` non-deterministic.
312
-
313
- Source: the exported `ɵGLOBAL_STORE` singleton in `packages/runtime/src/v2/runtime/runner/in-memory.ts`.
314
-
315
- A shared `dbPath` on `SqliteAgentRunner` is **not** a horizontal-scaling fix on its own.
316
- Sharing the file gives you durable, persisted history: runs survive process restarts, and
317
- completed runs are readable from any instance pointed at the same file. But the live-run
318
- bookkeeping used by the connect-bridge and by `stop()` lives in a process-local
319
- `ACTIVE_CONNECTIONS` map. A second instance has **no** entry for a run started elsewhere, so
320
- it can replay stored history but **cannot** reconnect to — or stop — an in-flight run on
321
- another instance. Use `SqliteAgentRunner` for restart-resilient single-instance durability;
322
- for managed multi-instance durability, use Intelligence mode.
323
-
324
- Source: `packages/sqlite-runner/src/sqlite-runner.ts:46` (module-level `ACTIVE_CONNECTIONS`).
325
-
326
- ## References
327
-
328
- - [InMemoryAgentRunner — store, bounds, concurrency, and lifecycle](agent-runners-in-memory.md)
329
- - [SqliteAgentRunner — schema, retention, ops](agent-runners-sqlite.md)
330
- - [Custom runner — Redis/Postgres skeleton](agent-runners-custom.md)
331
-
332
- ## See also
333
-
334
- - `copilotkit/intelligence-mode` — managed durability alternative (CopilotKit Intelligence managed service, not self-hostable)
335
- - `copilotkit/setup-endpoint` — runner is passed via the CopilotRuntime constructor
336
- - `copilotkit/scale-to-multi-agent` — horizontal scaling considerations
@@ -1,232 +0,0 @@
1
- BuiltInAgent Factory Modes — cookbook for TanStack AI, AI SDK, and custom AG-UI factories.
2
-
3
- ## The AgentFactoryContext
4
-
5
- ```typescript
6
- // packages/runtime/src/agent/index.ts
7
- export interface AgentFactoryContext {
8
- input: RunAgentInput; // messages, tools, forwardedProps, context
9
- abortController: AbortController; // prefer abortSignal
10
- abortSignal: AbortSignal; // pass to AI SDK / fetch / custom
11
- }
12
- ```
13
-
14
- Rule of thumb:
15
-
16
- - Prefer `abortSignal` for AI SDK, fetch, custom backends.
17
- - Use `abortController` for TanStack AI (its `chat()` takes the controller, not the signal).
18
- - NEVER call `ctx.abortController.abort()` inside the factory — use
19
- `agent.abortRun()` from outside.
20
-
21
- ## TanStack AI factory (preferred)
22
-
23
- ```typescript
24
- import { BuiltInAgent, convertInputToTanStackAI } from "@copilotkit/runtime/v2";
25
- import { chat } from "@tanstack/ai";
26
- import { openaiText } from "@tanstack/ai-openai";
27
-
28
- new BuiltInAgent({
29
- type: "tanstack",
30
- factory: ({ input, abortController }) => {
31
- const { messages, systemPrompts } = convertInputToTanStackAI(input);
32
- systemPrompts.unshift("You are a helpful assistant.");
33
- return chat({
34
- adapter: openaiText("gpt-4o"),
35
- messages,
36
- systemPrompts,
37
- tools: [
38
- /* TanStack AI toolDefinition()s */
39
- ],
40
- abortController,
41
- });
42
- },
43
- });
44
- ```
45
-
46
- ### TanStack AI + forwardedProps
47
-
48
- ```typescript
49
- new BuiltInAgent({
50
- type: "tanstack",
51
- factory: ({ input, abortController }) => {
52
- const { messages, systemPrompts } = convertInputToTanStackAI(input);
53
- const fwd = input.forwardedProps as
54
- | { model?: string; temperature?: number }
55
- | undefined;
56
- return chat({
57
- adapter: openaiText(fwd?.model ?? "gpt-4o"),
58
- messages,
59
- systemPrompts,
60
- modelOptions: { temperature: fwd?.temperature ?? 0.2 },
61
- abortController,
62
- });
63
- },
64
- });
65
- ```
66
-
67
- ## AI SDK factory (use when reasoning events are required)
68
-
69
- ```typescript
70
- import {
71
- BuiltInAgent,
72
- convertMessagesToVercelAISDKMessages,
73
- convertToolsToVercelAITools,
74
- } from "@copilotkit/runtime/v2";
75
- import { streamText, stepCountIs } from "ai";
76
- import { openai } from "@ai-sdk/openai";
77
-
78
- new BuiltInAgent({
79
- type: "aisdk",
80
- factory: ({ input, abortSignal }) => {
81
- const messages = convertMessagesToVercelAISDKMessages(input.messages, {
82
- forwardSystemMessages: true,
83
- });
84
- const tools = convertToolsToVercelAITools(input.tools);
85
- return streamText({
86
- model: openai("gpt-4o"),
87
- messages,
88
- tools,
89
- abortSignal,
90
- stopWhen: stepCountIs(5),
91
- });
92
- },
93
- });
94
- ```
95
-
96
- The `BuiltInAgentAISDKFactoryConfig` contract requires an object with a `fullStream`
97
- async iterable — this is exactly what `streamText()` returns.
98
-
99
- ## AI SDK + reasoning (Anthropic thinking)
100
-
101
- ```typescript
102
- import { anthropic } from "@ai-sdk/anthropic";
103
- import { streamText } from "ai";
104
- import {
105
- BuiltInAgent,
106
- convertMessagesToVercelAISDKMessages,
107
- } from "@copilotkit/runtime/v2";
108
-
109
- new BuiltInAgent({
110
- type: "aisdk",
111
- factory: ({ input, abortSignal }) =>
112
- streamText({
113
- model: anthropic("claude-sonnet-4-6"),
114
- messages: convertMessagesToVercelAISDKMessages(input.messages),
115
- providerOptions: {
116
- anthropic: { thinking: { type: "enabled", budgetTokens: 10000 } },
117
- },
118
- abortSignal,
119
- }),
120
- });
121
- ```
122
-
123
- TanStack AI silently drops reasoning events — only AI SDK surfaces them.
124
-
125
- ## Custom factory (raw AG-UI events)
126
-
127
- ```typescript
128
- import { BuiltInAgent } from "@copilotkit/runtime/v2";
129
- import type { BaseEvent } from "@ag-ui/client";
130
- import { EventType } from "@ag-ui/client";
131
-
132
- new BuiltInAgent({
133
- type: "custom",
134
- factory: async function* ({ input, abortSignal }): AsyncIterable<BaseEvent> {
135
- // Check abortSignal.aborted on every iteration — agent.abortRun() signals
136
- // cancellation via this flag, but the generator must consult it to stop yielding.
137
- if (abortSignal.aborted) return;
138
-
139
- const messageId = crypto.randomUUID();
140
- yield {
141
- type: EventType.TEXT_MESSAGE_START,
142
- messageId,
143
- role: "assistant",
144
- } as any;
145
-
146
- for (const delta of ["Hello", ", ", "world."]) {
147
- if (abortSignal.aborted) return; // honor cancellation between yields
148
- yield {
149
- type: EventType.TEXT_MESSAGE_CONTENT,
150
- messageId,
151
- delta,
152
- } as any;
153
- }
154
-
155
- yield { type: EventType.TEXT_MESSAGE_END, messageId } as any;
156
- },
157
- });
158
- ```
159
-
160
- A custom factory that never checks `abortSignal.aborted` (or registers an
161
- `addEventListener("abort", …)` handler to break its loop) is non-cancellable —
162
- `agent.abortRun()` will flip the flag but the generator will keep yielding until it
163
- exhausts its own source. Pass `abortSignal` through to any underlying `fetch` /
164
- streaming API as well so the upstream request is torn down.
165
-
166
- ## Manual state-tool wiring (Factory Mode only)
167
-
168
- Simple Mode auto-injects `AGUISendStateSnapshot` / `AGUISendStateDelta`. In Factory Mode
169
- you must register them by hand for shared-state updates to reach the LLM. The AI SDK
170
- factory works out of the box because `defineTool` output adapts through
171
- `convertToolDefinitionsToVercelAITools`:
172
-
173
- ```typescript
174
- import {
175
- BuiltInAgent,
176
- convertMessagesToVercelAISDKMessages,
177
- convertToolDefinitionsToVercelAITools,
178
- defineTool,
179
- } from "@copilotkit/runtime/v2";
180
- import { streamText } from "ai";
181
- import { openai } from "@ai-sdk/openai";
182
- import { z } from "zod";
183
-
184
- const sendStateSnapshot = defineTool({
185
- name: "AGUISendStateSnapshot",
186
- description: "Replace the entire application state with a new snapshot",
187
- parameters: z.object({
188
- snapshot: z.any().describe("The complete new state object"),
189
- }),
190
- execute: async ({ snapshot }) => ({ success: true, snapshot }),
191
- });
192
- const sendStateDelta = defineTool({
193
- name: "AGUISendStateDelta",
194
- description:
195
- "Apply incremental updates to application state using JSON Patch operations",
196
- // MUST mirror the Simple-Mode auto-injected schema (src/agent/index.ts:1140-1176)
197
- // or the frontend's state handler won't recognize the payload.
198
- parameters: z.object({
199
- delta: z
200
- .array(
201
- z.object({
202
- op: z.enum(["add", "replace", "remove"]),
203
- path: z.string(),
204
- value: z.any().optional(),
205
- }),
206
- )
207
- .describe("Array of JSON Patch operations"),
208
- }),
209
- execute: async ({ delta }) => ({ success: true, delta }),
210
- });
211
-
212
- new BuiltInAgent({
213
- type: "aisdk",
214
- factory: ({ input, abortSignal }) =>
215
- streamText({
216
- model: openai("gpt-4o"),
217
- messages: convertMessagesToVercelAISDKMessages(input.messages),
218
- tools: convertToolDefinitionsToVercelAITools([
219
- sendStateSnapshot,
220
- sendStateDelta,
221
- ]),
222
- abortSignal,
223
- }),
224
- });
225
- ```
226
-
227
- For TanStack AI factories, `defineTool` output is NOT a TanStack tool — passing it to
228
- `chat({ tools })` does not work. Either switch to the AI SDK factory above, or redefine
229
- the tools with `toolDefinition()` from `@tanstack/ai`.
230
-
231
- Source: `packages/runtime/src/agent/index.ts`,
232
- `docs/content/docs/integrations/built-in-agent/custom-agent.mdx`.
@@ -1,123 +0,0 @@
1
- BuiltInAgent helper utilities — exported from `@copilotkit/runtime/v2`.
2
-
3
- ## convertInputToTanStackAI
4
-
5
- ```typescript
6
- import { convertInputToTanStackAI } from "@copilotkit/runtime/v2";
7
-
8
- // signature (simplified):
9
- // convertInputToTanStackAI(input: RunAgentInput): {
10
- // messages: TanStackAIMessage[];
11
- // systemPrompts: string[];
12
- // }
13
- ```
14
-
15
- Converts the AG-UI `RunAgentInput` into TanStack AI's `chat()` inputs. System messages in
16
- the input are collected into the `systemPrompts` array (not the `messages` array). Unshift
17
- your own system prompt onto `systemPrompts` before calling `chat()`:
18
-
19
- ```typescript
20
- const { messages, systemPrompts } = convertInputToTanStackAI(input);
21
- systemPrompts.unshift("You are a helpful assistant.");
22
- return chat({ adapter, messages, systemPrompts, abortController });
23
- ```
24
-
25
- Source: `packages/runtime/src/agent/converters/tanstack.ts:156`.
26
-
27
- ## convertMessagesToVercelAISDKMessages
28
-
29
- ```typescript
30
- import { convertMessagesToVercelAISDKMessages } from "@copilotkit/runtime/v2";
31
-
32
- // signature:
33
- // convertMessagesToVercelAISDKMessages(
34
- // messages: Message[],
35
- // options?: { forwardSystemMessages?: boolean; forwardDeveloperMessages?: boolean }
36
- // ): ModelMessage[]
37
- ```
38
-
39
- Converts AG-UI `Message[]` to the Vercel AI SDK's `ModelMessage[]`. Handles multimodal
40
- content (text, image, audio/video/document, and legacy `binary`). By default drops
41
- `role: "system"` and `role: "developer"` messages — set the options to opt in.
42
-
43
- ```typescript
44
- const messages = convertMessagesToVercelAISDKMessages(input.messages, {
45
- forwardSystemMessages: true,
46
- });
47
- ```
48
-
49
- Source: `packages/runtime/src/agent/index.ts:435`.
50
-
51
- ## convertToolsToVercelAITools
52
-
53
- ```typescript
54
- import { convertToolsToVercelAITools } from "@copilotkit/runtime/v2";
55
-
56
- // signature:
57
- // convertToolsToVercelAITools(tools: RunAgentInput["tools"]): ToolSet
58
- ```
59
-
60
- Converts AG-UI `input.tools` (tools registered on the frontend — their parameters are plain
61
- JSON Schema) into the AI SDK's `ToolSet`. Throws `Invalid JSON schema for tool ${name}`
62
- when a tool's parameters aren't a JSON schema object. The resulting tools have no
63
- `execute` — the AI SDK emits tool-call events and the frontend handles them.
64
-
65
- ```typescript
66
- const tools = convertToolsToVercelAITools(input.tools);
67
- return streamText({ model, messages, tools, abortSignal });
68
- ```
69
-
70
- Source: `packages/runtime/src/agent/index.ts:599`.
71
-
72
- ## convertToolDefinitionsToVercelAITools
73
-
74
- ```typescript
75
- import { convertToolDefinitionsToVercelAITools } from "@copilotkit/runtime/v2";
76
-
77
- // signature:
78
- // convertToolDefinitionsToVercelAITools(tools: ToolDefinition[]): ToolSet
79
- ```
80
-
81
- Converts server-side `ToolDefinition[]` (Standard Schema V1 parameters + `execute`
82
- function) into an AI SDK `ToolSet`. Zod schemas pass through directly; non-Zod Standard
83
- Schema V1 parameters (Valibot, ArkType, ...) are converted to JSON Schema via
84
- `schemaToJsonSchema` and wrapped with `jsonSchema()` from `ai`.
85
-
86
- ```typescript
87
- import { defineTool } from "@copilotkit/runtime/v2";
88
- import { z } from "zod";
89
-
90
- const searchTool = defineTool({
91
- name: "search",
92
- description: "Search the web.",
93
- parameters: z.object({ query: z.string() }),
94
- execute: async ({ query }) => ({ results: [] }),
95
- });
96
-
97
- const tools = convertToolDefinitionsToVercelAITools([searchTool]);
98
- return streamText({ model, messages, tools, abortSignal });
99
- ```
100
-
101
- Source: `packages/runtime/src/agent/index.ts:633`.
102
-
103
- ## resolveModel
104
-
105
- ```typescript
106
- import { resolveModel } from "@copilotkit/runtime/v2";
107
-
108
- // signature:
109
- // resolveModel(spec: ModelSpecifier, apiKey?: string): LanguageModel
110
- ```
111
-
112
- Resolves a `"provider/model"` (or `"provider:model"`) string to a `LanguageModel`. If
113
- `spec` is already a `LanguageModel`, it's returned as-is. Throws
114
- `Invalid model string "..."` when the provider separator is missing.
115
-
116
- Supported providers: `openai`, `anthropic`, `google`/`gemini`/`google-gemini`, `vertex`.
117
- Unknown providers throw `Unknown provider "..." in "...". Supported: openai, anthropic, google (gemini).`
118
-
119
- ```typescript
120
- const model = resolveModel("openai/gpt-4o", process.env.OPENAI_API_KEY);
121
- ```
122
-
123
- Source: `packages/runtime/src/agent/index.ts:176-249`.