Insert content
Build a workflow that replaces the current selection with AI-generated content on the server.
See the source code on GitHub.
Prerequisites
This guide assumes you already configured JWT authentication for the Server AI Toolkit as shown in the AI agent chatbot guide.
Reuse the same session across read and execute
The selection read step returns a sessionId. Send that same sessionId with the execute request
so the server can reject stale edits when the selected content changed after the AI read it.
1. Read the current selection from the AI Server
The insert-content workflow starts by reading the selected content from a collaborative document. Call:
POST /v3/ai/toolkit/read/read-selection
const readResponse = await fetch(`${apiBaseUrl}/toolkit/read/read-selection`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${jwtToken}`,
'X-App-Id': appId,
},
body: JSON.stringify({
schemaAwarenessData,
range,
sessionId,
format: 'shorthand',
reviewOptions: {
mode: 'disabled',
},
experimental_documentOptions: {
documentId,
userId: 'ai-assistant',
},
}),
})
const readResult = await readResponse.json()
if (readResult.output.isEmpty) {
throw new Error('No selection available for insert-content workflow')
}2. Get the workflow definition and build the prompt
Fetch the workflow definition and the schema awareness prompt, then combine them in the system prompt. The workflow definition comes from:
POST /v3/ai/toolkit/workflows/insert-content
const workflowResponse = await fetch(`${apiBaseUrl}/toolkit/workflows/insert-content`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${jwtToken}`,
'X-App-Id': appId,
},
body: JSON.stringify({
format: 'shorthand',
}),
})
const workflow = await workflowResponse.json()
const schemaResponse = await fetch(`${apiBaseUrl}/toolkit/schema-awareness-prompt`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${jwtToken}`,
'X-App-Id': appId,
},
body: JSON.stringify({
schemaAwarenessData,
}),
})
const { prompt: schemaAwarenessPrompt } = await schemaResponse.json()
const result = streamText({
model,
system: `${workflow.systemPrompt}\n\n${schemaAwarenessPrompt}`,
prompt: JSON.stringify({
task,
replace: readResult.output.content,
context: readResult.output.prompt,
}),
output: Output.object({ schema: z.fromJSONSchema(workflow.outputSchema) }),
})
const workflowOutput = await result.outputUsing format: 'shorthand' keeps the model output compact while still validating it with a
structured-output schema.
3. Execute the workflow and get the inserted range
Pass the generated shorthand string to the execute endpoint. The response includes the new range of the inserted content. Call:
POST /v3/ai/toolkit/execute-workflow/insert-content
const executeResponse = await fetch(`${apiBaseUrl}/toolkit/execute-workflow/insert-content`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${jwtToken}`,
'X-App-Id': appId,
},
body: JSON.stringify({
schemaAwarenessData,
format: 'shorthand',
input: workflowOutput.content,
range,
sessionId: readResult.sessionId,
reviewOptions: {
mode: 'disabled',
},
experimental_documentOptions: {
documentId,
userId: 'ai-assistant',
},
}),
})
const executeResult = await executeResponse.json()4. Restore the selection on the client
After the collaborative document updates, reselect the inserted content so the user can keep working with the new text.
const result: {
sessionId: string
range: { from: number; to: number } | null
} = await response.json()
if (result.range) {
editor.commands.focus()
editor.commands.setTextSelection(result.range)
}Tracked changes
Tracked-changes support for the insert-content workflow is coming soon.
End result
The finished demo replaces the current selection and keeps the new content selected:
See the source code on GitHub.
Next steps
- Review the Server AI Toolkit REST API reference
- See the REST API request details