You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
(per-message). See [Client data and metadata](/ai-chat/frontend#client-data-and-metadata).
149
149
</Tip>
150
150
151
+
#### onValidateMessages
152
+
153
+
Validate or transform incoming `UIMessage[]` before they are converted to model messages. Fires once per turn with the raw messages from the wire payload (after cleanup of aborted tool parts), **before** accumulation and `toModelMessages()`.
154
+
155
+
Return the validated messages array. Throw to abort the turn with an error.
156
+
157
+
This is the right place to call the AI SDK's [`validateUIMessages`](https://ai-sdk.dev/docs/ai-sdk-ui/chatbot-message-persistence#validating-messages-on-the-server) to catch malformed messages from storage or untrusted input before they reach the model — especially useful when persisting conversations to a database, where tool schemas may drift between deploys.
returnstreamText({ model: openai("gpt-4o"), messages, tools: chatTools, abortSignal: signal });
176
+
},
177
+
});
178
+
```
179
+
180
+
<Note>
181
+
`onValidateMessages` fires **before**`onTurnStart` and message accumulation. If you need to validate messages loaded from a database, do the loading in `onChatStart` or `onPreload` and let `onValidateMessages` validate the full incoming set each turn.
182
+
</Note>
183
+
151
184
#### onTurnStart
152
185
153
186
Fires at the start of every turn, after message accumulation and `onChatStart` (turn 0), but **before**`run()` executes. Use it to persist messages before streaming begins — so a mid-stream page refresh still shows the user's message.
Copy file name to clipboardExpand all lines: docs/ai-chat/reference.mdx
+16Lines changed: 16 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,6 +15,7 @@ Options for `chat.agent()`.
15
15
|`clientDataSchema`|`TaskSchema`| — | Schema for validating and typing `clientData`|
16
16
|`onPreload`|`(event: PreloadEvent) => Promise<void> \| void`| — | Fires on preloaded runs before the first message |
17
17
|`onChatStart`|`(event: ChatStartEvent) => Promise<void> \| void`| — | Fires on turn 0 before `run()`|
18
+
|`onValidateMessages`|`(event: ValidateMessagesEvent) => UIMessage[] \| Promise<UIMessage[]>`| — | Validate/transform UIMessages before model conversion. See [onValidateMessages](/ai-chat/backend#onvalidatemessages)|
18
19
|`onTurnStart`|`(event: TurnStartEvent) => Promise<void> \| void`| — | Fires every turn before `run()`|
19
20
|`onBeforeTurnComplete`|`(event: BeforeTurnCompleteEvent) => Promise<void> \| void`| — | Fires after response but before stream closes. Includes `writer`. |
20
21
|`onTurnComplete`|`(event: TurnCompleteEvent) => Promise<void> \| void`| — | Fires after each turn completes (stream closed) |
@@ -39,6 +40,10 @@ Plus all standard [TaskOptions](/tasks/overview) — `retry`, `queue`, `machine`
39
40
40
41
All **`chat.agent`** lifecycle events (**`onPreload`**, **`onChatStart`**, **`onTurnStart`**, **`onBeforeTurnComplete`**, **`onTurnComplete`**, **`onCompacted`**) and the object passed to **`run`** include **`ctx`**: the same **`TaskRunContext`** shape as the `ctx` in `task({ run: (payload, { ctx }) => ... })`.
41
42
43
+
<Note>
44
+
**`onValidateMessages`** does not include `ctx` — it fires before message accumulation and is designed for pure validation/transformation of incoming messages.
45
+
</Note>
46
+
42
47
Use **`ctx`** for run metadata, tags, parent links, or any API that needs the full run record. The chat-specific string **`runId`** on events is always **`ctx.run.id`**; both are provided for convenience.
43
48
44
49
```ts
@@ -100,6 +105,17 @@ Passed to the `onChatStart` callback.
100
105
|`preloaded`|`boolean`| Whether this run was preloaded before the first message |
101
106
|`writer`|[`ChatWriter`](#chatwriter)| Stream writer for custom chunks. Lazy — no overhead if unused. |
0 commit comments