AI in the Editor7 min readβ€’

How to Build an AI Image Caption Workflow in Your CMS

Your media library has 40,000 images and maybe 3,000 of them have alt text. The rest shipped with filenames like "IMG_4471.jpg" because someone was on deadline.

Your media library has 40,000 images and maybe 3,000 of them have alt text. The rest shipped with filenames like "IMG_4471.jpg" because someone was on deadline. Now an accessibility audit is flagging the gaps, your SEO team wants descriptive captions for image search, and an editor is hand-typing alt text one asset at a time. It does not scale, it is inconsistent, and the moment a new batch of photography lands the backlog grows again.

Sanity, the AI-native content platform, treats this as a content modeling and automation problem rather than a manual chore. As the AI Content Operating System, Sanity wires generation into the data model, the editor, and the delivery layer, so a caption is not a one-off string an editor pastes in. It is a governed field that can be generated, reviewed, and corrected inside the same workflow that produces the rest of your content.

This guide walks through building an image caption workflow end to end: where captions live in your schema, how to generate them with AI Assist and Agent Actions, how to keep a human in the review loop, and how to evaluate quality before anything reaches production. The goal is captions that are accurate, on-brand, accessible, and produced at the speed your library actually grows.

Why manual captioning breaks at scale

The failure mode is predictable. A single editor can write a thoughtful caption in thirty seconds, but a library that grows by hundreds of assets a week turns that thirty seconds into a permanent backlog. Worse, manual captioning is inconsistent: one editor writes terse alt text for accessibility, another writes marketing-flavored captions, and a third leaves the field blank because the deadline won. The result is a media library where the metadata quality is a function of who happened to upload the asset and how busy they were that day.

The stakes are not cosmetic. Missing or poor alt text is a direct accessibility failure under WCAG, and accessibility audits increasingly carry legal exposure. Image search and AI Overviews lean heavily on descriptive text to understand what a picture shows, so empty captions cost discoverability. And when downstream LLM workflows try to retrieve or reason over your content, an image with no description is invisible to them; it cannot be matched, summarized, or grounded against.

The instinct is to throw a script at it: batch every asset through an image model, write the output back, and call it done. That gets you volume, but it also gets you confident, wrong captions at scale, with no review step and no record of what changed. The reframe this guide argues for is that captioning is not a one-time migration. It is an ongoing content operation that needs a home in your schema, a generation step the editor can trust, and a governance loop that catches the mistakes before they ship. Legacy CMSes stop at storing the field; the work is keeping it populated, accurate, and current as the library grows.

Model the caption as structured content, not a loose string

Before any AI touches your images, decide what a caption actually is in your model. A single text field is the trap most teams fall into, because an image carries several distinct kinds of text that serve different consumers. Alt text exists for screen readers and should be concise and literal. A display caption is editorial and may carry tone or attribution. A longer description can feed semantic search and LLM retrieval. Collapsing all of these into one field guarantees that one consumer is always badly served.

In Sanity you model these as separate, typed fields on the image object: an altText string with a length guideline, an optional caption for display, and a longer description field for machine consumers. Because the schema is code, you can attach validation rules (alt text required, maximum length, no leading filename junk) and the Studio enforces them at edit time rather than letting bad data through. This is the first pillar, model your business: the caption fields reflect the actual jobs the text has to do, not a generic blob.

Structure pays off downstream. Portable Text and typed fields preserve meaning across LLM chunking and retrieval, so when a description field feeds an embeddings pipeline or a generation prompt, the model receives clean, labeled context instead of a guessed-at string. It also means you can track which images still need captions with a simple GROQ query against the missing field, turning an invisible backlog into a queryable, prioritizable list. The difference between legacy CMSes and Sanity here is that Sanity adapts to the way your team actually classifies image text rather than forcing every caption into one box.

Illustration for How to Build an AI Image Caption Workflow in Your CMS
Illustration for How to Build an AI Image Caption Workflow in Your CMS

