Justified changes

Continuation from the review changes guide

This guide continues the review changes guide. Read it first.

The AI Toolkit can instruct the AI to include justifications for each change it makes to the document. This allows you to show users why a change was made, not just what changed.

See the source code on GitHub.

Enable justified changes

To enable justified changes, pass the operationMeta option to toolDefinitions() on the server. The string you provide becomes the description of the meta field in the tool schema, which the AI uses to understand what kind of justification to provide.

// api/route.ts
const agent = new ToolLoopAgent({
  model,
  instructions: '...',
  tools: toolDefinitions({
    operationMeta: 'Brief explanation of why this change improves the text',
  }),
})

Show justifications as tooltips

When a suggestion is selected, you can display the justification as a tooltip using the Floating UI library.

Install Floating UI

npm install @floating-ui/dom

Access the justification in renderDecorations

The justification is available in suggestion.metadata?.operationMeta. Use the isSelected option to only show the tooltip when the suggestion is focused.

import { computePosition, flip, offset, shift } from '@floating-ui/dom'

const result = toolkit.executeTool({
  toolName,
  input,
  reviewOptions: {
    mode: 'preview',
    displayOptions: {
      renderDecorations(options) {
        const decorations = [...options.defaultRenderDecorations()]

        // Add Accept and Reject buttons (same as the review changes guide)
        // ...

        // Show tooltip when selected and justification exists
        const justification = options.suggestion.metadata?.operationMeta
        if (options.isSelected && justification) {
          decorations.push(
            Decoration.widget(options.range.to, () => {
              const container = document.createElement('span')
              container.style.position = 'relative'

              const tooltip = document.createElement('div')
              tooltip.textContent = justification as string
              tooltip.style.cssText =
                'position:absolute;background:white;color:#1f2937;padding:8px 12px;border-radius:8px;border:1px solid #e5e7eb;font-size:13px;max-width:400px;width:max-content;z-index:50;pointer-events:none;box-shadow:0 4px 12px rgba(0,0,0,0.08),0 1px 3px rgba(0,0,0,0.06);'
              container.appendChild(tooltip)

              requestAnimationFrame(() => {
                computePosition(container, tooltip, {
                  placement: 'top',
                  middleware: [offset(8), flip(), shift({ padding: 8 })],
                }).then(({ x, y }) => {
                  tooltip.style.left = `${x}px`
                  tooltip.style.top = `${y}px`
                })
              })

              return container
            }),
          )
        }

        return decorations
      },
    },
  },
})

End result

With these changes, AI-generated suggestions include floating tooltips that explain the rationale behind each change:

See the source code on GitHub.