@assistant-ui/mcp-docs-server 0.1.24 → 0.1.25

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 (135) hide show
  1. package/.docs/organized/code-examples/waterfall.md +4 -2
  2. package/.docs/organized/code-examples/with-a2a.md +676 -0
  3. package/.docs/organized/code-examples/with-ag-ui.md +5 -6
  4. package/.docs/organized/code-examples/with-ai-sdk-v6.md +27 -15
  5. package/.docs/organized/code-examples/with-artifacts.md +4 -4
  6. package/.docs/organized/code-examples/with-assistant-transport.md +2 -2
  7. package/.docs/organized/code-examples/with-chain-of-thought.md +33 -25
  8. package/.docs/organized/code-examples/with-cloud-standalone.md +9 -6
  9. package/.docs/organized/code-examples/with-cloud.md +4 -4
  10. package/.docs/organized/code-examples/with-custom-thread-list.md +6 -6
  11. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +7 -7
  12. package/.docs/organized/code-examples/with-expo.md +565 -514
  13. package/.docs/organized/code-examples/with-external-store.md +2 -2
  14. package/.docs/organized/code-examples/with-ffmpeg.md +4 -4
  15. package/.docs/organized/code-examples/with-google-adk.md +353 -0
  16. package/.docs/organized/code-examples/with-heat-graph.md +304 -0
  17. package/.docs/organized/code-examples/with-langgraph.md +24 -22
  18. package/.docs/organized/code-examples/with-parent-id-grouping.md +3 -3
  19. package/.docs/organized/code-examples/with-react-hook-form.md +4 -4
  20. package/.docs/organized/code-examples/with-react-ink.md +265 -0
  21. package/.docs/organized/code-examples/with-react-router.md +5 -5
  22. package/.docs/organized/code-examples/with-store.md +28 -17
  23. package/.docs/organized/code-examples/with-tanstack.md +7 -7
  24. package/.docs/organized/code-examples/with-tap-runtime.md +5 -3
  25. package/.docs/raw/blog/2025-01-31-changelog/index.mdx +1 -1
  26. package/.docs/raw/blog/2026-03-launch-week/index.mdx +227 -0
  27. package/.docs/raw/docs/(docs)/architecture.mdx +1 -1
  28. package/.docs/raw/docs/(docs)/cli.mdx +14 -9
  29. package/.docs/raw/docs/(docs)/copilots/make-assistant-tool-ui.mdx +8 -3
  30. package/.docs/raw/docs/(docs)/copilots/make-assistant-tool.mdx +5 -1
  31. package/.docs/raw/docs/(docs)/copilots/{make-assistant-readable.mdx → make-assistant-visible.mdx} +14 -5
  32. package/.docs/raw/docs/(docs)/copilots/model-context.mdx +11 -11
  33. package/.docs/raw/docs/(docs)/copilots/motivation.mdx +2 -2
  34. package/.docs/raw/docs/(docs)/devtools.mdx +3 -2
  35. package/.docs/raw/docs/(docs)/guides/attachments.mdx +9 -11
  36. package/.docs/raw/docs/(docs)/guides/branching.mdx +11 -6
  37. package/.docs/raw/docs/(docs)/guides/chain-of-thought.mdx +18 -16
  38. package/.docs/raw/docs/(docs)/guides/context-api.mdx +81 -43
  39. package/.docs/raw/docs/(docs)/guides/dictation.mdx +5 -5
  40. package/.docs/raw/docs/(docs)/guides/editing.mdx +16 -7
  41. package/.docs/raw/docs/(docs)/guides/latex.mdx +3 -0
  42. package/.docs/raw/docs/(docs)/guides/message-timing.mdx +2 -1
  43. package/.docs/raw/docs/(docs)/guides/multi-agent.mdx +173 -0
  44. package/.docs/raw/docs/(docs)/guides/quoting.mdx +55 -206
  45. package/.docs/raw/docs/(docs)/guides/speech.mdx +1 -4
  46. package/.docs/raw/docs/(docs)/guides/suggestions.mdx +9 -15
  47. package/.docs/raw/docs/(docs)/guides/tool-ui.mdx +17 -7
  48. package/.docs/raw/docs/(docs)/guides/tools.mdx +24 -9
  49. package/.docs/raw/docs/(docs)/index.mdx +3 -3
  50. package/.docs/raw/docs/(docs)/installation.mdx +69 -46
  51. package/.docs/raw/docs/(reference)/api-reference/context-providers/text-message-part-provider.mdx +20 -6
  52. package/.docs/raw/docs/(reference)/api-reference/integrations/react-data-stream.mdx +24 -4
  53. package/.docs/raw/docs/(reference)/api-reference/integrations/react-hook-form.mdx +1 -1
  54. package/.docs/raw/docs/(reference)/api-reference/integrations/vercel-ai-sdk.mdx +20 -19
  55. package/.docs/raw/docs/(reference)/api-reference/overview.mdx +28 -53
  56. package/.docs/raw/docs/(reference)/api-reference/primitives/action-bar.mdx +4 -4
  57. package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-modal.mdx +7 -1
  58. package/.docs/raw/docs/(reference)/api-reference/primitives/attachment.mdx +20 -14
  59. package/.docs/raw/docs/(reference)/api-reference/primitives/branch-picker.mdx +1 -1
  60. package/.docs/raw/docs/(reference)/api-reference/primitives/composer.mdx +99 -45
  61. package/.docs/raw/docs/(reference)/api-reference/primitives/message-part.mdx +52 -40
  62. package/.docs/raw/docs/(reference)/api-reference/primitives/message.mdx +343 -23
  63. package/.docs/raw/docs/(reference)/api-reference/primitives/suggestion.mdx +4 -6
  64. package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list-item.mdx +4 -2
  65. package/.docs/raw/docs/(reference)/api-reference/primitives/thread-list.mdx +3 -5
  66. package/.docs/raw/docs/(reference)/api-reference/primitives/thread.mdx +169 -22
  67. package/.docs/raw/docs/(reference)/api-reference/runtimes/assistant-runtime.mdx +14 -4
  68. package/.docs/raw/docs/(reference)/api-reference/runtimes/attachment-runtime.mdx +15 -26
  69. package/.docs/raw/docs/(reference)/api-reference/runtimes/composer-runtime.mdx +39 -21
  70. package/.docs/raw/docs/(reference)/api-reference/runtimes/message-part-runtime.mdx +33 -9
  71. package/.docs/raw/docs/(reference)/api-reference/runtimes/message-runtime.mdx +48 -21
  72. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-item-runtime.mdx +36 -7
  73. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-list-runtime.mdx +30 -10
  74. package/.docs/raw/docs/(reference)/api-reference/runtimes/thread-runtime.mdx +12 -10
  75. package/.docs/raw/docs/(reference)/migrations/deprecation-policy.mdx +1 -1
  76. package/.docs/raw/docs/(reference)/migrations/react-langgraph-v0-7.mdx +9 -4
  77. package/.docs/raw/docs/(reference)/migrations/v0-11.mdx +7 -5
  78. package/.docs/raw/docs/(reference)/migrations/v0-12.mdx +9 -7
  79. package/.docs/raw/docs/(reference)/migrations/v0-14.mdx +159 -0
  80. package/.docs/raw/docs/(reference)/react-compatibility.mdx +5 -134
  81. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +84 -6
  82. package/.docs/raw/docs/cloud/ai-sdk.mdx +14 -4
  83. package/.docs/raw/docs/cloud/langgraph.mdx +13 -3
  84. package/.docs/raw/docs/ink/adapters.mdx +41 -0
  85. package/.docs/raw/docs/ink/custom-backend.mdx +203 -0
  86. package/.docs/raw/docs/ink/hooks.mdx +448 -0
  87. package/.docs/raw/docs/ink/index.mdx +239 -0
  88. package/.docs/raw/docs/ink/migration.mdx +140 -0
  89. package/.docs/raw/docs/ink/primitives.mdx +699 -0
  90. package/.docs/raw/docs/react-native/adapters.mdx +63 -87
  91. package/.docs/raw/docs/react-native/custom-backend.mdx +11 -14
  92. package/.docs/raw/docs/react-native/hooks.mdx +214 -232
  93. package/.docs/raw/docs/react-native/index.mdx +118 -159
  94. package/.docs/raw/docs/react-native/migration.mdx +144 -0
  95. package/.docs/raw/docs/react-native/primitives.mdx +431 -302
  96. package/.docs/raw/docs/runtimes/a2a/index.mdx +294 -0
  97. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +9 -9
  98. package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +14 -3
  99. package/.docs/raw/docs/runtimes/assistant-transport.mdx +59 -25
  100. package/.docs/raw/docs/runtimes/custom/custom-thread-list.mdx +13 -6
  101. package/.docs/raw/docs/runtimes/custom/external-store.mdx +138 -38
  102. package/.docs/raw/docs/runtimes/custom/local.mdx +184 -42
  103. package/.docs/raw/docs/runtimes/data-stream.mdx +92 -19
  104. package/.docs/raw/docs/runtimes/google-adk/index.mdx +624 -0
  105. package/.docs/raw/docs/runtimes/helicone.mdx +6 -6
  106. package/.docs/raw/docs/runtimes/langgraph/index.mdx +38 -27
  107. package/.docs/raw/docs/runtimes/langgraph/tutorial/introduction.mdx +1 -1
  108. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-1.mdx +15 -20
  109. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-2.mdx +7 -11
  110. package/.docs/raw/docs/runtimes/langgraph/tutorial/part-3.mdx +8 -11
  111. package/.docs/raw/docs/runtimes/langserve.mdx +6 -7
  112. package/.docs/raw/docs/runtimes/pick-a-runtime.mdx +18 -3
  113. package/.docs/raw/docs/ui/file.mdx +5 -4
  114. package/.docs/raw/docs/ui/image.mdx +5 -4
  115. package/.docs/raw/docs/ui/markdown.mdx +3 -1
  116. package/.docs/raw/docs/ui/model-selector.mdx +8 -8
  117. package/.docs/raw/docs/ui/part-grouping.mdx +7 -10
  118. package/.docs/raw/docs/ui/quote.mdx +210 -0
  119. package/.docs/raw/docs/ui/reasoning.mdx +12 -11
  120. package/.docs/raw/docs/ui/sources.mdx +88 -17
  121. package/.docs/raw/docs/ui/streamdown.mdx +16 -7
  122. package/.docs/raw/docs/ui/thread-list.mdx +11 -13
  123. package/.docs/raw/docs/ui/thread.mdx +28 -33
  124. package/.docs/raw/docs/ui/tool-fallback.mdx +5 -6
  125. package/.docs/raw/docs/ui/tool-group.mdx +9 -8
  126. package/.docs/raw/docs/utilities/heat-graph.mdx +236 -0
  127. package/.docs/raw/docs/utilities/tw-shimmer.mdx +211 -0
  128. package/package.json +4 -4
  129. package/.docs/raw/docs/(reference)/legacy/styled/assistant-modal.mdx +0 -77
  130. package/.docs/raw/docs/(reference)/legacy/styled/decomposition.mdx +0 -635
  131. package/.docs/raw/docs/(reference)/legacy/styled/markdown.mdx +0 -77
  132. package/.docs/raw/docs/(reference)/legacy/styled/scrollbar.mdx +0 -72
  133. package/.docs/raw/docs/(reference)/legacy/styled/thread-width.mdx +0 -22
  134. package/.docs/raw/docs/(reference)/legacy/styled/thread.mdx +0 -77
  135. /package/.docs/raw/docs/cloud/{overview.mdx → index.mdx} +0 -0