Generate captions with AI Assist inside the Studio

Once the fields exist, the editor-facing layer is AI Assist: in-Studio LLM helpers that work directly on the document an editor is looking at. For captioning, the relevant moves are concrete. An editor can generate alt text from an uploaded image, rewrite a caption in a different voice to match a campaign, translate the caption and alt text into every locale the site ships, and fact-check a generated description against a knowledge base before accepting it. The key property is that this happens where the editor already works, not in a separate tool they have to context-switch into.

This matters because adoption is the real constraint on any AI feature. A captioning script that lives in a separate pipeline produces output nobody reviews; an in-editor assistant that drafts the caption and leaves the human to approve or tweak it produces output people actually trust. AI Assist is configured against your schema, so it knows the alt text field wants something concise and the description field wants something fuller, and it can be pointed at instructions that encode your brand voice and accessibility standards.

The distinction to hold onto is that the AI is not bolted on with a plugin. It is wired into the same Studio that governs the rest of your content, which means a generated caption flows through the same review, the same permissions, and the same publishing controls as anything an editor types by hand. Legacy CMSes that add a ChatGPT button treat generation as a novelty; here it is a first-class step in the editorial workflow, framed by the second pillar, automate everything, without removing the editor from the loop.

Automate the pipeline with Agent Actions and Functions

In-editor generation handles the asset an editor is actively working on. The backlog of 37,000 uncaptioned images needs a pipeline. This is where Agent Actions and Functions come in, and they map to a different lens than AI Assist: AI as a content pipeline primitive rather than AI inside the editor.

Agent Actions are schema-aware APIs for LLM-driven workflows, generate, transform, translate, and validate, that operate on documents programmatically. Because they understand your schema, an Agent Action that generates a caption knows exactly which field to write to and what constraints apply, so the output lands as valid structured content rather than a raw string you have to clean up. You can run a batch over every image where altText is empty, generating drafts at the scale your library actually demands.

Functions are the serverless hooks that connect this to events. An enrich-on-publish or generate-on-upload Function can fire the moment a new asset enters the Content Lake, generating a draft caption automatically so the backlog never rebuilds. Translate-on-publish can fan a caption out to every locale once it is approved. The pattern is that editors are not scaling linearly with content volume; the pipeline absorbs the volume and the humans review the output. This is the concrete meaning of scaling output rather than scaling people: a team of three keeps a library of fifty thousand assets captioned because the generation is automated and only the judgment is manual. The counter-example is the script-only approach, which scales volume but produces unreviewed text that quietly degrades your library's trustworthiness.

Keep a human in the loop with Studio review and Content Releases

Automated captioning without governance is how you ship a confidently wrong description of a sensitive image to production. The whole point of building this inside a Content Operating System rather than a standalone script is that the governance already exists. Generated captions are drafts, not live data, and they move through the same review the rest of your content does.

In practice, an AI-generated caption lands as a draft on the image document. An editor sees it in the Studio, where Visual Editing and the Presentation Tool let them see the caption in the context of where the image actually renders, not as a disembodied string. Roles & Permissions decide who can approve AI-generated content, so a junior editor might generate and a senior editor approves. Content Releases let you stage a whole batch of newly captioned assets, review them together, and schedule them to go live as a unit rather than dribbling out unreviewed changes. Audit logs record what was generated and who approved it, which is exactly the provenance an accessibility or compliance review will ask for.

This review loop is also where evaluation lives, which is the next section's subject, but the governance point stands on its own. Legacy CMSes create silos: the AI tool is over here, the publishing controls are over there, and reconciling them is manual. A shared foundation means the AI-touched caption is subject to the same staging, the same permissions, and the same audit trail as everything else. On the compliance side, Sanity is SOC 2 Type II compliant, GDPR-aligned, offers regional hosting and data residency, and publishes its sub-processor list, so the AI workflow you build inherits a platform that enterprise governance teams can sign off on.

