@assistant-ui/mcp-docs-server 0.1.32 → 0.1.34
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.
- package/.docs/organized/code-examples/waterfall.md +20 -22
- package/.docs/organized/code-examples/with-a2a.md +24 -24
- package/.docs/organized/code-examples/with-ag-ui.md +30 -25
- package/.docs/organized/code-examples/with-ai-sdk-v6.md +11 -9
- package/.docs/organized/code-examples/with-artifacts.md +49 -37
- package/.docs/organized/code-examples/with-assistant-transport.md +63 -51
- package/.docs/organized/code-examples/with-browser-extension.md +22 -10
- package/.docs/organized/code-examples/with-chain-of-thought.md +406 -87
- package/.docs/organized/code-examples/with-cloud-standalone.md +25 -24
- package/.docs/organized/code-examples/with-cloud.md +11 -9
- package/.docs/organized/code-examples/with-custom-thread-list.md +14 -12
- package/.docs/organized/code-examples/with-elevenlabs-conversational.md +23 -21
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +14 -13
- package/.docs/organized/code-examples/with-expo.md +44 -29
- package/.docs/organized/code-examples/with-external-store.md +9 -7
- package/.docs/organized/code-examples/with-ffmpeg.md +322 -285
- package/.docs/organized/code-examples/with-generative-ui.md +1066 -256
- package/.docs/organized/code-examples/with-google-adk.md +10 -8
- package/.docs/organized/code-examples/with-heat-graph.md +13 -11
- package/.docs/organized/code-examples/with-image-generation.md +19 -17
- package/.docs/organized/code-examples/with-interactables.md +317 -239
- package/.docs/organized/code-examples/with-langchain.md +14 -12
- package/.docs/organized/code-examples/with-langgraph.md +91 -83
- package/.docs/organized/code-examples/with-livekit.md +24 -22
- package/.docs/organized/code-examples/with-mcp.md +18 -12
- package/.docs/organized/code-examples/with-opencode.md +66 -66
- package/.docs/organized/code-examples/with-react-hook-form.md +19 -17
- package/.docs/organized/code-examples/with-react-ink.md +297 -102
- package/.docs/organized/code-examples/with-react-router.md +17 -15
- package/.docs/organized/code-examples/with-resumable-stream.md +15 -14
- package/.docs/organized/code-examples/with-store.md +78 -76
- package/.docs/organized/code-examples/with-tanstack.md +13 -14
- package/.docs/organized/code-examples/with-tap-runtime.md +26 -24
- package/.docs/raw/docs/(docs)/architecture.mdx +94 -42
- package/.docs/raw/docs/(docs)/cli.mdx +1 -2
- package/.docs/raw/docs/(docs)/installation.mdx +1 -1
- package/.docs/raw/docs/(reference)/api-reference/adapters/persistence.mdx +5 -1
- package/.docs/raw/docs/(reference)/api-reference/external-store/message-conversion.mdx +15 -15
- package/.docs/raw/docs/(reference)/api-reference/external-store/runtime.mdx +14 -1
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/index.mdx +18 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/rendering.mdx +33 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/spec.mdx +45 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/composer-triggers.mdx +41 -41
- package/.docs/raw/docs/(reference)/api-reference/hooks/model-context.mdx +19 -1
- package/.docs/raw/docs/(reference)/api-reference/hooks/primitives.mdx +122 -122
- package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +43 -2
- package/.docs/raw/docs/(reference)/api-reference/model-context/context.mdx +6 -0
- package/.docs/raw/docs/(reference)/api-reference/overview.mdx +4 -6
- package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +30 -0
- package/.docs/raw/docs/(reference)/api-reference/tools/component-tools.mdx +20 -3
- package/.docs/raw/docs/(reference)/api-reference/tools/index.mdx +8 -8
- package/.docs/raw/docs/(reference)/api-reference/tools/rendering.mdx +52 -4
- package/.docs/raw/docs/(reference)/api-reference/tools/toolkits.mdx +100 -10
- package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +7 -59
- package/.docs/raw/docs/cloud/ai-sdk.mdx +0 -2
- package/.docs/raw/docs/{(docs)/copilots → copilots}/model-context.mdx +34 -26
- package/.docs/raw/docs/{(docs)/copilots → copilots}/motivation.mdx +32 -26
- package/.docs/raw/docs/guides/chain-of-thought.mdx +7 -9
- package/.docs/raw/docs/guides/context-api.mdx +2 -1
- package/.docs/raw/docs/guides/index.mdx +3 -12
- package/.docs/raw/docs/guides/mentions.mdx +4 -4
- package/.docs/raw/docs/guides/slash-commands.mdx +1 -1
- package/.docs/raw/docs/guides/suggestions.mdx +1 -1
- package/.docs/raw/docs/ink/adapters.mdx +23 -1
- package/.docs/raw/docs/ink/hooks.mdx +101 -85
- package/.docs/raw/docs/ink/migration.mdx +1 -1
- package/.docs/raw/docs/ink/primitives.mdx +2 -2
- package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +1 -1
- package/.docs/raw/docs/integrations/index.mdx +2 -2
- package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +17 -2
- package/.docs/raw/docs/migrations/toolkit-tools.mdx +232 -0
- package/.docs/raw/docs/primitives/chain-of-thought.mdx +10 -16
- package/.docs/raw/docs/primitives/message.mdx +9 -10
- package/.docs/raw/docs/react-native/hooks.mdx +62 -79
- package/.docs/raw/docs/react-native/migration.mdx +1 -1
- package/.docs/raw/docs/react-native/primitives.mdx +2 -2
- package/.docs/raw/docs/runtimes/a2a/client-and-hooks.mdx +3 -0
- package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +41 -0
- package/.docs/raw/docs/runtimes/ai-sdk/v6.mdx +122 -1
- package/.docs/raw/docs/runtimes/concepts/architecture.mdx +46 -4
- package/.docs/raw/docs/runtimes/concepts/threads.mdx +7 -1
- package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +54 -12
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +62 -4
- package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +30 -7
- package/.docs/raw/docs/runtimes/google-adk/hooks.mdx +108 -38
- package/.docs/raw/docs/runtimes/langgraph/generative-ui.mdx +2 -2
- package/.docs/raw/docs/runtimes/langgraph/streaming.mdx +14 -1
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +64 -50
- package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +98 -86
- package/.docs/raw/docs/tools/backend.mdx +144 -0
- package/.docs/raw/docs/tools/defining-tools.mdx +538 -0
- package/.docs/raw/docs/tools/dynamic-tools.mdx +110 -0
- package/.docs/raw/docs/tools/generative-ui.mdx +214 -0
- package/.docs/raw/docs/tools/index.mdx +71 -0
- package/.docs/raw/docs/{guides → tools}/interactables.mdx +1 -1
- package/.docs/raw/docs/{integrations/tools → tools}/mcp.mdx +145 -50
- package/.docs/raw/docs/{guides → tools}/multi-agent.mdx +15 -17
- package/.docs/raw/docs/tools/tool-ui.mdx +967 -0
- package/.docs/raw/docs/{integrations/tools/react-mcp.mdx → tools/user-managed-mcp.mdx} +7 -7
- package/.docs/raw/docs/ui/directive-text.mdx +3 -3
- package/.docs/raw/docs/ui/mcp-config.mdx +4 -4
- package/.docs/raw/docs/ui/mermaid.mdx +16 -9
- package/.docs/raw/docs/ui/part-grouping.mdx +84 -50
- package/.docs/raw/docs/ui/reasoning.mdx +4 -5
- package/.docs/raw/docs/ui/tool-fallback.mdx +16 -0
- package/.docs/raw/docs/ui/tool-group.mdx +5 -6
- package/.docs/raw/docs/utilities/heat-graph.mdx +1 -1
- package/.docs/raw/docs/utilities/react-o11y.mdx +2 -2
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/prepare-docs/code-examples.d.ts.map +1 -1
- package/dist/prepare-docs/code-examples.js.map +1 -1
- package/dist/prepare-docs/copy-raw.d.ts.map +1 -1
- package/dist/prepare-docs/copy-raw.js.map +1 -1
- package/dist/prepare-docs/prepare.js.map +1 -1
- package/dist/stdio.js.map +1 -1
- package/dist/tools/docs.js.map +1 -1
- package/dist/tools/examples.js.map +1 -1
- package/dist/tools/tests/test-setup.js.map +1 -1
- package/dist/utils/mdx.js.map +1 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js.map +1 -1
- package/package.json +5 -5
- package/.docs/organized/code-examples/with-parent-id-grouping.md +0 -596
- package/.docs/raw/docs/(docs)/copilots/make-assistant-tool-ui.mdx +0 -151
- package/.docs/raw/docs/(docs)/copilots/make-assistant-tool.mdx +0 -230
- package/.docs/raw/docs/guides/generative-ui.mdx +0 -142
- package/.docs/raw/docs/guides/tool-ui.mdx +0 -858
- package/.docs/raw/docs/guides/tools.mdx +0 -736
- /package/.docs/raw/docs/{(docs)/copilots → copilots}/assistant-frame.mdx +0 -0
- /package/.docs/raw/docs/{(docs)/copilots → copilots}/make-assistant-visible.mdx +0 -0
- /package/.docs/raw/docs/{(docs)/copilots → copilots}/use-assistant-instructions.mdx +0 -0
- /package/.docs/raw/docs/{guides → tools}/mcp-apps.mdx +0 -0
|
@@ -81,46 +81,44 @@ type PurchaseStockResult = {
|
|
|
81
81
|
};
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
Then we
|
|
84
|
+
Then we define a tool UI renderer:
|
|
85
85
|
|
|
86
86
|
```tsx title="@/components/tools/purchase-stock/PurchaseStockTool.tsx"
|
|
87
87
|
"use client";
|
|
88
88
|
|
|
89
89
|
import { TransactionConfirmationPending } from "./transaction-confirmation-pending";
|
|
90
90
|
import { TransactionConfirmationFinal } from "./transaction-confirmation-final";
|
|
91
|
-
import {
|
|
92
|
-
|
|
93
|
-
export const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
},
|
|
123
|
-
);
|
|
91
|
+
import type { ToolCallMessagePartComponent } from "@assistant-ui/react";
|
|
92
|
+
|
|
93
|
+
export const PurchaseStockToolUI: ToolCallMessagePartComponent<
|
|
94
|
+
PurchaseStockArgs,
|
|
95
|
+
string
|
|
96
|
+
> = function PurchaseStockUI({ args, result, status, addResult }) {
|
|
97
|
+
const handleReject = async () => {
|
|
98
|
+
addResult(JSON.stringify({ approve: false }));
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const handleConfirm = async () => {
|
|
102
|
+
addResult(JSON.stringify({ approve: true }));
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<div className="mb-4 flex flex-col items-center gap-2">
|
|
107
|
+
<div>
|
|
108
|
+
<pre className="whitespace-pre-wrap break-all text-center">
|
|
109
|
+
purchase_stock({JSON.stringify(args)})
|
|
110
|
+
</pre>
|
|
111
|
+
</div>
|
|
112
|
+
{!result && status.type !== "running" && (
|
|
113
|
+
<TransactionConfirmationPending
|
|
114
|
+
{...args}
|
|
115
|
+
onConfirm={handleConfirm}
|
|
116
|
+
onReject={handleReject}
|
|
117
|
+
/>
|
|
118
|
+
)}
|
|
119
|
+
</div>
|
|
120
|
+
);
|
|
121
|
+
};
|
|
124
122
|
```
|
|
125
123
|
|
|
126
124
|
Finally, we add a `TransactionConfirmationPending` component to ask for approval.
|
|
@@ -208,16 +206,32 @@ export function TransactionConfirmationPending(props: TransactionConfirmation) {
|
|
|
208
206
|
|
|
209
207
|
### Bind approval UI
|
|
210
208
|
|
|
211
|
-
```tsx title="@/app/page.tsx" {1,
|
|
212
|
-
|
|
209
|
+
```tsx title="@/app/page.tsx" {1-5,12}
|
|
210
|
+
"use client";
|
|
211
|
+
|
|
212
|
+
import { Thread } from "@/components/assistant-ui/thread";
|
|
213
|
+
import { PriceSnapshotToolUI } from "@/components/tools/price-snapshot/PriceSnapshotTool";
|
|
214
|
+
import { PurchaseStockToolUI } from "@/components/tools/purchase-stock/PurchaseStockTool";
|
|
215
|
+
import { AuiProvider, defineToolkit, Tools, useAui } from "@assistant-ui/react";
|
|
216
|
+
|
|
217
|
+
const toolkit = defineToolkit({
|
|
218
|
+
price_snapshot: {
|
|
219
|
+
type: "backend",
|
|
220
|
+
render: PriceSnapshotToolUI,
|
|
221
|
+
},
|
|
222
|
+
purchase_stock: {
|
|
223
|
+
type: "backend",
|
|
224
|
+
render: PurchaseStockToolUI,
|
|
225
|
+
},
|
|
226
|
+
});
|
|
213
227
|
|
|
214
228
|
export default function Home() {
|
|
229
|
+
const aui = useAui({ tools: Tools({ toolkit }) });
|
|
230
|
+
|
|
215
231
|
return (
|
|
216
|
-
<
|
|
217
|
-
<PriceSnapshotTool />
|
|
218
|
-
<PurchaseStockTool />
|
|
232
|
+
<AuiProvider value={aui}>
|
|
219
233
|
<Thread />
|
|
220
|
-
</
|
|
234
|
+
</AuiProvider>
|
|
221
235
|
);
|
|
222
236
|
}
|
|
223
237
|
```
|
|
@@ -305,7 +319,7 @@ We will import the new `<TransactionConfirmationFinal />` component and use it i
|
|
|
305
319
|
|
|
306
320
|
import { TransactionConfirmationPending } from "./transaction-confirmation-pending";
|
|
307
321
|
import { TransactionConfirmationFinal } from "./transaction-confirmation-final";
|
|
308
|
-
import {
|
|
322
|
+
import type { ToolCallMessagePartComponent } from "@assistant-ui/react";
|
|
309
323
|
|
|
310
324
|
type PurchaseStockArgs = {
|
|
311
325
|
ticker: string;
|
|
@@ -320,51 +334,49 @@ type PurchaseStockResult = {
|
|
|
320
334
|
error?: string;
|
|
321
335
|
};
|
|
322
336
|
|
|
323
|
-
export const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
},
|
|
367
|
-
);
|
|
337
|
+
export const PurchaseStockToolUI: ToolCallMessagePartComponent<
|
|
338
|
+
PurchaseStockArgs,
|
|
339
|
+
string
|
|
340
|
+
> = function PurchaseStockUI({ args, result, status, addResult }) {
|
|
341
|
+
let resultObj: PurchaseStockResult;
|
|
342
|
+
try {
|
|
343
|
+
resultObj = result ? JSON.parse(result) : {};
|
|
344
|
+
} catch (e) {
|
|
345
|
+
resultObj = { error: result! };
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const handleReject = () => {
|
|
349
|
+
addResult(JSON.stringify({ approve: false }));
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
const handleConfirm = async () => {
|
|
353
|
+
addResult(JSON.stringify({ approve: true }));
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
return (
|
|
357
|
+
<div className="mb-4 flex flex-col items-center gap-2">
|
|
358
|
+
<div>
|
|
359
|
+
<pre className="whitespace-pre-wrap break-all text-center">
|
|
360
|
+
purchase_stock({JSON.stringify(args)})
|
|
361
|
+
</pre>
|
|
362
|
+
</div>
|
|
363
|
+
{!result && status.type !== "running" && (
|
|
364
|
+
<TransactionConfirmationPending
|
|
365
|
+
{...args}
|
|
366
|
+
onConfirm={handleConfirm}
|
|
367
|
+
onReject={handleReject}
|
|
368
|
+
/>
|
|
369
|
+
)}
|
|
370
|
+
{resultObj.approve && <TransactionConfirmationFinal {...args} />}
|
|
371
|
+
{resultObj.approve === false && (
|
|
372
|
+
<pre className="font-bold text-red-600">User rejected purchase</pre>
|
|
373
|
+
)}
|
|
374
|
+
{resultObj.cancelled && (
|
|
375
|
+
<pre className="font-bold text-red-600">Cancelled</pre>
|
|
376
|
+
)}
|
|
377
|
+
</div>
|
|
378
|
+
);
|
|
379
|
+
};
|
|
368
380
|
```
|
|
369
381
|
|
|
370
382
|
### Try it out!
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Backend Tools
|
|
3
|
+
description: Wire assistant-ui toolkits into your server with the AI SDK — AISDKToolkit, frontendTools, mixing client and server tools, and multi-modal results.
|
|
4
|
+
platforms: ["react"]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
A tool is only callable if the **model** knows about it, and the model is configured on your server. This page covers wiring a toolkit into an AI SDK route handler: exposing your generative toolkit, receiving client-defined tools, mixing the two, and round-tripping multi-modal results.
|
|
8
|
+
|
|
9
|
+
For authoring tools, see [Defining Tools](/docs/tools/defining-tools). For MCP servers, see [MCP](/docs/tools/mcp).
|
|
10
|
+
|
|
11
|
+
## The request body
|
|
12
|
+
|
|
13
|
+
`@assistant-ui/react-ai-sdk` posts `{ messages, system, tools }` to your route. `tools` is the map of **frontend** tools the client serialized for this request (the model needs their schemas to call them, even though they run in the browser):
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
const {
|
|
17
|
+
messages,
|
|
18
|
+
system,
|
|
19
|
+
tools,
|
|
20
|
+
}: {
|
|
21
|
+
messages: UIMessage[];
|
|
22
|
+
system?: string;
|
|
23
|
+
tools?: Record<string, { description?: string; parameters: JSONSchema7 }>;
|
|
24
|
+
} = await req.json();
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Generative toolkits: `AISDKToolkit`
|
|
28
|
+
|
|
29
|
+
When you author tools in a [`"use generative"` file](/docs/tools/defining-tools#quick-start-use-generative), the same import resolves to the **server build** inside a route handler — schema plus any backend `execute`, with renderers stripped. Wrap it in an `AISDKToolkit` and call `.tools()` with the uploaded `tools`:
|
|
30
|
+
|
|
31
|
+
```ts title="app/api/chat/route.ts"
|
|
32
|
+
import { AISDKToolkit } from "@assistant-ui/react-ai-sdk";
|
|
33
|
+
import { streamText, convertToModelMessages, type UIMessage } from "ai";
|
|
34
|
+
import { openai } from "@ai-sdk/openai";
|
|
35
|
+
import toolkit from "../../toolkit";
|
|
36
|
+
|
|
37
|
+
const aiToolkit = new AISDKToolkit({ toolkit });
|
|
38
|
+
|
|
39
|
+
export async function POST(req: Request) {
|
|
40
|
+
const { messages, system, tools } = await req.json();
|
|
41
|
+
|
|
42
|
+
const result = streamText({
|
|
43
|
+
model: openai("gpt-5.4-nano"),
|
|
44
|
+
system,
|
|
45
|
+
messages: await convertToModelMessages(messages),
|
|
46
|
+
tools: await aiToolkit.tools({ frontend: tools }),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return result.toUIMessageStreamResponse();
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`AISDKToolkit.tools()` registers every toolkit tool with the model using its schema, wires the backend `execute` where the server build carries one, and merges in the uploaded frontend tools. A server `execute` wins over an uploaded entry of the same name. Frontend and human tools (no server `execute`) are exposed schema-only and left for the client and the user to fulfill.
|
|
54
|
+
|
|
55
|
+
<Callout type="info">
|
|
56
|
+
If your toolkit spreads in MCP server tools (`defineMcpToolkit`), `.tools()`
|
|
57
|
+
also opens those connections. A module-scope `aiToolkit` pools them across
|
|
58
|
+
requests; see [MCP](/docs/tools/mcp) for the connection lifecycle and when to
|
|
59
|
+
call `aiToolkit.close()`. The older
|
|
60
|
+
`generativeTools({ toolkit, frontendTools })` is deprecated, MCP-less, and
|
|
61
|
+
superseded by `AISDKToolkit`.
|
|
62
|
+
</Callout>
|
|
63
|
+
|
|
64
|
+
## Client-defined tools: `frontendTools`
|
|
65
|
+
|
|
66
|
+
If a toolkit cannot go through the generative compiler, the AI SDK adapter still
|
|
67
|
+
serializes browser-executed tools into the request `tools`. Convert them to the
|
|
68
|
+
AI SDK shape with `frontendTools` and spread your own server tools alongside:
|
|
69
|
+
|
|
70
|
+
```ts title="app/api/chat/route.ts"
|
|
71
|
+
import { frontendTools } from "@assistant-ui/react-ai-sdk";
|
|
72
|
+
import { streamText, convertToModelMessages, tool, zodSchema } from "ai";
|
|
73
|
+
import { openai } from "@ai-sdk/openai";
|
|
74
|
+
import { z } from "zod";
|
|
75
|
+
|
|
76
|
+
export async function POST(req: Request) {
|
|
77
|
+
const { messages, tools } = await req.json();
|
|
78
|
+
|
|
79
|
+
const result = streamText({
|
|
80
|
+
model: openai("gpt-5.4-nano"),
|
|
81
|
+
messages: await convertToModelMessages(messages),
|
|
82
|
+
tools: {
|
|
83
|
+
...frontendTools(tools ?? {}),
|
|
84
|
+
query_database: tool({
|
|
85
|
+
description: "Query the application database.",
|
|
86
|
+
inputSchema: zodSchema(z.object({ query: z.string() })),
|
|
87
|
+
execute: async ({ query }) => db.query(query),
|
|
88
|
+
}),
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
return result.toUIMessageStreamResponse();
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`AISDKToolkit.tools()` calls `frontendTools` for you under the hood; reach for
|
|
97
|
+
`frontendTools` directly when you're not on the generative build.
|
|
98
|
+
|
|
99
|
+
<Callout type="tip">
|
|
100
|
+
`toToolsJSONSchema` emits the uploaded tools in alphabetical order, so two
|
|
101
|
+
renders that register the same set produce byte-identical request bodies —
|
|
102
|
+
which keeps provider prompt caches stable across renders.
|
|
103
|
+
</Callout>
|
|
104
|
+
|
|
105
|
+
## Multi-modal results
|
|
106
|
+
|
|
107
|
+
When a tool declares [`toModelOutput`](/docs/tools/defining-tools#multi-modal-tool-results), frontend tool results round-trip through the AI SDK chat protocol back to your route on the next turn. For `toModelOutput` to fire on those round-tripped results, pass the tool registry to `convertToModelMessages` as well — the [same pattern the AI SDK documents](https://ai-sdk.dev/docs/reference/ai-sdk-ui/convert-to-model-messages#multi-modal-tool-responses) for any multi-modal tool response:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
const aiSDKTools = { ...frontendTools(tools ?? {}) };
|
|
111
|
+
|
|
112
|
+
const result = streamText({
|
|
113
|
+
model,
|
|
114
|
+
// Pass tools to BOTH calls so prior results are projected via toModelOutput.
|
|
115
|
+
messages: await convertToModelMessages(messages, { tools: aiSDKTools }),
|
|
116
|
+
tools: aiSDKTools,
|
|
117
|
+
});
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Skip the `{ tools }` argument and prior results are sent as a plain JSON blob — `toModelOutput` is silently ignored. Tools without `toModelOutput` are unaffected either way.
|
|
121
|
+
|
|
122
|
+
<Callout type="warn">
|
|
123
|
+
**Read/write compatibility for persisted threads.** When `toModelOutput` is
|
|
124
|
+
set, the runtime persists the AI SDK output as
|
|
125
|
+
`{ __aui_modelContent, value }`. Upgrade every reader before any writer starts
|
|
126
|
+
producing `toModelOutput`; older readers treat the whole envelope as the
|
|
127
|
+
`result` and break that tool's `render`. Don't return objects whose top-level
|
|
128
|
+
key is literally `__aui_modelContent` from any `execute`.
|
|
129
|
+
</Callout>
|
|
130
|
+
|
|
131
|
+
## Multi-step tool calls
|
|
132
|
+
|
|
133
|
+
To let the model see a frontend tool's result and continue, configure the runtime to send back automatically when the last assistant message is complete with tool calls:
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import { lastAssistantMessageIsCompleteWithToolCalls } from "ai";
|
|
137
|
+
|
|
138
|
+
const runtime = useChatRuntime({
|
|
139
|
+
api: "/api/chat",
|
|
140
|
+
sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithToolCalls,
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
For the full AI SDK v6 backend setup — history persistence, reasoning, server-side approvals — see the [AI SDK v6 guide](/docs/runtimes/ai-sdk/v6).
|