Skip to content

Commit c80b85e

Browse files
authored
docs(ai-chat): atomic onTurnComplete writes + Anthropic prose (#3693)
## Summary Three post-merge fixes for the AI Agents docs (#3226), all caught by review after merge. ## Fixes - **`onTurnComplete` examples now use `db.$transaction`** — both the Database persistence "Complete example" and the Lifecycle hooks reference example were doing two separate `await` calls (`db.chat.update` then `db.chatSession.upsert`). That's the exact non-atomic pattern the warning earlier on the persistence page calls out as ❌: a refresh between the two writes reads a stale `lastEventId` and duplicates the assistant message on resume. Both examples now use the recommended atomic form. - **Background injection self-review prose aligned with the code** — the prose said "gpt-4o-mini" but the example above it had been swapped to `claude-haiku-4-5`. The Anthropic-sweep script only touched code blocks; this prose line wasn't picked up. ## Test plan - [x] Both updated examples use `db.$transaction([...])` - [x] Prose matches the model used in the code block - [ ] Mintlify deployment passes
1 parent 80bb600 commit c80b85e

3 files changed

Lines changed: 26 additions & 20 deletions

File tree

docs/ai-chat/background-injection.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ export const myChat = chat.agent({
154154
});
155155
```
156156

157-
The self-review runs on `gpt-4o-mini` (fast, cheap) in the background. If the user sends another message before it completes, the coaching is still injected — `chat.inject()` persists across the idle wait.
157+
The self-review runs on `claude-haiku-4-5` (fast, cheap) in the background. If the user sends another message before it completes, the coaching is still injected — `chat.inject()` persists across the idle wait.
158158

159159
## Other use cases
160160

docs/ai-chat/lifecycle-hooks.mdx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -412,15 +412,18 @@ Fires after each turn completes, after the response is captured and the stream i
412412
export const myChat = chat.agent({
413413
id: "my-chat",
414414
onTurnComplete: async ({ chatId, uiMessages, runId, chatAccessToken, lastEventId }) => {
415-
await db.chat.update({
416-
where: { id: chatId },
417-
data: { messages: uiMessages },
418-
});
419-
await db.chatSession.upsert({
420-
where: { id: chatId },
421-
create: { id: chatId, runId, publicAccessToken: chatAccessToken, lastEventId },
422-
update: { runId, publicAccessToken: chatAccessToken, lastEventId },
423-
});
415+
// Atomic write — see Database persistence for the race-condition rationale
416+
await db.$transaction([
417+
db.chat.update({
418+
where: { id: chatId },
419+
data: { messages: uiMessages },
420+
}),
421+
db.chatSession.upsert({
422+
where: { id: chatId },
423+
create: { id: chatId, runId, publicAccessToken: chatAccessToken, lastEventId },
424+
update: { runId, publicAccessToken: chatAccessToken, lastEventId },
425+
}),
426+
]);
424427
},
425428
run: async ({ messages, signal }) => {
426429
return streamText({ model: anthropic("claude-sonnet-4-5"), messages, abortSignal: signal });

docs/ai-chat/patterns/database-persistence.mdx

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -258,16 +258,19 @@ export const myChat = chat.agent({
258258
});
259259
},
260260
onTurnComplete: async ({ chatId, uiMessages, runId, chatAccessToken, lastEventId }) => {
261-
// Persist assistant response + stream position
262-
await db.chat.update({
263-
where: { id: chatId },
264-
data: { messages: uiMessages },
265-
});
266-
await db.chatSession.upsert({
267-
where: { id: chatId },
268-
create: { id: chatId, runId, publicAccessToken: chatAccessToken, lastEventId },
269-
update: { runId, publicAccessToken: chatAccessToken, lastEventId },
270-
});
261+
// Persist assistant response + stream position atomically — see the
262+
// race-condition warning earlier on this page.
263+
await db.$transaction([
264+
db.chat.update({
265+
where: { id: chatId },
266+
data: { messages: uiMessages },
267+
}),
268+
db.chatSession.upsert({
269+
where: { id: chatId },
270+
create: { id: chatId, runId, publicAccessToken: chatAccessToken, lastEventId },
271+
update: { runId, publicAccessToken: chatAccessToken, lastEventId },
272+
}),
273+
]);
271274
},
272275
run: async ({ messages, signal }) => {
273276
return streamText({

0 commit comments

Comments
 (0)