Capture Tone of Voice Function
AI-Powered Tone Analysis for Consistent Brand Voice
schemaTypes/post.ts
defineField({
name: 'toneOfVoice',
title: 'Tone of Voice',
type: 'text',
readOnly: () => true, // This is optional
description: 'Tone of voice analysis will be automatically generated when you publish a post',
}),functions/capture-tone-of-voice/index.ts
import {createClient} from '@sanity/client'
import {documentEventHandler} from '@sanity/functions'
export const handler = documentEventHandler(async ({context, event}) => {
const {local} = context // local is true when running locally
const {data} = event
const client = createClient({
...context.clientOptions,
apiVersion: 'vX',
useCdn: false,
})
try {
const result = await client.agent.action.generate({
// Set `noWrite` to `false` to write the tone of voice to the document
noWrite: local ? true : false, // if local is true, we don't want to write to the document, just return the result for logging
instructionParams: {
content: {
type: 'field',
path: 'content',
},
},
instruction: `Examine the $content. Explain the tone of voice for the post.`,
target: {
path: 'toneOfVoice',
},
conditionalPaths: {
defaultReadOnly: false,
},
documentId: data._id,
schemaId: '_.schemas.default',
forcePublishedWrite: true,
})
console.log(
local
? 'Generated tone analysis (LOCAL TEST MODE - Content Lake not updated):'
: 'Generated tone analysis:',
result.toneOfVoice,
)
} catch (error) {
console.error('Error occurred during tone of voice generation:', error)
}
})
sanity.blueprint.ts
import {defineBlueprint, defineDocumentFunction} from '@sanity/blueprints'
export default defineBlueprint({
resources: [
defineDocumentFunction({
name: 'capture-tone-of-voice',
src: './functions/capture-tone-of-voice',
memory: 2,
timeout: 60,
event: {
on: ['create', 'update'],
filter:
"_type == 'post' && (delta::changedAny(content) || (delta::operation() == 'create' && defined(content)))",
projection: '{_id}',
},
}),
],
})This Sanity Function solves a fundamental content strategy challenge: understanding and maintaining consistent tone across your content library. Content creators often lack objective feedback on their writing style, making it difficult to ensure brand voice consistency and optimize content engagement.
Quick Start
View full instructions and source code.
Initialize blueprints if you haven't already: npx sanity blueprints init
Then: npx sanity blueprints add function --example capture-tone-of-voice
Then deploy: npx sanity blueprints deploy
How It Works
When a content editor publishes a new blog post, the function automatically:
- Triggers on the publish event for post documents
- Analyzes the post's content field to identify tone characteristics
- Generates objective tone assessment using AI
- Stores the analysis in a dedicated
toneOfVoicefield - Provides immediate insights into writing style and voice
Key Benefits
- Provides objective feedback on content tone and style
- Helps maintain consistent brand voice across all content
- Enables data-driven content strategy decisions
- Reduces subjective editorial discussions about tone
- Scales tone analysis as your content library grows
- Improves content creator awareness of their writing style
Technical Implementation
The function uses Sanity's AI capabilities to provide sophisticated tone analysis of portable text content. It's built with:
- Event-driven architecture (triggers on document publish)
- AI-powered tone identification and explanation
- Dedicated schema field for storing analysis results
- Simple, customizable implementation for different content types
Perfect For
- Content teams needing objective tone feedback
- Brands requiring consistent voice across multiple creators
- Editorial workflows focused on audience engagement optimization
- Organizations building comprehensive content style guides
The function is compatible with any Sanity project and can be easily customized to focus on specific tone characteristics or content types relevant to your brand strategy.
Contributor

Ken Jones Pizza
Designer who spends most of his time coding