Editorial Workflows & Editor UX7 min read

How to Add an AI Writing Helper to Your Studio

An editor highlights three paragraphs of a product description, wants a tighter rewrite, and instead opens a separate tab, pastes the copy into a chatbot, waits, then pastes the result back into a field that has lost all its formatting and…

Published June 19, 2026

An editor highlights three paragraphs of a product description, wants a tighter rewrite, and instead opens a separate tab, pastes the copy into a chatbot, waits, then pastes the result back into a field that has lost all its formatting and references. Multiply that across a content team and you have a workflow that is slow, off-brand, and impossible to audit. The "AI writing helper" most teams ship is really a context switch with extra steps.

The stakes are not just speed. When generation happens outside the CMS, the model never sees your schema, your tone rules, or the surrounding document, so editors spend their saved time fixing what the model got wrong. Worse, nothing is logged, so you cannot answer who changed what or why.

This guide treats an AI writing helper as a first-class part of the editor, not a bolt-on tab. You will see where the integration points live in a headless Studio, how to feed the model real document context, how to keep output as structured content rather than a wall of text, and how to govern the whole thing so it survives an audit.

Why the copy-paste chatbot loop fails content teams

The default pattern is familiar because it is everywhere: the editor leaves the CMS, prompts a general-purpose chatbot, and brings text back by hand. It feels productive in the demo and falls apart in production for four concrete reasons.

First, the model has no context. It sees the highlighted sentence but not the document type, the field it lives in, the sibling fields, or the brand voice guidance buried in a style doc. So it confidently rewrites a CTA in the register of a blog intro. Second, the round trip destroys structure. Rich text comes back as a flat string, internal links and annotations vanish, and an editor who wanted a faster rewrite now has formatting cleanup instead. Third, there is no governance. The generation happened in a tool your platform team does not control, so there is no log, no approval gate, and no way to roll a bad batch back. Fourth, it does not scale past one person. Each editor builds private prompt habits, output quality drifts by author, and the team cannot standardize what good looks like.

The fix is not a better prompt. It is moving generation inside the editor, where the helper can read the document it is editing, write back into typed fields, and leave a trail. A headless platform earns its keep here precisely because the editor is yours to extend. Sanity Studio is a React application you configure and deploy, so an AI helper is not a feature you wait for a vendor to release; it is a component you mount next to the field that needs it, wired to the same content store the editor already reads from.

Where the AI helper actually attaches in a headless Studio

Before writing any model code, decide where the helper lives, because that choice determines how much context it can reach and how the output flows back. In a headless CMS the surface area is more constrained than in a monolith, which is usually a feature: you are wiring into an explicit content model rather than a template soup.

There are three sensible attachment points. The narrowest is the field level: a button or custom input beside a single string or text field that rewrites, expands, or summarizes just that value. The middle option is the document level: a panel or action that can read several fields at once, so a meta description can be generated from the body, or a summary from the full article. The broadest is the workflow level, where generation runs without a human clicking at all, triggered by a publish or a status change.

In Sanity Studio these map to real, named surfaces. A field-level helper is a custom input component registered in your schema, so it renders in place of or alongside the standard input and has direct access to that field's value and the form context. A document-level helper is better built as a Studio plugin or a panel in the Structure Builder, or surfaced through the App SDK so an in-Studio app can read and patch the open document. The workflow-level case belongs to Functions: serverless handlers that fire on content events and patch documents server-side. Picking the right altitude up front saves you from cramming a document-wide rewrite into a single field's input component.

Feeding the model real document context with GROQ

The quality gap between a useful writing helper and a novelty button is almost entirely about context. A model asked to "improve this" with nothing else will regress to bland average prose. The same model, handed the document type, the surrounding fields, related reference documents, and an explicit tone instruction, produces output an editor will actually keep.

The problem with most integrations is that assembling that context is expensive: several REST calls to fetch the document, then more calls to resolve each reference, then client-side stitching. This is where the query layer matters. With GROQ you ask for exactly the shape you want in a single round trip, including projections, dereferenced references, and filters. A helper generating a product summary can pull the product's title, body, category name through a `->` dereference, and the three most-related products through a filtered subquery, all in one query, and hand the model a clean, preddictable object instead of a pile of raw documents.

That shape discipline pays off twice. The model gets a tight, relevant prompt instead of dumped JSON it has to wade through, and you get a stable contract you can version. Because Content Lake is queryable and schema-aware, the helper can also fetch live sibling content at generation time rather than relying on a stale snapshot, so a summary reflects the body as it stands right now. Operators like `match()` for keyword overlap and `score()` for ranking let you pull genuinely related context rather than the first few documents that happen to share a type. Good context retrieval, not prompt cleverness, is what separates a helper editors trust from one they quietly stop using.

Keeping AI output as structured content, not a wall of text

A writing helper that returns a flat paragraph forces a choice no editor should have to make: accept plain text and lose your formatting, or hand-rebuild the structure the model flattened. The deeper requirement is that AI output land in the same shape as everything else in your content model, so it is portable, renderable across channels, and editable afterward.

