@assistant-ui/mcp-docs-server 0.1.8 → 0.1.10

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 (28) hide show
  1. package/.docs/organized/code-examples/with-ai-sdk-v5.md +24 -17
  2. package/.docs/organized/code-examples/with-assistant-transport.md +1599 -0
  3. package/.docs/organized/code-examples/with-cloud.md +11 -11
  4. package/.docs/organized/code-examples/with-external-store.md +9 -9
  5. package/.docs/organized/code-examples/with-ffmpeg.md +17 -16
  6. package/.docs/organized/code-examples/with-langgraph.md +33 -110
  7. package/.docs/organized/code-examples/with-parent-id-grouping.md +9 -9
  8. package/.docs/organized/code-examples/with-react-hook-form.md +17 -16
  9. package/.docs/raw/docs/api-reference/primitives/Thread.mdx +40 -8
  10. package/.docs/raw/docs/cloud/persistence/langgraph.mdx +42 -66
  11. package/.docs/raw/docs/copilots/assistant-frame.mdx +18 -16
  12. package/.docs/raw/docs/devtools.mdx +51 -0
  13. package/.docs/raw/docs/getting-started.mdx +2 -4
  14. package/.docs/raw/docs/guides/ToolUI.mdx +112 -37
  15. package/.docs/raw/docs/guides/Tools.mdx +170 -6
  16. package/.docs/raw/docs/migrations/react-langgraph-v0-7.mdx +324 -0
  17. package/.docs/raw/docs/runtimes/ai-sdk/use-chat.mdx +2 -2
  18. package/.docs/raw/docs/runtimes/custom/local.mdx +1 -1
  19. package/.docs/raw/docs/runtimes/langgraph/index.mdx +55 -20
  20. package/.docs/raw/docs/runtimes/mastra/full-stack-integration.mdx +6 -5
  21. package/.docs/raw/docs/runtimes/mastra/overview.mdx +3 -3
  22. package/.docs/raw/docs/runtimes/mastra/separate-server-integration.mdx +13 -13
  23. package/.docs/raw/docs/ui/Thread.mdx +368 -5
  24. package/package.json +8 -8
  25. package/.docs/raw/docs/migrations/v0-7.mdx +0 -188
  26. package/.docs/raw/docs/migrations/v0-8.mdx +0 -160
  27. package/.docs/raw/docs/migrations/v0-9.mdx +0 -75
  28. package/.docs/raw/docs/ui/primitives/Thread.mdx +0 -197
@@ -359,13 +359,167 @@ const RefundTool = makeAssistantTool({
359
359
  });
