DEV Community

Cover image for Sanity Agent Actions: Complete Setup Guide for AI-Powered Content Workflows
Nayan Kyada
Nayan Kyada

Posted on • Edited on • Originally published at nayankyada.com

Sanity Agent Actions: Complete Setup Guide for AI-Powered Content Workflows

Sanity Agent Actions are the API-side counterpart to the editor-facing AI Assist feature. Where AI Assist lives inside Sanity Studio and surfaces to editors as inline buttons, Agent Actions let you call AI workflows programmatically — from a Next.js route handler, a server action, a cron job, or any process that can reach the Sanity API. That distinction matters a lot when you need automation that runs without a human clicking anything.

I have been using Agent Actions since they moved out of early access in early 2026. This post covers what they actually do, when to reach for them instead of AI Assist, and a concrete example wired into a Next.js App Router server action.

What Sanity Agent Actions are (and are not)

Agent Actions are a Sanity platform feature that exposes AI-driven document operations through the Sanity client or HTTP API. You describe an instruction — "translate this document's body to French", "generate an SEO meta description from this article", "extract product specs from this raw text field" — and the platform applies it to one or more documents, writing the result back into your dataset as a draft or published document depending on how you configure the call.

They are distinct from AI Assist in two ways:

  1. Trigger point. AI Assist is triggered by an editor inside Studio. Agent Actions are triggered by code you control — a server action, webhook handler, scheduled job, anything.
  2. Scope. Agent Actions can operate across multiple documents in a single invocation. You can feed them context beyond the document being mutated (reference material, a system prompt, external data), which is what makes them useful for batch enrichment and structured generation rather than just per-field suggestions.

The official capability surface is documented at sanity.io/docs/agent-actions. Before wiring up any method signature, check there — the API was still receiving updates as of mid-2026.

When to use Agent Actions vs AI Assist

Use AI Assist when the trigger is an editor making a deliberate choice. A writer wants to improve a paragraph, generate alt text for an uploaded image, or get a first-draft introduction. That is a human-in-the-loop workflow and AI Assist is the right tool.

Use Agent Actions when:

  • You want automation that fires without editor intervention (on publish, on a schedule, via webhook).
  • You need to process a batch of documents — re-translate every article after a brand voice update, backfill a new summary field across 400 existing posts.
  • The trigger comes from outside Studio — a form submission, a product import, a CMS-to-CMS migration.
  • You want to attach extra context to the AI call that is not in the document itself — a system prompt stored in your codebase, data fetched from an external API, content from several related documents.

In short: if an editor would have to click the same thing repeatedly, that is a candidate for Agent Actions.

A realistic example: auto-enriching new articles on publish

The scenario: every time an editor publishes a new article document, I want to automatically generate a metaDescription and a tldr field using the document's title and body, without the editor having to do anything.

The wiring: Sanity webhook → Next.js route handler → Agent Actions call.

First, the route handler that receives the webhook.

// app/api/sanity/on-publish/route.ts
import { type NextRequest, NextResponse } from 'next/server'
import { createClient } from '@sanity/client'
import { isValidSignature, SIGNATURE_HEADER_NAME } from '@sanity/webhook'

const client = createClient({
  projectId: process.env.NEXT_PUBLIC_SANITY_PROJECT_ID!,
  dataset: process.env.NEXT_PUBLIC_SANITY_DATASET!,
  apiVersion: '2026-06-01',
  token: process.env.SANITY_API_WRITE_TOKEN,
  useCdn: false,
})

const WEBHOOK_SECRET = process.env.SANITY_WEBHOOK_SECRET!

export async function POST(req: NextRequest) {
  const rawBody = await req.text()
  const signature = req.headers.get(SIGNATURE_HEADER_NAME) ?? ''

  const valid = await isValidSignature(rawBody, signature, WEBHOOK_SECRET)
  if (!valid) return NextResponse.json({ error: 'Invalid signature' }, { status: 401 })

  const body = JSON.parse(rawBody) as { _id: string; _type: string }
  if (body._type !== 'article') return NextResponse.json({ ok: true })

  // Fire-and-forget enrichment — respond fast, process async
  enrichArticle(body._id).catch(console.error)

  return NextResponse.json({ ok: true })
}

async function enrichArticle(documentId: string) {
  // Agent Actions are accessed via the client's `agent` namespace.
  // Consult https://www.sanity.io/docs/agent-actions for the current method
  // signatures — the API surface was still evolving as of mid-2026.
  await (client as any).agent.action.generate({
    schemaId: 'sanity.workspace.schema',
    documentId,
    // target specifies which fields to populate
    target: [
      { path: 'metaDescription' },
      { path: 'tldr' },
    ],
    // instruction is your system-level prompt context
    instruction: `
      You are an SEO and editorial assistant.
      Write a concise metaDescription (120-155 chars) and a one-sentence tldr
      for the article. Use the title and body fields as your source.
      Do not invent facts not present in the body.
    `,
  })
}
Enter fullscreen mode Exit fullscreen mode