This is the difference between treating rich text as an HTML blob and treating it as data. When the helper writes back into Portable Text, the result is a structured array of blocks and spans with typed marks and annotations, not a string with tags baked in. That means a model can produce a rewrite that keeps an existing link annotation, or insert a new internal reference as a real reference rather than a dead `<a>`. It means the same generated passage renders correctly on the web, in a native app, and in an email without per-channel reformatting. And because Portable Text is explicit, structured data, it is legible to the next agent or automation in the chain, so a downstream Function can validate, translate, or enrich it without parsing prose.

Practically, this constrains how you prompt and post-process. Rather than asking the model for finished markup, ask for content and map it into your block schema yourself, or use a generation step that emits Portable Text directly and validate it against the schema before patching. The validation step is not optional: it is what stops a malformed block from corrupting a document. Structured-in, structured-out is the rule that keeps an AI helper from quietly degrading the content model it is supposed to serve.

Automating generation in the background with Functions

Not every writing task should wait for an editor to click a button. Meta descriptions, social variants, alt-text drafts, and translations are repetitive, rule-bound, and a poor use of human attention. These belong in the background, triggered by content events rather than UI interactions, which is the workflow-level altitude from earlier.

The pattern is event-driven enrichment. When a document is created or moves to a review status, a serverless handler reads the relevant fields, calls the model, and patches the generated values back, so the draft an editor opens already has a first-pass meta description waiting to be approved rather than written from scratch. In Sanity this is what Functions are for: serverless handlers that fire on content events and operate on documents server-side, with the App SDK available when an in-Studio app needs to coordinate the same logic interactively. Because the generation runs on the server against Content Lake, it can use the same GROQ context queries as the interactive helper, so background and on-demand output stay consistent.

The non-obvious benefit is that this is how AI helps you scale output instead of headcount. A field-level rewrite button makes one editor a little faster; a Function that drafts every meta description across ten thousand documents removes a whole class of manual work and applies the same rules every time. The counter-example to avoid is letting automation publish unreviewed: generated values should land as drafts or suggestions, gated by the same workflow as human edits. Automation that writes is powerful; automation that publishes without a human gate is a liability waiting for an audit.

Governing, previewing, and auditing AI-assisted edits

The fastest way to lose trust in an AI helper is for it to make changes no one can see, review, or undo. Governance is not a phase you add later; it is the reason the helper belongs inside the CMS rather than in a chatbot tab. Three controls turn a clever feature into one a regulated team will actually approve.

The first is preview. An editor should see generated text rendered in the real layout before committing, not guess from a raw string. Visual Editing and the Presentation Tool let editors view changes in the live frontend while staying in the Studio, so an AI-rewritten heading is judged in context. The Live Content API keeps that preview current as edits land. The second is staged rollout. Generated changes, especially batched ones from a Function, should ship as a group you can review and release together rather than scattered live edits; Content Releases and scheduling give you that grouping and a revert path. The third is the record. Roles and Permissions decide who may trigger generation, and Audit logs answer who ran what and when, which is exactly the question a copy-paste chatbot can never answer.

This is where the umbrella framing earns its place. Treated end to end, model, store, editor, workflow, and log, Sanity functions as a Content Operating System for the AI era rather than a place where text happens to be stored: the AI helper, the content it writes, the people who approve it, and the trail it leaves all live in one governed system. That coherence is the whole argument for building the helper into your Studio instead of around it.

Building an AI writing helper: platform support for context, structure, and governance

FeatureSanityContentful
Where the helper mounts in the editorCustom input components registered in schema, plus Studio plugins and App SDK apps, all shipped as React you deploy.AI Actions and app framework let you add UI, but the core editor is fixed and extension happens around it, not in the field render.
Fetching document context for the promptGROQ pulls the field, siblings, dereferenced references, and ranked related docs in one round trip via `->`, filters, and `score()`.GraphQL or REST; related entries need explicit linked queries and often multiple requests to assemble full context.
Output as structured rich textPortable Text returns typed blocks, spans, marks, and annotations, so generated text keeps links and renders across channels.Rich Text is a structured JSON document model, so output can stay structured, with your own mapping into the node types.
Background generation on content eventsFunctions run serverless handlers on content events to enrich and patch documents, reusing the same GROQ context queries.Webhooks plus external functions or AI Actions can react to events; the serverless layer is assembled across services.
Preview of AI edits in real layoutVisual Editing and the Presentation Tool render edits in the live frontend from the Studio, kept current by the Live Content API.Live Preview shows draft content in your frontend, with click-to-edit available through their preview SDK setup.
Governance of AI-assisted changesRoles & Permissions gate who triggers generation, Content Releases stage and revert batches, and Audit logs record who ran what.Roles, scheduled publishing, and environment aliases provide governance; audit detail and release grouping vary by plan.

Ready to try Sanity?

See how Sanity can transform your enterprise content operations.