360
360
  ```
361
361
 
362
+ ### Tool Human Input
363
+
364
+ Tools can pause their execution to request user input or approval before continuing. This is useful for:
365
+
366
+ - Requesting user confirmation for sensitive operations
367
+ - Collecting additional information mid-execution
368
+ - Implementing progressive disclosure workflows
369
+ - Building interactive, multi-step tool experiences
370
+
371
+ ```tsx
372
+ import { makeAssistantTool, tool } from "@assistant-ui/react";
373
+ import { z } from "zod";
374
+
375
+ const confirmationTool = tool({
376
+ description: "Send an email with confirmation",
377
+ parameters: z.object({
378
+ to: z.string(),
379
+ subject: z.string(),
380
+ body: z.string(),
381
+ }),
382
+ execute: async ({ to, subject, body }, { human }) => {
383
+ // Request user confirmation before sending
384
+ const confirmed = await human({
385
+ type: "confirmation",
386
+ action: "send-email",
387
+ details: { to, subject },
388
+ });
389
+
390
+ if (!confirmed) {
391
+ return {
392
+ status: "cancelled",
393
+ message: "Email sending cancelled by user",
394
+ };
395
+ }
396
+
397
+ // Proceed with sending the email
398
+ await sendEmail({ to, subject, body });
399
+ return { status: "sent", message: `Email sent to ${to}` };
400
+ },
401
+ });
402
+
403
+ const EmailTool = makeAssistantTool({
404
+ ...confirmationTool,
405
+ toolName: "sendEmail",
406
+ render: ({ args, result, interrupt, resume }) => {
407
+ // The interrupt payload is available when the tool is waiting for user input
408
+ if (interrupt) {
409
+ return (
410
+ <div className="confirmation-dialog">
411
+ <h3>Confirm Email</h3>
412
+ <p>Send email to: {interrupt.payload.details.to}</p>
413
+ <p>Subject: {interrupt.payload.details.subject}</p>
414
+ <div className="actions">
415
+ <button onClick={() => resume(true)}>Confirm</button>
416
+ <button onClick={() => resume(false)}>Cancel</button>
417
+ </div>
418
+ </div>
419
+ );
420
+ }
421
+
422
+ // Show the result after completion
423
+ if (result) {
424
+ return (
425
+ <div className="email-result">
426
+ <p>{result.message}</p>
427
+ </div>
428
+ );
429
+ }
430
+
431
+ // Show loading state
432
+ return <div>Preparing email...</div>;
433
+ },
434
+ });
435
+ ```
436
+
437
+ #### Human Input Behavior
438
+
439
+ - **Payload**: The object passed to `human()` is available in the `render` function as `interrupt.payload`
440
+ - **Type**: The `interrupt` object has the structure `{ type: "human", payload: ... }`
441
+ - **Resume**: Call `resume(payload)` to continue execution - the payload becomes the resolved value of the `human()` call
442
+ - **Multiple Requests**: If `human()` is called multiple times, previous requests are automatically rejected with an error
443
+ - **Cancellation**: If the tool execution is aborted (e.g., user cancels the message), all pending requests are rejected
444
+
445
+ #### Advanced Human Input Patterns
446
+
447
+ You can use human input for complex multi-step interactions:
448
+
449
+ ```tsx
450
+ const wizardTool = tool({
451
+ description: "Multi-step data processing wizard",
452
+ parameters: z.object({
453
+ dataSource: z.string(),
454
+ }),
455
+ execute: async ({ dataSource }, { human }) => {
456
+ // Step 1: Load data
457
+ const data = await loadData(dataSource);
458
+
459
+ // Step 2: Request user to select columns
460
+ const selectedColumns = await human({
461
+ type: "column-selection",
462
+ availableColumns: data.columns,
463
+ });
464
+
465
+ // Step 3: Request processing options
466
+ const options = await human({
467
+ type: "processing-options",
468
+ columns: selectedColumns,
469
+ });
470
+
471
+ // Step 4: Process data with user selections
472
+ const result = await processData(data, selectedColumns, options);
473
+ return result;
474
+ },
475
+ });
476
+
477
+ const WizardTool = makeAssistantTool({
478
+ ...wizardTool,
479
+ toolName: "dataWizard",
480
+ render: ({ args, result, interrupt, resume }) => {
481
+ if (interrupt?.payload.type === "column-selection") {
482
+ return (
483
+ <ColumnSelector
484
+ columns={interrupt.payload.availableColumns}
485
+ onSelect={(cols) => resume(cols)}
486
+ />
487
+ );
488
+ }
489
+
490
+ if (interrupt?.payload.type === "processing-options") {
491
+ return (
492
+ <ProcessingOptions
493
+ columns={interrupt.payload.columns}
494
+ onConfirm={(opts) => resume(opts)}
495
+ />
496
+ );
497
+ }
498
+
499
+ if (result) {
500
+ return <ResultDisplay data={result} />;
501
+ }
502
+
503
+ return <div>Loading...</div>;
504
+ },
505
+ });
506
+ ```
507
+
508
+ <Callout type="note">
509
+ When a tool calls `human()` multiple times (e.g., for multi-step
510
+ workflows), each new request automatically rejects any previous pending
511
+ request. Make sure to handle potential errors if you need to support
512
+ cancellation of earlier steps.
513
+ </Callout>
514
+
362
515
  ### MCP (Model Context Protocol) Tools
363
516
 
364
517
  Integration with MCP servers using AI SDK v5's experimental MCP support:
365
518
 
366
519
  <Callout type="warning">
367
- MCP support in AI SDK v5 is experimental. The API may change in future releases.
368
- Make sure to install the MCP SDK: `npm install @modelcontextprotocol/sdk`
520
+ MCP support in AI SDK v5 is experimental. The API may change in future
521
+ releases. Make sure to install the MCP SDK: `npm install
522
+ @modelcontextprotocol/sdk`
369
523
  </Callout>
370
524
 
371
525
  ```tsx
