Overview
The Suggestions API adds suggestion mode to any input, editor, or custom component in your app. When it’s on, edits from a human (or an AI agent) aren’t written straight to your data. They’re captured as proposed changes that a reviewer accepts or rejects from the comment dialog, diff-style, like Google Docs suggestions. On accept, your app applies the change. You mark any DOM element as a suggestion target with a single attribute. The SDK captures the before and after values, saves each edit as aSuggestion, and shows accept/reject buttons on the comment dialog.
The accept/reject UI renders on the Velt comment dialog, so your app needs Velt Comments set up. That’s where reviewers act on a suggestion.
How it works
- You enable suggestion mode. The SDK starts watching every element tagged with
data-velt-suggestion-target="<targetId>", including elements added to the DOM later. - A user focuses a target. The SDK snapshots the target’s current value as the
oldValuefor that edit session. - A user edits and commits the change (for example, by clicking away from a text field). The SDK reads the new value, compares it to the snapshot, and creates a pending
Suggestiononly if they differ. - A reviewer accepts or rejects from the comment dialog. The outcome is emitted on the comment element as the
suggestionAccepted/suggestionRejectedevents. - Your app applies the change. Your
suggestionAcceptedhandler readscommentAnnotation.suggestion.newValueand writes it into your own state or backend.
Properties
- A suggestion is a regular comment annotation with
type: "suggestion"and a populatedsuggestionfield. There is no separate suggestions data store. - Suggestion mode is global for the current user and not persisted. A page reload returns to normal editing until you enable it again.
- An edit is committed when the user finishes it, not on every keystroke. Text-like inputs (text, number, date, textarea, contenteditable) commit when the field loses focus (
focusout), so each focus session produces at most one suggestion. Dropdowns, checkboxes, and radios commit onchange, since picking a value is the whole edit. - Unchanged values never create suggestions. Focusing and blurring without editing is ignored, and
commitSuggestionrejects anewValuethat’s identical to the old value. - Events come from two elements: accept/reject outcomes are emitted on the comment element, while the rest of the lifecycle (
suggestionCreated,suggestionStale,targetEditStart,targetEditCommit) is emitted on the SuggestionElement. See Event Subscription. - The SDK never mutates your data. It captures intent, orchestrates review, and persists the outcome. Applying the change is your code’s job.
- Drift detection is best-effort. On accept, if a getter is registered, the live value is compared against
oldValue; a mismatch setsdriftDetected: trueon the suggestion. v1 records the flag; a future release will surface a confirmation prompt. - Stale wins over drift. If the target DOM node can’t be resolved at accept time, the suggestion transitions to
staleimmediately and drift detection is skipped.
APIs
Frontend APIs
Follow these steps to add suggestions to your app. Steps 1 and 2 are the minimum to capture suggestions; step 3 controls how edits become suggestions, step 4 applies them once accepted, and step 5 lets you query suggestions for your own UI. All Suggestions methods live on a singleSuggestionElement instance. Get it once and reuse it. In React, the hooks shown below wrap it for you, so you rarely need the element directly:
- React / Next.js
- Other Frameworks
1. Define Suggestion Targets
Add thedata-velt-suggestion-target="<targetId>" attribute to any element you want to track. The targetId is an ID you own and should stay stable, like the ID of the record the input edits. Don’t generate a random ID on each render: if the targetId changes, the SDK can’t match suggestions back to the element.
- React / Next.js
- Other Frameworks
registerTarget? Usually not. For a single input, the SDK reads the value on its own: it checks for a registered getter first, then the form value (.value / .checked), then textContent. So a plain <input> needs no registerTarget call. You only need it when one target covers several inputs at once, like a table row with a qty field and a price field. There’s no single .value to read in that case, so you provide a getter function that returns the whole object:
- React / Next.js
- Other Frameworks
registerTarget() doesn’t return an unsubscribe function. To remove a registration, call unregisterTarget(targetId).2. Enable Suggestion Mode
Nothing is captured until you turn suggestion mode on, typically from a “Suggest changes” toggle in your toolbar. It applies to the whole page for the current user and resets on page reload, so enable it again after a refresh. Pass an optionalEnableSuggestionModeConfig to control how edits become suggestions (see step 3).
- React / Next.js
- Other Frameworks
- React / Next.js
- Other Frameworks
3. Capture Edits as Suggestions
When a user finishes an edit, you decide how it becomes a suggestion. There are three ways, from simplest to most control. Use one per target; only one of them handles any given edit. Option 1: Auto-commit withonTargetEditCommit (simplest)
Pass onTargetEditCommit when you enable suggestion mode. The SDK calls it with the old and new values every time a user finishes an edit. Return an object and the SDK creates the suggestion right away, using your summary and metadata. This is the path most apps want. (onTargetEditStart fires when editing begins; it’s informational in v1 and its return value is reserved for future use.)
- React / Next.js
- Other Frameworks
targetEditCommit event
If you skip onTargetEditCommit, subscribe to the targetEditCommit event instead. The event gives you the edit details plus a commitSuggestion function that’s already tied to that edit. Call it to create the suggestion (you can override summary / metadata), or don’t call it to discard the edit. Nothing is created until you call it.
- React / Next.js
- Other Frameworks
startSuggestion / commitSuggestion
When there’s no input for the SDK to watch (a custom widget, a canvas element, or an “AI proposes a change” button), create the suggestion yourself. Call startSuggestion(targetId) to capture the current value as oldValue, then commitSuggestion(config) with the newValue to create it.
- React / Next.js
- Other Frameworks
commitSuggestion only works while suggestion mode is on and the targetId is known to the SDK (tagged in the DOM or registered via registerTarget). It also creates nothing when newValue is identical to the captured oldValue.4. Apply Accepted Suggestions
This is the step you can’t skip. When a reviewer clicks Accept or Reject on the comment dialog, the SDK updates the suggestion’s status but does not change your data. Listen for thesuggestionAccepted event on the comment element (not the SuggestionElement), read commentAnnotation.suggestion.newValue, and write it to your state or backend yourself.
- React / Next.js
- Other Frameworks
If the target element is no longer on the page when a reviewer accepts, the suggestion is marked
stale instead of accepted. Listen for that on the SuggestionElement with useSuggestionEventCallback('suggestionStale') (React) or suggestionElement.on('suggestionStale') (other frameworks).5. Get Suggestions
Beyond the built-in accept/reject buttons, you’ll often want to render your own indicators: a “1 pending change” badge on a row, a custom review panel, or a count in a toolbar. Query suggestions reactively with an optionalSuggestionGetSuggestionsFilter, or fetch the single pending suggestion for a target.
- React / Next.js
- Other Frameworks
Backend APIs
Suggestions are stored as comment annotations, so you manage them from your backend with the same Comment Annotations REST APIs.Add Suggestions
- Add agent-generated suggestions using the Add Comment Annotations REST API with
type: "suggestion"and anagentblock on the root comment. Learn more - See the Agent Comments guide for the full walkthrough of agent findings.
Get Suggestions
- Get suggestion annotations using the Get Comment Annotations REST API. Use the
agentSuggestionsfilter to return only fresh (unaccepted) agent suggestions. Learn more
Update and Delete Suggestions
- Update annotation-level fields using the Update Comment Annotations REST API. Learn more
- Delete suggestion threads using the Delete Comment Annotations REST API. Learn more
Event Subscription
on
Subscribe to Suggestion Events. Events come from two elements: review outcomes are emitted on the comment element, and the rest of the lifecycle is emitted on the SuggestionElement. Here is the list of events you can subscribe to and the event objects you will receive.- React / Next.js
- Other Frameworks
Lifecycle
A suggestion moves forward through these states (seeSuggestionStatus):
Data model
Suggestions are stored asCommentAnnotation objects with type === 'suggestion' and a populated suggestion field. The full type hierarchy lives in the Suggestions section of the Data Models reference.
