AI-powered rich text editor custom component for Retool

John Miniadis

AI-powered editing

Block-level transforms

Open source

tl;dr here's the repository

This Retool custom component brings block-level AI actions into a rich text editor built on editor.js. Operators can rewrite a paragraph, summarize a section, or draft a reply from ticket context all from inside a single Retool app, without switching tools or copying text to an external AI interface.

We built it for a client's internal support tool and walked through it live at Retool's Build Together session. The component is open source and documented.

If you're looking for the base Editor.js component without AI, that's in our component library.

Why Retool's stock text area isn't enough for block-level AI

Retool's text area outputs a string. That works for simple inputs, but it creates two problems once AI enters the picture.

The first is granularity. When an operator wants to rewrite one paragraph of a draft reply, the text area has no concept of that block. You'd need to write your own selection and parsing logic, all of it outside Retool's low-code surface.

The second is structured output. Once the operator is done, the data needs to flow into queries, tables, and workflow nodes without a parsing step. A markdown or HTML blob is the wrong shape for that.

We needed a rich text editor that outputs structured JSON per block, and lets AI act on individual blocks without touching the rest. The base Editor.js component already solved the structured output problem. This component adds the AI layer on top.

What this Retool custom component does

The AI Editor is a Retool custom component built on editor.js. Every block, wether paragraph, heading, list is its own JSON object. Two AI actions live in each block's settings panel: Rewrite and Summarize. A slash-menu action handles Draft reply, inserting a new block grounded in whatever app state you pass to the query.

All three AI actions route through a Retool JavaScript query, not through the component itself. The component fires an event; the query reads the context, calls the LLM, and writes the response back. That means the prompt, the model, and the context stay fully configurable in Retool with no component code to touch, and you can wire it to any LLM endpoint: Retool AI, OpenAI, Anthropic, or your own.

[VIDEO EMBED Build Together session]

Features

  • Block-level AI transforms: Rewrite and Summarize actions on every block via the three-dot settings panel. Each fires a Retool event with the block's content and type; the LLM response replaces that block in place via editor.blocks.update(id, data).

  • Slash-menu Draft reply: Typing / opens the slash menu with a Draft reply entry. Inserts a placeholder block and fires aiTransformRequest with transformScope: 'insert'. Grounds the draft from app state in your query, not block content.

  • LLM-agnostic: Wire to any endpoint via a Retool JavaScript query. Retool AI, OpenAI, Anthropic, or custom so no component changes needed.

  • Structured JSON output: editorData exposes the full editor.js block structure in real time. Bind directly to queries, tables, or workflow nodes with {{ AIEditor1.editorData.blocks }}.

  • Retool-native event model: Two events: aiTransformRequest (fires when an operator triggers any AI action) and editorChange (fires on content change, debounced 400ms).

  • Isolated Retool surface: All Retool-specific wiring lives in one file (index.tsx). Swap a few hooks and you have a standalone React component.

  • TypeScript throughout: Hooks, refs, CSS modules. Full React surface, no sandboxing.

How the Retool custom component event model works

Retool custom component events carry no payload. The pattern is: the component sets state properties first, then fires the event. Your query reads the state.




When the query has a result, it writes back:

The salt is String.fromCharCode(8203) a zero-width space that forces Retool to detect a value change even when the AI returns identical text twice in a row.

Component properties

Output: component writes, your app reads

 


Property

 

 


Type

 

 


Description

 

 


editorData

 

 


object

 

 


Full editor.js JSON, updated on every change (debounced 400ms)

 

 


transformBlockContent

 

 


string

 

 


Text of the block being transformed (empty for insert scope)

 

 


transformType

 

 


string

 

 


summarize, rewrite, or draft

 

 


transformBlockId

 

 


string

 

 


editor.js id of the block being transformed or replaced

 

 


transformScope

 

 


string

 

 


block (tune-menu) or insert (slash-menu Draft reply)

 

 

 

Input: your app writes, component reads

 


Property

 

 


Type

 

 


Description

 

 


transformResponse

 

 


string

 

 


LLM response. Bind to your query result.

 

 


readOnly

 

 


boolean

 

 


Toggle read-only mode.

 

 

Installation & usage

Clone the repository




Install dependencies

Log in to Retool

You'll need an API access token with read and write scopes for Custom Component Libraries.

Start development mode

This syncs local changes to Retool on every save. Open any Retool app and drag the AIEditor component onto the canvas.

Deploy

Once deployed, pin your app to the published version in Custom Component settings. Anyone in the org can use the component from the component panel.

Wiring up the AI query

Create a JavaScript query that calls your LLM endpoint. Switch on {{ AIEditor1.transformScope }} to handle block transforms vs. draft inserts, then on {{ AIEditor1.transformType }} for the action. For block-scope transforms, use {{ AIEditor1.transformBlockContent }} as user content. Reference any other app state directly in the prompt, the query runs in the full Retool app scope.

Add an event handler on the AIEditor1 component:

  • Event: aiTransformRequest

  • Action: Trigger your transform query

  • Then: Set AIEditor1.transformResponse to {{ yourTransformQuery.data }}

The component routes the response to the correct block internally; your query doesn't need to track transformBlockId.

Limitations

  • Gets heavy past ~50 blocks. Right for replies, drafts, and short-form content, not for long documents.

  • No collaborative editing. editor.js doesn't support it natively.

  • No streaming on AI responses. The editor waits for the full response, showing a "Drafting reply..." state while the query runs.

Get involved

The component is open source and documented. If you're building AI-assisted workflows in Retool such as support tools, sales ops, content review, the repo is a good starting point.

We're always open to pull requests, feature ideas, or new use cases. If you're thinking about what else is possible in Retool, take a look at our component library or get in touch.

 

GitHub: StackdropCO/retool-ai-editor