@@ -414,15 +568,13 @@ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
414
568
  // HTTP transport
415
569
  const httpClient = await experimental_createMCPClient({
416
570
  transport: new StreamableHTTPClientTransport(
417
- new URL("http://localhost:3000/mcp")
571
+ new URL("http://localhost:3000/mcp"),
418
572
  ),
419
573
  });
420
574
 
421
575
  // Server-Sent Events transport
422
576
  const sseClient = await experimental_createMCPClient({
423
- transport: new SSEClientTransport(
424
- new URL("http://localhost:3000/sse")
425
- ),
577
+ transport: new SSEClientTransport(new URL("http://localhost:3000/sse")),
426
578
  });
427
579
  ```
428
580
 
@@ -560,9 +712,21 @@ Tools receive additional context during execution:
560
712
  execute: async (args, context) => {
561
713
  // context.abortSignal - AbortSignal for cancellation
562
714
  // context.toolCallId - Unique identifier for this invocation
715
+ // context.human - Function to request human input
716
+
717
+ // Example: Request user confirmation
718
+ const userResponse = await context.human({
719
+ message: "Are you sure?",
720
+ });
563
721
  };
564
722
  ```
565
723
 
724
+ The execution context provides:
725
+
726
+ - **`abortSignal`**: An `AbortSignal` that triggers when the tool execution is cancelled
727
+ - **`toolCallId`**: A unique identifier for this specific tool invocation
728
+ - **`human`**: A function that pauses execution and requests user input. The payload passed to `human()` becomes available in the render function, and the value passed to `resume()` becomes the resolved value of the `human()` call
729
+
566
730
  ## Runtime Integration
567
731
 
568
732
  Each integration handles tools differently:
@@ -0,0 +1,324 @@
1
+ ---
2
+ title: Migrating to react-langgraph v0.7
3
+ ---
4
+
5
+ import { Callout } from "fumadocs-ui/components/callout";
6
+ import { Steps, Step } from "fumadocs-ui/components/steps";
7
+
8
+ ## Overview
9
+
10
+ This guide helps you migrate from the previous LangGraph integration pattern to the new simplified API introduced in `@assistant-ui/react-langgraph` v0.7. The new API consolidates thread management directly into `useLangGraphRuntime`, eliminating the need for separate runtime hooks and manual thread state management.
11
+
12
+ ## Key Changes
13
+
14
+ ### 1. Simplified Thread Management
15
+
16
+ The `useLangGraphRuntime` hook now directly handles thread lifecycle:
17
+ - No more `useRemoteThreadListRuntime` wrapper
18
+ - No more separate runtime hook functions
19
+ - Thread management is built into the core runtime
20
+
21
+ ### 2. New `initialize` Parameter
22
+
23
+ The `stream` function now receives an `initialize` parameter that handles thread creation and loading automatically.
24
+
25
+ ### 3. Direct Cloud Integration
26
+
27
+ Cloud persistence can now be configured directly in `useLangGraphRuntime` with the `cloud` parameter.
28
+
29
+ ## Migration Steps
30
+
31
+ <Steps>
32
+
33
+ <Step>
34
+
35
+ ### Update Your Runtime Implementation
36
+
37
+ #### Before (Old Pattern)
38
+
39
+ ```tsx
40
+ import {
41
+ useCloudThreadListRuntime,
42
+ useThreadListItemRuntime,
43
+ } from "@assistant-ui/react";
44
+ import { useLangGraphRuntime } from "@assistant-ui/react-langgraph";
45
+
46
+ const useMyLangGraphRuntime = () => {
47
+ const threadListItemRuntime = useThreadListItemRuntime();
48
+
49
+ const runtime = useLangGraphRuntime({
50
+ stream: async function* (messages) {
51
+ const { externalId } = await threadListItemRuntime.initialize();
52
+ if (!externalId) throw new Error("Thread not found");
53
+
54
+ return sendMessage({
55
+ threadId: externalId,
56
+ messages,
57
+ });
58
+ },
59
+ onSwitchToThread: async (externalId) => {
60
+ const state = await getThreadState(externalId);
61
+ return {
62
+ messages: state.values.messages,
63
+ };
64
+ },
65
+ });
66
+
67
+ return runtime;
68
+ };
69
+
70
+ // In your component:
71
+ const runtime = useCloudThreadListRuntime({
72
+ cloud,
73
+ runtimeHook: useMyLangGraphRuntime,
74
+ create: async () => {
75
+ const { thread_id } = await createThread();
76
+ return { externalId: thread_id };
77
+ },
78
+ });
79
+ ```
80
+
81
+ #### After (New Pattern)
82
+
83
+ ```tsx
84
+ import { useLangGraphRuntime } from "@assistant-ui/react-langgraph";
85
+
86
+ // Directly in your component:
87
+ const runtime = useLangGraphRuntime({
88
+ cloud, // Optional: for cloud persistence
89
+ stream: async function* (messages, { initialize }) {
90
+ const { externalId } = await initialize();
91
+ if (!externalId) throw new Error("Thread not found");
92
+
93
+ return sendMessage({
94
+ threadId: externalId,
95
+ messages,
96
+ });
97
+ },
98
+ create: async () => {
99
+ const { thread_id } = await createThread();
100
+ return { externalId: thread_id };
101
+ },
102
+ load: async (externalId) => {
103
+ const state = await getThreadState(externalId);
104
+ return {
105
+ messages: state.values.messages,
106
+ };
107
+ },
108
+ });
109
+ ```
110
+
111
+ </Step>
112
+
113
+ <Step>
114
+
115
+ ### Update Import Statements
116
+
117
+ Remove unused imports:
118
+
119
+ ```diff
120
+ - import {
121
+ - useCloudThreadListRuntime,
122
+ - useThreadListItemRuntime,
123
+ - } from "@assistant-ui/react";
124
+ + import { AssistantCloud } from "@assistant-ui/react";
125
+ ```
126
+
127
+ </Step>
128
+
129
+ <Step>
130
+
131
+ ### Simplify Component Structure
132
+
133
+ You no longer need a separate runtime hook function. Everything can be defined directly in your component or provider:
134
+
135
+ ```tsx
136
+ export function MyRuntimeProvider({ children }) {
137
+ const cloud = useMemo(
138
+ () => new AssistantCloud({
139
+ baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL,
140
+ }),
141
+ []
142
+ );
143
+
144
+ const runtime = useLangGraphRuntime({
145
+ cloud,
146
+ // All configuration inline
147
+ stream: async function* (messages, { initialize }) {
148
+ // Your stream implementation
149
+ },
150
+ create: async () => {
151
+ // Your create implementation
152
+ },
153
+ load: async (externalId) => {
154
+ // Your load implementation
155
+ },
156
+ });
157
+
158
+ return (
159
+ <AssistantRuntimeProvider runtime={runtime}>
160
+ {children}
161
+ </AssistantRuntimeProvider>
162
+ );
163
+ }
164
+ ```
165
+
166
+ </Step>
167
+
168
+ <Step>
169
+
170
+ ### Update Method Names
171
+
172
+ Rename methods to match the new API:
173
+
174
+ - `onSwitchToThread` → `load`
175
+ - `onSwitchToNewThread` → handled automatically via `create`
176
+ - Thread ID management is now automatic
177
+
178
+ </Step>
179
+
180
+ </Steps>
181
+
182
+ ## API Reference Changes
183
+
184
+ ### Old API
185
+
186
+ ```typescript
187
+ type OldLangGraphRuntimeOptions = {
188
+ threadId?: string;
189
+ stream: (messages: Message[]) => AsyncGenerator;
190
+ onSwitchToNewThread?: () => Promise<void>;
191
+ onSwitchToThread?: (threadId: string) => Promise<ThreadState>;
192
+ };
193
+ ```
194
+
195
+ ### New API
196
+
197
+ ```typescript
198
+ type NewLangGraphRuntimeOptions = {
199
+ cloud?: AssistantCloud;
200
+ stream: (
201
+ messages: Message[],
202
+ context: {
203
+ initialize: () => Promise<{
204
+ remoteId: string;
205
+ externalId: string | undefined;
206
+ }>
207
+ }
208
+ ) => AsyncGenerator;
209
+ create?: () => Promise<{ externalId: string }>;
210
+ load?: (externalId: string) => Promise<ThreadState>;
211
+ delete?: (externalId: string) => Promise<void>;
212
+ };
213
+ ```
214
+
215
+ ## Benefits of the New API
216
+
217
+ 1. **Simpler Setup**: No need for multiple runtime hooks and wrappers
218
+ 2. **Cleaner Code**: All configuration in one place
219
+ 3. **Better Type Safety**: More explicit types for thread management
220
+ 4. **Automatic Thread Handling**: The runtime manages thread lifecycle internally
221
+ 5. **Optional Cloud Integration**: Add cloud persistence with a single parameter
222
+
223
+ ## Common Migration Issues
224
+
225
+ <Callout type="warning">
226
+ **Breaking Change**: The `threadId` and `onSwitchToNewThread` parameters are no longer supported. Use the new `create` and `load` methods instead.
227
+ </Callout>
228
+
229
+ ### Issue: `threadListItemRuntime` is not defined
230
+
231
+ **Solution**: Remove references to `useThreadListItemRuntime()`. Use the `initialize` parameter in the stream function instead.
232
+
233
+ ### Issue: Thread switching doesn't work
234
+
235
+ **Solution**: Ensure you've implemented both `create` and `load` functions. The runtime needs both to manage thread lifecycle.
236
+
237
+ ### Issue: Cloud persistence not working
238
+
239
+ **Solution**: Pass the `AssistantCloud` instance directly to `useLangGraphRuntime` via the `cloud` parameter.
240
+
241
+ ## Example: Complete Migration
242
+
243
+ Here's a complete before and after example for a typical LangGraph integration:
244
+
245
+ ### Before
246
+
247
+ ```tsx title="runtime-provider.tsx"
248
+ import {
249
+ AssistantCloud,
250
+ AssistantRuntimeProvider,
251
+ useCloudThreadListRuntime,
252
+ useThreadListItemRuntime,
253
+ } from "@assistant-ui/react";
254
+ import { useLangGraphRuntime } from "@assistant-ui/react-langgraph";
255
+
256
+ const useMyRuntime = () => {
257
+ const threadListItemRuntime = useThreadListItemRuntime();
258
+
259
+ return useLangGraphRuntime({
260
+ stream: async function* (messages) {
261
+ const { externalId } = await threadListItemRuntime.initialize();
262
+ // ... implementation
263
+ },
264
+ onSwitchToThread: async (externalId) => {
265
+ // ... implementation
266
+ },
267
+ });
268
+ };
269
+
270
+ export function Provider({ children }) {
271
+ const cloud = new AssistantCloud({ /* config */ });
272
+
273
+ const runtime = useCloudThreadListRuntime({
274
+ cloud,
275
+ runtimeHook: useMyRuntime,
276
+ create: async () => { /* ... */ },
277
+ });
278
+
279
+ return (
280
+ <AssistantRuntimeProvider runtime={runtime}>
281
+ {children}
282
+ </AssistantRuntimeProvider>
283
+ );
284
+ }
285
+ ```
286
+
287
+ ### After
288
+
289
+ ```tsx title="runtime-provider.tsx"
290
+ import {
291
+ AssistantCloud,
292
+ AssistantRuntimeProvider,
293
+ } from "@assistant-ui/react";
294
+ import { useLangGraphRuntime } from "@assistant-ui/react-langgraph";
295
+
296
+ export function Provider({ children }) {
297
+ const cloud = new AssistantCloud({ /* config */ });
298
+
299
+ const runtime = useLangGraphRuntime({
300
+ cloud,
301
+ stream: async function* (messages, { initialize }) {
302
+ const { externalId } = await initialize();
303
+ // ... implementation
304
+ },
305
+ create: async () => { /* ... */ },
306
+ load: async (externalId) => {
307
+ // ... implementation (formerly onSwitchToThread)
308
+ },
309
+ });
310
+
311
+ return (
312
+ <AssistantRuntimeProvider runtime={runtime}>
313
+ {children}
314
+ </AssistantRuntimeProvider>
315
+ );
316
+ }
317
+ ```
318
+
319
+ ## Need Help?
320
+
321
+ If you encounter issues during migration:
322
+ 1. Check the updated [LangGraph documentation](/docs/runtimes/langgraph)
323
+ 2. Review the [example implementation](https://github.com/assistant-ui/assistant-ui/tree/main/examples/with-langgraph)
324
+ 3. Report issues on [GitHub](https://github.com/assistant-ui/assistant-ui/issues)
@@ -130,7 +130,7 @@ const runtime = useChatRuntime({
130
130
  <Callout type="info">
131
131
  By default, `useChatRuntime` uses `AssistantChatTransport` which automatically
132
132
  forwards system messages and frontend tools to your backend API. This enables
133
- your backend to receive the full context from the Assistant UI.
133
+ your backend to receive the full context from the assistant-ui.
134
134
  </Callout>
135
135
 
136
136
  ### Custom Transport Configuration
@@ -165,7 +165,7 @@ const runtime = useChatRuntime({
165
165
 
166
166
  #### Transport Options
167
167
 
168
- - **`AssistantChatTransport`** (default): Automatically forwards system messages and frontend tools from the Assistant UI context to your backend
168
+ - **`AssistantChatTransport`** (default): Automatically forwards system messages and frontend tools from the assistant-ui context to your backend
169
169
  - **`DefaultChatTransport`**: Standard AI SDK transport without automatic forwarding
170
170
 
171
171
  ### Using Frontend Tools with `frontendTools`
@@ -732,7 +732,7 @@ Provide follow-up suggestions:
732
732
 
733
733
  ```tsx
734
734
  const suggestionAdapter: SuggestionAdapter = {
735
- async *get({ messages }) {
735
+ async *generate({ messages }) {
736
736
  // Analyze conversation context
737
737
  const lastMessage = messages[messages.length - 1];
738
738
 
@@ -61,7 +61,6 @@ npm install @assistant-ui/react @assistant-ui/react-ui @assistant-ui/react-langg
61
61
  ```tsx twoslash title="@/api/api/[...path]/route.ts"
62
62
  import { NextRequest, NextResponse } from "next/server";
63
63
 
64
-
65
64
  function getCorsHeaders() {
66
65
  return {
67
66
  "Access-Control-Allow-Origin": "*",
@@ -188,7 +187,6 @@ export const sendMessage = async (params: {
188
187
  // ---cut---
189
188
  "use client";
190
189
 
191
- import { useRef } from "react";
192
190
  import { Thread } from "@/components/assistant-ui";
193
191
  import { AssistantRuntimeProvider } from "@assistant-ui/react";
194
192
  import { useLangGraphRuntime } from "@assistant-ui/react-langgraph";
@@ -196,27 +194,21 @@ import { useLangGraphRuntime } from "@assistant-ui/react-langgraph";
196
194
  import { createThread, getThreadState, sendMessage } from "@/lib/chatApi";
197
195
 
198
196
  export function MyAssistant() {
199
- const threadIdRef = useRef<string | undefined>();
200
197
  const runtime = useLangGraphRuntime({
201
- threadId: threadIdRef.current,
202
- stream: async (messages) => {
203
- if (!threadIdRef.current) {
204
- const { thread_id } = await createThread();
205
- threadIdRef.current = thread_id;
206
- }
207
- const threadId = threadIdRef.current;
198
+ stream: async (messages, { initialize }) => {
199
+ const { externalId } = await initialize();
200
+ if (!externalId) throw new Error("Thread not found");
208
201
  return sendMessage({
209
- threadId,
202
+ threadId: externalId,
210
203
  messages,
211
204
  });
212
205
  },
213
- onSwitchToNewThread: async () => {
206
+ create: async () => {
214
207
  const { thread_id } = await createThread();
215
- threadIdRef.current = thread_id;
208
+ return { externalId: thread_id };
216
209
  },
217
- onSwitchToThread: async (threadId) => {
218
- const state = await getThreadState(threadId);
219
- threadIdRef.current = threadId;
210
+ load: async (externalId) => {
211
+ const state = await getThreadState(externalId);
220
212
  return {
221
213
  messages: state.values.messages,
222
214
  interrupts: state.tasks[0]?.interrupts,
@@ -306,14 +298,57 @@ import { convertLangChainMessages } from "@assistant-ui/react-langgraph";
306
298
  const threadMessage = convertLangChainMessages(langChainMessage);
307
299
  ```
308
300
 
309
- ## Interrupt Persistence
301
+ ## Thread Management
302
+
303
+ ### Basic Thread Support
304
+
305
+ The `useLangGraphRuntime` hook now includes built-in thread management capabilities:
306
+
307
+ ```typescript
308
+ const runtime = useLangGraphRuntime({
309
+ stream: async (messages, { initialize }) => {
310
+ // initialize() creates or loads a thread and returns its IDs
311
+ const { remoteId, externalId } = await initialize();
312
+ // Use externalId (your backend's thread ID) for API calls
313
+ return sendMessage({ threadId: externalId, messages });
314
+ },
315
+ create: async () => {
316
+ // Called when creating a new thread
317
+ const { thread_id } = await createThread();
318
+ return { externalId: thread_id };
319
+ },
320
+ load: async (externalId) => {
321
+ // Called when loading an existing thread
322
+ const state = await getThreadState(externalId);
323
+ return {
324
+ messages: state.values.messages,
325
+ interrupts: state.tasks[0]?.interrupts,
326
+ };
327
+ },
328
+ });
329
+ ```
310
330
 
311
- LangGraph supports interrupting the execution flow to request user input or handle specific interactions. These interrupts can be persisted and restored when switching between threads. This means that if a user switches away from a thread during an interaction (like waiting for user approval), the interaction state will be preserved when they return to that thread.
331
+ ### Cloud Persistence
332
+
333
+ For persistent thread history across sessions, integrate with assistant-cloud:
334
+
335
+ ```typescript
336
+ const runtime = useLangGraphRuntime({
337
+ cloud: new AssistantCloud({
338
+ baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL,
339
+ }),
340
+ // ... stream, create, load functions
341
+ });
342
+ ```
343
+
344
+ See the [Cloud Persistence guide](/docs/cloud/persistence/langgraph) for detailed setup instructions.
345
+
346
+ ## Interrupt Persistence
312
347
 
313
- To handle interrupts in your application:
348
+ LangGraph supports interrupting the execution flow to request user input or handle specific interactions. These interrupts can be persisted and restored when switching between threads:
314
349
 
315
350
  1. Make sure your thread state type includes the `interrupts` field
316
- 2. Return the interrupts from `onSwitchToThread` along with the messages
351
+ 2. Return the interrupts from the `load` function along with the messages
317
352
  3. The runtime will automatically restore the interrupt state when switching threads
318
353
 
319
354
  This feature is particularly useful for applications that require user approval flows, multi-step forms, or any other interactive elements that might span multiple thread switches.