@@ -30,13 +30,18 @@ assistant-ui organizes state into **scopes** - logical boundaries that provide a
30
30
  └── 💬 Thread (thread) - Active conversation with messages
31
31
  ├── 🔵 Message (message) - User or assistant message
32
32
  │ ├── 📝 Part (part) - Content within a message (text, tool calls, etc.)
33
+ │ ├── 🧠 ChainOfThought (chainOfThought) - Reasoning steps within a message
34
+ │ │ └── 📝 Part (part) - Individual reasoning/tool-call step
33
35
  │ ├── 📎 Attachment (attachment) - Files attached to messages
34
36
  │ └── ✏️ Composer (composer) - Edit mode for existing messages
35
37
  │ └── 📎 Attachment (attachment) - Files in edit mode
36
38
  └── ✏️ Composer (composer) - New message input
37
39
  └── 📎 Attachment (attachment) - Files being added
38
40
 
41
+ 💡 Suggestions (suggestions) - Follow-up message suggestions
42
+ └── 💬 Suggestion (suggestion) - Individual suggestion item
39
43
  🔧 Tools (tools) - Custom UI components for tool calls
44
+ 🧩 ModelContext (modelContext) - Model context and tool registration
40
45
  ```
41
46
 
42
47
  **How scopes work:**
@@ -166,12 +171,12 @@ The API object is stable and doesn't cause re-renders. Use it for:
166
171
  // Thread actions
167
172
  aui.thread().append(message);
168
173
  aui.thread().startRun(config);
174
+ aui.thread().resumeRun(config);
169
175
  aui.thread().cancelRun();
170
- aui.thread().switchToNewThread();
171
- aui.thread().switchToThread(threadId);
172
176
  aui.thread().getState();
173
- aui.thread().message(idOrIndex);
174
- aui.thread().composer;
177
+ aui.thread().message({ index: idx });
178
+ aui.thread().message({ id: messageId });
179
+ aui.thread().composer();
175
180
 
176
181
  // Message actions
177
182
  aui.message().reload();
@@ -180,12 +185,14 @@ aui.message().stopSpeaking();
180
185
  aui.message().submitFeedback({ type: "positive" | "negative" });
181
186
  aui.message().switchToBranch({ position, branchId });
182
187
  aui.message().getState();
183
- aui.message().part(indexOrToolCallId);
184
- aui.message().composer;
188
+ aui.message().part({ index: idx });
189
+ aui.message().part({ toolCallId });
190
+ aui.message().composer();
185
191
 
186
192
  // Part actions
187
- api.part().addResult(result);
188
- api.part().getState();
193
+ aui.part().addToolResult(result);
194
+ aui.part().resumeToolCall(result);
195
+ aui.part().getState();
189
196
 
190
197
  // Composer actions
191
198
  aui.composer().send();
@@ -193,8 +200,8 @@ aui.composer().setText(text);
193
200
  aui.composer().setRole(role);
194
201
  aui.composer().addAttachment(file); // File object
195
202
  aui.composer().addAttachment({ name, content }); // external source
196
- aui.composer().clearAttachments();
197
- aui.composer().reset();
203
+ await aui.composer().clearAttachments();
204
+ await aui.composer().reset();
198
205
  aui.composer().getState();
199
206
 
200
207
  // Attachment actions
@@ -212,7 +219,23 @@ aui.threadListItem().rename(title);
212
219
  aui.threadListItem().archive();
213
220
  aui.threadListItem().unarchive();
214
221
  aui.threadListItem().delete();
215
- aui.threads().getState();
222
+ aui.threadListItem().getState();
223
+
224
+ // Suggestions actions
225
+ aui.suggestions().getState();
226
+ aui.suggestions().suggestion({ index: 0 });
227
+
228
+ // Suggestion actions
229
+ aui.suggestion().getState();
230
+
231
+ // ChainOfThought actions
232
+ aui.chainOfThought().getState();
233
+ aui.chainOfThought().setCollapsed(collapsed);
234
+ aui.chainOfThought().part({ index: 0 });
235
+
236
+ // ModelContext actions
237
+ aui.modelContext().getState();
238
+ aui.modelContext().register(provider);
216
239
 
217
240
  // Tools actions
218
241
  aui.tools().setToolUI(toolName, render);
@@ -228,26 +251,29 @@ import { useAuiEvent } from "@assistant-ui/react";
228
251
 
229
252
  // Listen to current scope events (most common)
230
253
  useAuiEvent("composer.send", (event) => {
231
- console.log("Current composer sent message:", event.message);
254
+ console.log("Composer sent message in thread:", event.threadId);
255
+ });
256
+
257
+ // Listen to thread events
258
+ useAuiEvent("thread.runStart", (event) => {
259
+ console.log("Run started in thread:", event.threadId);
232
260
  });
233
261
 
234
262
  // Listen to all events of a type across all scopes
235
263
  useAuiEvent({ event: "composer.send", scope: "*" }, (event) => {
236
- console.log("Any composer sent a message:", event);
264
+ console.log("Any composer sent a message:", event.threadId);
237
265
  });
238
266
 
239
267
  // Listen to ALL events (useful for debugging or analytics)
240
268
  useAuiEvent("*", (event) => {
241
- console.log("Event occurred:", event.type, "from:", event.source);
242
- // Send to analytics, logging, etc.
269
+ console.log("Event occurred:", event.event, event.payload);
243
270
  });
244
271
 
245
272
  // Practical example: Track user interactions
246
273
  function AnalyticsTracker() {
247
274
  useAuiEvent("composer.send", (event) => {
248
275
  analytics.track("message_sent", {
249
- messageLength: event.message.content.length,
250
- hasAttachments: event.message.attachments.length > 0,
276
+ threadId: event.threadId,
251
277
  });
252
278
  });
253
279
 
@@ -272,9 +298,13 @@ Each scope provides access to specific state and actions:
272
298
  - **Thread** (`thread`): Conversation with messages
273
299
  - **Message** (`message`): Individual message (user or assistant)
274
300
  - **Part** (`part`): Content part within a message (text, tool calls, etc.)
301
+ - **ChainOfThought** (`chainOfThought`): Reasoning steps grouped within a message
275
302
  - **Composer** (`composer`): Text input for sending or editing messages
276
303
  - **Attachment** (`attachment`): File or media attached to a message or composer
304
+ - **Suggestions** (`suggestions`): Collection of follow-up message suggestions
305
+ - **Suggestion** (`suggestion`): Individual follow-up suggestion
277
306
  - **Tools** (`tools`): Tool UI components
307
+ - **ModelContext** (`modelContext`): Model context and tool registration
278
308
 
279
309
  ### Scope Resolution
280
310
 
@@ -301,7 +331,7 @@ Before accessing a scope, check if it's available:
301
331
  const aui = useAui();
302
332
 
303
333
  // Check if message scope exists
304
- if (api.message.source) {
334
+ if (aui.message.source) {
305
335
  // Safe to use message scope
306
336
  const { role } = aui.message().getState();
307
337
  }
@@ -325,9 +355,9 @@ const partByToolCall = aui.message().part({ toolCallId: "call_123" });
325
355
  // Access attachment by index
326
356
  const attachment = aui.composer().attachment({ index: 0 }).getState();
327
357
 
328
- // Access thread from thread list
329
- const thread = aui.threads().thread("main");
358
+ // Access thread list item by ID or index
330
359
  const threadItem = aui.threads().item({ id: "thread_123" });
360
+ const threadByIndex = aui.threads().item({ index: 0 });
331
361
  ```