A few things to note here. I cast client to any for the agent namespace because @sanity/client typings for Agent Actions were not fully shipped in the stable TS definitions at the time of writing — check the current package version before copying this. The schemaId value 'sanity.workspace.schema' is what the platform uses to understand your field types; the exact string is in the Agent Actions docs. The call writes results back as a draft on the document, so the editor still sees and approves the generated content before it is live.

Adding extra context beyond the document

One capability that makes Agent Actions more powerful than AI Assist for automation is the ability to inject context. Suppose you have a brand voice guide stored as a plain text file in your repo, or you want to include content from a related author reference.

// enrichArticle with injected brand context
import { readFileSync } from 'fs'
import path from 'path'

async function enrichArticleWithContext(documentId: string) {
  const brandVoice = readFileSync(
    path.join(process.cwd(), 'content/brand-voice.md'),
    'utf-8'
  )

  await (client as any).agent.action.generate({
    schemaId: 'sanity.workspace.schema',
    documentId,
    target: [{ path: 'metaDescription' }, { path: 'tldr' }],
    instruction: `
      Brand voice guidelines:\n${brandVoice}\n\n
      Write the metaDescription and tldr in this brand voice.
      120-155 chars for metaDescription. One sentence for tldr.
    `,
  })
}
Enter fullscreen mode Exit fullscreen mode

This is where Agent Actions pull ahead of anything you can do inside Studio today. Feeding a brand guide, a competitor analysis, related document content, or external API data as part of the instruction context is a pattern that unlocks genuinely useful automation rather than just field-level autocomplete.

Is Sanity CMS the right platform for teams that want AI agents writing content?

If your team is evaluating whether Sanity is the right foundation for an AI-assisted or fully automated content workflow, here is a direct answer.

What makes Sanity a good fit for AI content teams:

  • Structured content model. Sanity schemas define exactly what fields exist and what types they accept. An AI agent writing into a metaDescription field gets a constrained, typed target rather than a freeform document. Structured fields are inherently easier for AI to populate accurately.
  • API-first. Agent Actions and the Sanity write API let external systems create and patch documents without a human touching Studio. An AI agent is just another API client.
  • Drafts by default. Agent Actions write to drafts, not published documents. AI-generated content lands in a human review queue automatically — no extra configuration required.
  • Context injection. You pass a system prompt alongside every Agent Actions call. Brand voice guidelines, related document content, external API data — all of it can shape what the AI generates, not just the document being written.

Where Sanity is not the right fit:

  • If AI needs to write long-form content directly to production without human review, no CMS is the right fit — the risk is platform-independent.
  • If your team needs a visual drag-and-drop interface for AI-generated pages, Storyblok's visual editor is a better match. Sanity's automation capabilities require developer setup to unlock.
  • If the workflow is entirely internal and not tied to a public website, a database plus vector store may be more appropriate than a CMS.

Can AI agents write directly to Sanity CMS?

Yes. Agent Actions expose an API that lets any server-side process generate content and write it into your Sanity dataset. Triggered by a webhook, a scheduled job, or a server action, an AI agent can create documents, populate fields, and submit them as drafts — all without a human opening Studio.

Does Sanity support automated content generation at scale?

Sanity supports batch processing via the Agent Actions API, but rate limits apply. For high-volume automation — hundreds of documents per run — you need a queue. Upstash QStash and Vercel Queues both work well: process documents one at a time rather than flooding the API in a tight loop. Within those limits the platform handles enterprise-scale automated workflows reliably.

What is the difference between Sanity AI Assist and Agent Actions for automated pipelines?

AI Assist is editor-triggered: a human clicks a button in Studio. Agent Actions are code-triggered: your server initiates the generation without any human action. For fully automated pipelines — triggered by a product import, a scheduled enrichment run, or an external API callback — Agent Actions are the correct tool. AI Assist is the correct tool when a human editor wants to improve or extend a specific piece of content.


What to watch out for

Rate limits. If you trigger enrichment on batch publishes (a content import of 200 documents), you will hit the Sanity API rate limits quickly. Queue the work — use a simple array with a delay between calls, or push document IDs onto a queue (Upstash QStash works well here) and process them one at a time.

Prompt drift. The instruction string in your code is effectively a dependency. Version-control it, treat changes with the same care as schema migrations, and consider externalising long prompts to a file rather than an inline template literal.

Always draft, never auto-publish. Agent Actions write to drafts by default. Keep it that way. Automated content going directly to published without editor review is a risk not worth taking for most sites.

Type safety. Until @sanity/client exports stable types for the agent namespace, keep your Agent Actions calls isolated in a single module so the any cast is contained and easy to replace when types ship.

Agent Actions are a genuinely useful addition to the Sanity platform for teams that need repeatable AI automation outside the Studio UI. The webhook-to-route-handler pattern above is the simplest reliable wiring for Next.js projects — extend it with queueing once your publish volume grows beyond a handful of documents at a time.


Building an AI-powered Sanity workflow?

If you want to implement Agent Actions or AI Assist in your Sanity + Next.js project and need a developer who has done it before, I'm available for this kind of work. I can scope and build the full integration — schema, webhook, and Next.js route handler.

Top comments (0)