Caret’s AI agents can propose targeted edits to your document — a rewrite of a paragraph, a completion of an unfinished sentence, or a structural reorganisation. These proposals are called suggestions. Rather than writing changes directly into the database, the AI emits a suggestion record inDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/arrozet/caret/llms.txt
Use this file to discover all available pages before exploring further.
proposed state. The frontend renders it as inline ghost text inside the Tiptap editor; the user then accepts or rejects it. Only if the user accepts does the change flow through a Tiptap transaction, keeping the Y.js collaborative document state consistent for all connected collaborators.
Three endpoints manage the full suggestion lifecycle: POST /api/v1/ai/suggestions to create a suggestion, GET /api/v1/ai/suggestions to list suggestions for a conversation, and PATCH /api/v1/ai/suggestions/{suggestion_id}/status to advance a suggestion through its lifecycle. All routes are proxied through the API Gateway at https://api.caret.page/api/v1/ai/... and require a valid Supabase JWT.
Suggestion lifecycle
Every suggestion starts in theproposed state the moment it is created by the AI service. From there it can move to one of three terminal states:
| Status | Meaning |
|---|---|
proposed | The AI has generated a suggestion and it is awaiting the user’s decision. Ghost text is visible in the editor. |
applied | The user accepted the suggestion. The frontend has already applied the change via a Tiptap transaction; this PATCH call records that outcome. |
dismissed | The user rejected the suggestion. The ghost text is removed from the editor and the suggestion is archived. |
superseded | A newer suggestion for the same document position was generated before the user acted on this one. The old suggestion is automatically retired. |
The AI service never writes directly to document content tables. All accepted suggestions reach the document exclusively through Tiptap editor transactions, which Y.js then propagates to every collaborator in real time. This guarantees that the CRDT document state is always the source of truth — the suggestion record in the database is metadata only.
How suggestions surface in the editor
- The user sends a message to the AI via
POST /api/v1/ai/conversations/{conversation_id}/streamwithagent_type: "general". - The general agent analyses the document and, when it decides to propose an edit, emits a
document_changeSSE event containing aDocumentChangePayloadwithproposed_text,original_text, andoperation. - After the stream ends, the AI service persists the suggestion to the
ai_suggestionstable inproposedstate and populatessuggestion_idon the final event. - The frontend displays the diff as inline ghost text using Tiptap’s decoration system.
- The user clicks Accept or Reject in the editor UI.
- Accept: The frontend applies the change as a Tiptap transaction → Y.js syncs it to all collaborators → frontend calls
PATCH …/statuswith{ "status": "applied" }. - Reject: The frontend discards the ghost text → calls
PATCH …/statuswith{ "status": "dismissed" }.
- Accept: The frontend applies the change as a Tiptap transaction → Y.js syncs it to all collaborators → frontend calls
POST /api/v1/ai/suggestions
Create a new suggestion record inproposed state. In normal usage the AI service creates suggestion records automatically as part of the stream flow (triggered by a document_change SSE event). This endpoint is available for cases where the frontend needs to persist a suggestion independently.
Request body
UUID of the parent conversation.
UUID of the document this suggestion targets. The authenticated user must have access to this document.
The full replacement text proposed by the AI. Minimum 1 character.
UUID of the assistant message that generated this suggestion. Optional.
The document text that was present at the target position when the suggestion was generated.
null for insertion-only suggestions.Character offset of the start of the targeted range.
null for whole-document suggestions.Character offset of the end of the targeted range.
null for whole-document suggestions.Response — 201 Created
Returns the full suggestion object in proposed state. The response schema is identical to the PATCH response documented below.
Error responses
| Status | Condition |
|---|---|
404 Not Found | The document_id does not exist. |
403 Forbidden | The authenticated user does not have access to the document. |
GET /api/v1/ai/suggestions
List all suggestions for a conversation, optionally filtered by status.Query parameters
UUID of the conversation whose suggestions to list.
Optional lifecycle status filter. When omitted all suggestions are returned. One of
proposed, applied, dismissed, superseded.Response — 200 OK
Returns a JSON array of suggestion objects. Each object has the same fields as the PATCH response documented below.
PATCH /api/v1/ai/suggestions//status
Transition a suggestion to its next lifecycle state. The authenticated user must have access to the document the suggestion belongs to; the service validates document access before applying the status change.Path parameters
UUID of the suggestion to update.
Request body
The new lifecycle status. Must be one of:
applied— the user accepted the suggestion and it has been committed to the document.dismissed— the user rejected the suggestion.superseded— a newer suggestion has replaced this one (typically set programmatically by the frontend when a second suggestion arrives for the same position).
Response — 200 OK
Returns the full updated suggestion object.
UUID of the suggestion.
UUID of the parent conversation.
UUID of the document this suggestion targets.
UUID of the assistant message that generated this suggestion, or
null.Updated lifecycle status:
applied, dismissed, or superseded.The document text that was present at the position when the suggestion was generated, or
null for insertion-only suggestions.The full replacement text proposed by the AI.
Character offset of the start of the targeted range in the document, or
null for whole-document suggestions.Character offset of the end of the targeted range in the document, or
null for whole-document suggestions.ISO 8601 creation timestamp.
ISO 8601 last-updated timestamp (reflects the status change).
Error responses
| Status | Condition |
|---|---|
404 Not Found | The suggestion UUID does not exist. |
403 Forbidden | The authenticated user does not have access to the document the suggestion belongs to. |