Sanity Library Reference Docs
    Preparing search index...

    Module content-agent - v0.4.3

    content-agent

    Vercel AI SDK provider for Sanity Content Agent API.

    npm install content-agent ai
    

    Create a provider instance with your organization ID and token, then use .agent(threadId) to get a model for a conversation thread:

    import { createContentAgent } from "content-agent";
    import { generateText } from "ai";

    const contentAgent = createContentAgent({
    organizationId: "your-org-id",
    token: "your-sanity-token",
    });

    const model = contentAgent.agent("my-thread");

    const result = await generateText({
    model,
    prompt: "What blog posts do I have?",
    });

    console.log(result.text);

    Use streamText from the AI SDK for streaming responses:

    import { streamText } from "ai";

    const { textStream } = streamText({
    model: contentAgent.agent("my-thread"),
    prompt: "Summarize my latest content",
    });

    for await (const text of textStream) {
    process.stdout.write(text);
    }

    Each application key uniquely identifies a deployed Sanity Studio workspace. Since multiple studios can share the same project ID and dataset, the application key is used to unambiguously target the right one.

    List available applications for your organization, then target one by its key:

    const apps = await contentAgent.applications();

    const app = apps.find((app) => app.title === "My Studio");

    const model = contentAgent.agent("my-thread", {
    application: { key: app.key },
    });

    Pass AI SDK tools to streamText or generateText — tool schemas are forwarded to the agent, and execution happens locally on the client:

    import { streamText, tool, stepCountIs } from "ai";
    import { z } from "zod";

    const result = streamText({
    model: contentAgent.agent("my-thread", { application: { key: "my-studio" } }),
    prompt: `Find all blog posts still in draft and submit them for review. Assign them to anna@example.com.`,
    tools: {
    submit_for_review: tool({
    description: `Submit a document for editorial review. The document must be in draft state.`,
    inputSchema: z.object({
    documentId: z.string().describe("The Sanity document _id"),
    email: z.string().email().describe("Assign a specific reviewer"),
    note: z.string().optional().describe("Note for the reviewer"),
    }),
    execute: async ({ documentId, email, note }) => {
    const res = await fetch(
    "https://workflows.internal.example.com/api/review",
    {
    method: "POST",
    body: JSON.stringify({ documentId, email, note }),
    },
    );

    const { ticketUrl } = await res.json();
    return { success: true, documentId, ticketUrl };
    },
    }),
    },
    });

    The model decides when to call your tools. stopWhen controls how many round-trips are allowed between the model and tool execution.

    Pass a config object to .agent() to control behavior:

    const model = contentAgent.agent("my-thread", {
    application: { key: "your-application-key" },
    config: {
    instruction: "You are a helpful content assistant for our marketing team.",
    userMessageContext: {
    "slack-channel": "#marketing",
    "user-role": "editor",
    },
    capabilities: {
    read: true,
    write: false,
    },
    filter: {
    read: '_type in ["post", "author", "category"]',
    write: '_type == "post"',
    },
    },
    });
    Field Type Description
    instruction string Custom instruction included in the system prompt
    userMessageContext Record<string, string> Key-value pairs appended to each user message as XML tags
    capabilities object Controls what operations the agent can perform (read, write)
    filter object GROQ boolean expressions for document access control
    perspectives object Perspective locking for read and write operations

    Each entry in userMessageContext is rendered as an XML tag in the user message. This gives the model structured context it can reason about without polluting the conversation.

    config: {
    userMessageContext: {
    "slack-channel": "#marketing",
    "image-urls": "https://example.com/hero.png\nhttps://example.com/logo.jpg",
    },
    }

    The model sees:

    <slack-channel>#marketing</slack-channel>
    <image-urls>
    https://example.com/hero.png
    https://example.com/logo.jpg
    </image-urls>

    Each capability can be true, false, or a preset object:

    // Read-only
    config: { capabilities: { read: true, write: false } }

    // Minimal write access
    config: { capabilities: { read: true, write: { preset: "minimal" } } }

    MIT

    Provider

    ContentAgentProvider
    ContentAgentProviderSettings
    createContentAgent

    Model

    ContentAgentModel
    ContentAgentModelConfig

    Configuration

    AgentSettings
    GenerateOptions
    GenerateResult
    GenerateSettings
    Application
    ApplicationResource
    Capabilities
    Capability
    CapabilityPreset
    CapabilityPresetValue
    Config
    Filter
    OutputFormat
    UserMessageContext

    API Types

    ChatRequest
    ChatResponse
    ErrorResponse
    GenerateRequest
    Message
    MessageRole
    ValidationIssue

    Utilities

    SanityAgentError
    buildApiUrl
    buildHeaders
    classifyAgentError
    createSSEStream
    extractTextFromParts
    extractTextFromStream
    fetchApi
    getAgentErrorMessage
    mapFinishReason
    parseStreamLine

    Other

    ClientToolDefinition
    operations
    AgentErrorType
    components
    ParsedStreamLine
    paths
    GENERIC_ERROR_MESSAGE