332
362
 
333
363
  ## Common Patterns
@@ -400,7 +430,7 @@ function MessageCounter() {
400
430
 
401
431
  ### Resolution Dynamics
402
432
 
403
- When you call `api.scope()`, the API resolves the current scope at that moment. This resolution happens each time you call the function, which matters when dealing with changing contexts:
433
+ When you call `aui.scope()`, the API resolves the current scope at that moment. This resolution happens each time you call the function, which matters when dealing with changing contexts:
404
434
 
405
435
  ```tsx
406
436
  const aui = useAui();
@@ -458,27 +488,35 @@ const isRunning = useAuiState((s) => s.thread.isRunning);
458
488
 
459
489
  ### Scope States
460
490
 
461
- | Scope | Key State Properties | Description |
462
- | -------------- | --------------------------------------------------------------------------------- | ------------------------------------------------ |
463
- | ThreadList | `mainThreadId`, `threadIds`, `isLoading`, `threadItems` | Manages all available conversation threads |
464
- | ThreadListItem | `id`, `title`, `status`, `remoteId`, `externalId` | Individual thread metadata and status |
465
- | Thread | `isRunning`, `isLoading`, `isDisabled`, `messages`, `capabilities`, `suggestions` | Active conversation state and message history |
466
- | Message | `role`, `content`, `status`, `attachments`, `parentId`, `branchNumber`, `isLast` | Individual message content and metadata |
467
- | Composer | `text`, `role`, `attachments`, `isEmpty`, `canCancel`, `type`, `isEditing` | Text input state for new/edited messages |
468
- | Part | `type`, `content`, `status`, `text`, `toolCallId`, `toolName` | Content parts within messages (text, tool calls) |
469
- | Attachment | `id`, `type`, `name`, `url`, `size`, `mimeType` | File attachments metadata and content |
491
+ | Scope | Key State Properties | Description |
492
+ | -------------- | ------------------------------------------------------------------------------------------------ | -------------------------------------------------- |
493
+ | ThreadList | `mainThreadId`, `newThreadId`, `threadIds`, `archivedThreadIds`, `isLoading`, `threadItems` | Manages all available conversation threads |
494
+ | ThreadListItem | `id`, `title`, `status`, `remoteId`, `externalId` | Individual thread metadata and status |
495
+ | Thread | `isRunning`, `isLoading`, `isDisabled`, `isEmpty`, `messages`, `capabilities`, `suggestions` | Active conversation state and message history |
496
+ | Message | `role`, `content`, `status`, `attachments`, `parts`, `parentId`, `branchNumber`, `branchCount`, `isLast`, `index` | Individual message content and metadata |
497
+ | Part | `type`, `status`, `text`, `toolCallId`, `toolName` | Content parts within messages (text, tool calls) |
498
+ | ChainOfThought | `parts`, `collapsed`, `status` | Reasoning steps grouped within a message |
499
+ | Composer | `text`, `role`, `attachments`, `isEmpty`, `canCancel`, `type`, `isEditing` | Text input state for new/edited messages |
500
+ | Attachment | `id`, `type`, `name`, `contentType`, `status` | File attachments metadata and content |
501
+ | Suggestions | `suggestions` | Collection of follow-up message suggestions |
502
+ | Suggestion | `title`, `label`, `prompt` | Individual suggestion with title, label, and prompt |
503
+ | ModelContext | *(empty — use `register()` / `getToolCallParams()` methods)* | Model context and tool registration |
470
504
 
471
505
  ### Available Actions by Scope
472
506
 
473
- | Scope | Actions | Use Cases |
474
- | -------------- | ------------------------------------------------------------------------- | ----------------------------------------- |
475
- | ThreadList | `switchToNewThread()`, `switchToThread(id)`, `getState()` | Thread navigation and creation |
476
- | ThreadListItem | `switchTo()`, `rename(title)`, `archive()`, `unarchive()`, `delete()` | Thread management operations |
477
- | Thread | `append(message)`, `startRun()`, `cancelRun()`, `switchToNewThread()` | Message handling and conversation control |
478
- | Message | `reload()`, `speak()`, `stopSpeaking()`, `submitFeedback(feedback)` | Message interactions and regeneration |
479
- | Composer | `send()`, `setText(text)`, `addAttachment(file \| attachment)`, `reset()` | Text input and message composition |
480
- | Part | `addResult(result)`, `getState()` | Tool call result handling |
481
- | Attachment | `remove()`, `getState()` | File management |
507
+ | Scope | Actions | Use Cases |
508
+ | -------------- | ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
509
+ | ThreadList | `switchToNewThread()`, `switchToThread(id)`, `item(selector)`, `thread("main")`, `getState()` | Thread navigation and creation |
510
+ | ThreadListItem | `switchTo()`, `rename(title)`, `archive()`, `unarchive()`, `delete()`, `getState()` | Thread management operations |
511
+ | Thread | `append(message)`, `startRun(config)`, `resumeRun(config)`, `cancelRun()`, `reset()`, `export()`, `import(repository)`, `message(selector)`, `composer()`, `getState()` | Message handling and conversation control |
512
+ | Message | `reload()`, `speak()`, `stopSpeaking()`, `submitFeedback(feedback)`, `switchToBranch(options)`, `getCopyText()`, `part(selector)`, `attachment(selector)`, `composer()`, `setIsCopied(value)`, `setIsHovering(value)`, `getState()` | Message interactions and regeneration |
513
+ | Part | `addToolResult(result)`, `resumeToolCall(result)`, `getState()` | Tool call result handling |
514
+ | ChainOfThought | `setCollapsed(collapsed)`, `part({ index })`, `getState()` | Expand/collapse reasoning steps |
515
+ | Composer | `send()`, `setText(text)`, `setRole(role)`, `addAttachment(file \| attachment)`, `clearAttachments()` (async), `reset()` (async), `getState()` | Text input and message composition |
516
+ | Attachment | `remove()`, `getState()` | File management |
517
+ | Suggestions | `suggestion({ index })`, `getState()` | Access follow-up suggestions |
518
+ | Suggestion | `getState()` | Read individual suggestion data |
519
+ | ModelContext | `register(provider)`, `getState()` | Register model context providers |
482
520
 
483
521
  ### Common Events
484
522
 
@@ -508,7 +546,7 @@ function SafeMessageButton() {
508
546
  const aui = useAui();
509
547
 
510
548
  const role = useAuiState((s) =>
511
- api.message.source !== undefined ? s.message.role : "none",
549
+ aui.message.source !== undefined ? s.message.role : "none",
512
550
  );
513
551
 
514
552
  return <div>Role: {role}</div>;
@@ -558,18 +596,18 @@ const value = useAuiState((s) => s.scope.property);
558
596
 
559
597
  // Perform action
560
598
  const aui = useAui();
561
- api.scope().action();
599
+ aui.scope().action();
562
600
 
563
601
  // Listen to events
564
602
  useAuiEvent("source.event", (e) => {});
565
603
 
566
604
  // Check scope availability
567
- if (api.scope.source) {
605
+ if (aui.scope.source) {
568
606
  /* scope exists */
569
607
  }
570
608
 
571
609
  // Get state imperatively
572
- const state = api.scope().getState();
610
+ const state = aui.scope().getState();
573
611
 
574
612
  // Navigate scopes
575
613
  aui.thread().message({ id: "..." }).getState();
@@ -38,7 +38,7 @@ const runtime = useChatRuntime({
38
38
  The dictation feature uses `ComposerPrimitive.Dictate` and `ComposerPrimitive.StopDictation` components.
39
39
 
40
40
  ```tsx
41
- import { ComposerPrimitive } from "@assistant-ui/react";
41
+ import { AuiIf, ComposerPrimitive } from "@assistant-ui/react";
42
42
  import { MicIcon, SquareIcon } from "lucide-react";
43
43
 
44
44
  const ComposerWithDictation = () => (
@@ -46,18 +46,18 @@ const ComposerWithDictation = () => (
46
46
  <ComposerPrimitive.Input />
47
47
 
48
48
  {/* Show Dictate button when not dictating */}
49
- <ComposerPrimitive.If dictation={false}>
49
+ <AuiIf condition={(s) => s.composer.dictation == null}>
50
50
  <ComposerPrimitive.Dictate>
51
51
  <MicIcon />
52
52
  </ComposerPrimitive.Dictate>
53
- </ComposerPrimitive.If>
53
+ </AuiIf>
54
54
 
55
55
  {/* Show Stop button when dictating */}
56
- <ComposerPrimitive.If dictation>
56
+ <AuiIf condition={(s) => s.composer.dictation != null}>
57
57
  <ComposerPrimitive.StopDictation>
58
58
  <SquareIcon className="animate-pulse" />
59
59
  </ComposerPrimitive.StopDictation>
60
- </ComposerPrimitive.If>
60
+ </AuiIf>
61
61
 
62
62
  <ComposerPrimitive.Send />
63
63
  </ComposerPrimitive.Root>
@@ -9,8 +9,8 @@ Give the user the ability to edit their message.
9
9
 
10
10
  You can show an editor interface by using `ComposerPrimitive`.
11
11
 
12
- ```tsx {1,11,25,31-43}
13
- import { ComposerPrimitive } from "@assistant-ui/react";
12
+ ```tsx {1-2,11,25,31-52}
13
+ import { ComposerPrimitive, useAuiState } from "@assistant-ui/react";
14
14
  ...
15
15
 
16
16
  const Thread = () => {
@@ -18,10 +18,12 @@ const Thread = () => {
18
18
  <ThreadPrimitive.Root>
19
19
  <ThreadPrimitive.Viewport>
20
20
  ...
21
- <ThreadPrimitive.Messages components={{
22
- ...,
23
- EditComposer, // <-- Show our new component during edit mode
24
- }} />
21
+ <ThreadPrimitive.Messages>
22
+ {({ message }) => {
23
+ // Show our new component during edit mode
24
+ return <MessageWithEditComposer />;
25
+ }}
26
+ </ThreadPrimitive.Messages>
25
27
  </ThreadPrimitive.Viewport>
26
28
  ...
27
29
  </ThreadPrimitive.Root>
@@ -40,7 +42,14 @@ const UserMessage = () => {
40
42
  );
41
43
  };
42
44
 
43
- // define a new component
45
+ // define a wrapper component that handles both display and edit mode
46
+ const MessageWithEditComposer = () => {
47
+ const isEditing = useAuiState((s) => s.composer.isEditing);
48
+ if (isEditing) return <EditComposer />;
49
+ return <UserMessage />;
50
+ };
51
+
52
+ // define the edit composer component
44
53
  const EditComposer = () => {
45
54
  return (
46
55
  // you can return a MessagePrimitive including a ComposerPrimitive, or only a ComposerPrimitive
@@ -32,6 +32,7 @@ import "katex/dist/katex.min.css"; // [!code ++]
32
32
  ### Update `markdown-text.tsx`
33
33
 
34
34
  ```tsx title="/components/assistant-ui/markdown-text.tsx"
35
+ import { MarkdownTextPrimitive } from "@assistant-ui/react-markdown";
35
36
  import remarkMath from "remark-math"; // [!code ++]
36
37
  import rehypeKatex from "rehype-katex"; // [!code ++]
37
38
 
@@ -69,6 +70,8 @@ Many language models generate LaTeX using different delimiter formats:
69
70
  You can use the `preprocess` prop to normalize these formats:
70
71
 
71
72
  ```tsx title="/components/assistant-ui/markdown-text.tsx"
73
+ import { MarkdownTextPrimitive } from "@assistant-ui/react-markdown";
74
+
72
75
  const MarkdownTextImpl = () => {
73
76
  return (
74
77
  <MarkdownTextPrimitive
@@ -14,6 +14,7 @@ Display stream performance metrics — duration, tokens per second, TTFT — on
14
14
  Use `useMessageTiming()` inside a message component to access timing data:
15
15
 
16
16
  ```tsx
17
+ import type { FC } from "react";
17
18
  import { useMessageTiming } from "@assistant-ui/react";
18
19
 
19
20
  const MessageTimingDisplay: FC = () => {
@@ -39,7 +40,7 @@ Place it inside `MessagePrimitive.Root`, typically near the action bar:
39
40
  const AssistantMessage: FC = () => {
40
41
  return (
41
42
  <MessagePrimitive.Root>
42
- <MessagePrimitive.Parts components={{ ... }} />
43
+ <MessagePrimitive.Parts>{...}</MessagePrimitive.Parts>
43
44
  <ActionBarPrimitive.Root>
44
45
  <ActionBarPrimitive.Copy />
45
46
  <ActionBarPrimitive.Reload />
@@ -0,0 +1,173 @@
1
+ ---
2
+ title: Multi-Agent
3
+ description: Render sub-agent conversations inside tool call UIs.
4
+ ---
5
+
6
+ In a multi-agent (orchestrator) architecture, a main agent invokes sub-agents via tool calls. Each sub-agent may produce its own conversation (user/assistant messages, tool calls, etc.). assistant-ui supports rendering these nested conversations using the `MessagePartPrimitive.Messages` primitive.
7
+
8
+ ## Overview
9
+
10
+ When a tool call includes a `messages` field (`ToolCallMessagePart.messages`), it represents a sub-agent's conversation history. `MessagePartPrimitive.Messages` reads this field from the current tool call part and renders it as a nested thread.
11
+
12
+ Key behaviors:
13
+
14
+ - **Scope inheritance** — Parent tool UI registrations are available in sub-agent messages. A `makeAssistantToolUI` registered at the top level works inside sub-agent conversations too.
15
+ - **Recursive** — Sub-agent messages can contain tool calls that themselves have nested messages. Just use `MessagePartPrimitive.Messages` again.
16
+ - **Read-only** — Sub-agent messages are rendered in a readonly context. No editing, branching, or composing.
17
+
18
+ ## Quick Start
19
+
20
+ <Steps>
21
+ <Step>
22
+
23
+ ### Register a Tool UI for the Sub-Agent
24
+
25
+ ```tsx
26
+ import {
27
+ makeAssistantToolUI,
28
+ MessagePartPrimitive,
29
+ } from "@assistant-ui/react";
30
+
31
+ const ResearchAgentToolUI = makeAssistantToolUI({
32
+ toolName: "invoke_researcher",
33
+ render: ({ args, status }) => (
34
+ <div className="my-2 rounded-lg border p-4">
35
+ <div className="mb-2 text-sm font-medium text-gray-500">
36
+ Researcher Agent {status.type === "running" && "(working...)"}
37
+ </div>
38
+ <MessagePartPrimitive.Messages>
39
+ {({ message }) => {
40
+ if (message.role === "user") return <MyUserMessage />;
41
+ return <MyAssistantMessage />;
42
+ }}
43
+ </MessagePartPrimitive.Messages>
44
+ </div>
45
+ ),
46
+ });
47
+ ```
48
+
49
+ </Step>
50
+ <Step>
51
+
52
+ ### Provide the Messages from the Backend
53
+
54
+ Your backend must populate the `messages` field on the tool call result. For example, with the AI SDK:
55
+
56
+ ```ts title="api/chat/route.ts"
57
+ tools: {
58
+ invoke_researcher: tool({
59
+ description: "Invoke the researcher sub-agent",
60
+ parameters: z.object({ query: z.string() }),
61
+ execute: async ({ query }) => {
62
+ const subAgentMessages = await runResearcherAgent(query);
63
+ return {
64
+ answer: subAgentMessages.at(-1)?.content,
65
+ // The messages field is picked up by assistant-ui
66
+ messages: subAgentMessages,
67
+ };
68
+ },
69
+ }),
70
+ },
71
+ ```
72
+
73
+ <Callout type="info">
74
+ The exact mechanism for populating `messages` depends on your backend
75
+ framework. The key requirement is that the tool result's corresponding
76
+ `ToolCallMessagePart` includes a `messages` array of `ThreadMessage` objects.
77
+ </Callout>
78
+
79
+ </Step>
80
+ <Step>
81
+
82
+ ### Register the Tool UI Component
83
+
84
+ ```tsx
85
+ function App() {
86
+ return (
87
+ <AssistantRuntimeProvider runtime={runtime}>
88
+ <Thread />
89
+ <ResearchAgentToolUI />
90
+ </AssistantRuntimeProvider>
91
+ );
92
+ }
93
+ ```
94
+
95
+ </Step>
96
+ </Steps>
97
+
98
+ ## Recursive Sub-Agents
99
+
100
+ If a sub-agent's tool calls also have nested messages, the same pattern applies recursively:
101
+
102
+ ```tsx
103
+ const OuterAgentToolUI = makeAssistantToolUI({
104
+ toolName: "invoke_planner",
105
+ render: () => (
106
+ <div className="rounded border p-3">
107
+ <h4>Planner Agent</h4>
108
+ <MessagePartPrimitive.Messages>
109
+ {({ message }) => {
110
+ if (message.role === "user") return <MyUserMessage />;
111
+ return (
112
+ <MessagePrimitive.Parts>
113
+ {({ part }) => {
114
+ if (part.type === "text") return <MyText />;
115
+ if (part.type === "tool-call" && part.toolName === "invoke_researcher") return (
116
+ <div className="ml-4 rounded border p-3">
117
+ <h5>Researcher Agent</h5>
118
+ {/* Nested sub-agent renders recursively */}
119
+ <MessagePartPrimitive.Messages>
120
+ {({ message }) => {
121
+ if (message.role === "user") return <MyUserMessage />;
122
+ return <MyAssistantMessage />;
123
+ }}
124
+ </MessagePartPrimitive.Messages>
125
+ </div>
126
+ );
127
+ if (part.type === "tool-call") return <MyToolFallback {...part} />;
128
+ return null;
129
+ }}
130
+ </MessagePrimitive.Parts>
131
+ );
132
+ }}
133
+ </MessagePartPrimitive.Messages>
134
+ </div>
135
+ ),
136
+ });
137
+ ```
138
+
139
+ ## ReadonlyThreadProvider
140
+
141
+ For advanced use cases where you have a `ThreadMessage[]` array and want to render it as a thread outside of a tool call context, use `ReadonlyThreadProvider` directly:
142
+
143
+ ```tsx
144
+ import {
145
+ ReadonlyThreadProvider,
146
+ ThreadPrimitive,
147
+ type ThreadMessage,
148
+ } from "@assistant-ui/react";
149
+
150
+ function SubConversation({
151
+ messages,
152
+ }: {
153
+ messages: readonly ThreadMessage[];
154
+ }) {
155
+ return (
156
+ <ReadonlyThreadProvider messages={messages}>
157
+ <ThreadPrimitive.Messages>
158
+ {({ message }) => {
159
+ if (message.role === "user") return <MyUserMessage />;
160
+ return <MyAssistantMessage />;
161
+ }}
162
+ </ThreadPrimitive.Messages>
163
+ </ReadonlyThreadProvider>
164
+ );
165
+ }
166
+ ```
167
+
168
+ `ReadonlyThreadProvider` inherits the parent's tool UI registrations and model context through scope inheritance.
169
+
170
+ ## Related
171
+
172
+ - [Generative UI](/docs/guides/tool-ui) — Creating tool call UIs
173
+ - [MessagePartPrimitive](/docs/api-reference/primitives/message-part) — API reference for message part primitives