Evaluate caption quality before it reaches production

Generation is the easy part; knowing whether the output is good is the hard part, and the part most teams skip. A caption can be grammatical, on-brand, and completely wrong about what the image shows. Without an evaluation step you are trusting a model's confidence, and image models are confidently wrong often enough to matter, especially with people, products, and anything where a misdescription is embarrassing or harmful.

A workable evaluation loop has a few layers. Schema validation is the cheap first pass: alt text present, within length, not a leftover filename. Then there is automated checking, where AI Assist can fact-check a generated description against a Knowledge Base of your products or brand facts, catching the caption that calls the wrong product by name. For semantic correctness, the Embeddings Index API and dataset embeddings let you compare a caption against similar, already-approved captions to flag outliers that drift from your established style. The final layer is always human spot-checking, sampled through Content Releases so a reviewer sees a representative batch rather than every single asset.

The reason to keep evaluation inside the same platform is freshness and tied state. Because embeddings are tied to the content, when a caption changes the semantic record updates automatically; there is no separate vector pipeline drifting out of sync with the source of truth. The reframe here is that an AI captioning workflow is not finished when it generates text. It is finished when it can tell you which captions to trust and which to review, and that judgment layer is what separates a durable content operation from a one-time batch job that nobody dares run again.

AI image captioning: native CMS workflow vs. bolt-on approaches

FeatureSanityContentfulStrapi + LangChain.jsBuilder.io
In-editor caption generationAI Assist generates alt text, captions, and translations directly on the image document, configured against your schema and brand instructions.Studio AI / Quick Start AI offer in-app generation, though caption fields and validation are configured separately from the AI layer.No native in-editor assistant; generation requires building a LangChain.js flow and a custom Strapi admin plugin to surface it to editors.Builder AI focuses on page and section generation; image alt text generation is not a first-class, schema-aware editor action.
Schema-aware batch pipelineAgent Actions are schema-aware APIs (generate, transform, translate, validate) that write valid structured caption fields across a whole backlog.App Framework plus Management API can script batch jobs, but the AI step is your own code calling an external model, not a schema-aware primitive.Fully DIY: LangChain.js orchestrates the model and you map output back to fields through the REST or GraphQL API yourself.Geared to visual page building rather than programmatic batch enrichment of an existing media library's metadata.
Event-driven auto-captioningFunctions fire generate-on-upload or enrich-on-publish so new assets get draft captions automatically and the backlog never rebuilds.Webhooks can trigger external functions you host and maintain; the captioning logic and model calls live outside the platform.Achievable with lifecycle hooks plus your own service, but every piece is self-hosted and self-maintained.Limited server-side automation hooks for this use case; enrichment is generally handled in the visual editor.
Governance of AI outputGenerated captions are drafts subject to Studio review, Roles & Permissions, Content Releases, and Audit logs, same as hand-typed content.Roles and workflows exist; tying AI-generated fields into the same review and approval flow takes configuration.Draft and publish states exist, but review governance for AI output is whatever you build into your custom flow.Publishing controls are present; dedicated review and audit trails for AI-generated metadata are limited.
Semantic quality checksEmbeddings Index API and dataset embeddings compare captions against approved examples; embeddings are tied to content so they stay fresh.No native content embeddings; semantic comparison means bolting on a separate vector database and keeping it in sync.Requires a separate vector store (e.g. Pinecone or pgvector) wired up and maintained alongside the CMS.No native embeddings layer for content; semantic evaluation is out of scope for the platform.
Fact-checking against brand factsAI Assist can fact-check a generated description against a Knowledge Base of products and brand facts before an editor accepts it.Possible through custom app logic and external retrieval, not a built-in fact-check action on the field.Implementable via a RAG step in your LangChain.js flow, entirely on you to build and maintain.Not a built-in capability; brand-fact validation would need external tooling.