> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tryprofound.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Using Sanity in Agents

After connecting your Sanity account, the following actions become available as Agent steps. Each step requires you to select a connected **Sanity Project** from a dropdown.

<Tabs>
  <Tab title="Create resource" icon="file-plus">
    #### **Create Resource**

    Create a new document in your Sanity dataset.

    **Required inputs**

    * **Sanity Project** — Select the Sanity project you connected in Profound
    * **Dataset** — Select the dataset (e.g., `production`)
    * **Document Details** — A JSON object with your document fields (must include `_type`)

    **Optional inputs**

    * **Rich Text Content** — A JSON object mapping field names to HTML strings. Profound automatically converts HTML to Sanity's Portable Text format
    * **Publish Resource** — Check this to publish immediately, or leave unchecked to create a draft

    By default, new documents are created as **drafts**. Profound automatically generates a draft ID prefixed with `drafts.` for you. Enable **Publish Resource** to make the document live immediately.

    <Callout icon="lightbulb" color="#376CFF">
      **Tip:** Leave **Publish Resource** unchecked to create drafts for review in Sanity Studio before publishing.
    </Callout>
  </Tab>

  <Tab title="Update resource" icon="pencil">
    #### **Update Resource**

    Update an existing document in your Sanity dataset.

    **Required inputs**

    * **Sanity Project** — Select the Sanity project you connected in Profound
    * **Dataset** — Select the dataset
    * **Resource ID** — The Sanity document ID to update
    * **Update Details** — A JSON object with the fields you want to change

    **Optional inputs**

    * **Rich Text Content** — A JSON object mapping field names to HTML strings, auto-converted to Portable Text

    <Callout icon="lightbulb" color="#376CFF">
      **Important:** Only the fields you provide will be modified; all other fields remain unchanged. The document's `_type` cannot be changed after creation.
    </Callout>
  </Tab>

  <Tab title="Get resource" icon="file">
    #### **Get Resource**

    Retrieve a single document by ID.

    **Required inputs**

    * **Sanity Project** — Select the Sanity project you connected in Profound
    * **Dataset** — Select the dataset
    * **Resource ID** — The Sanity document ID to fetch

    The output includes the document's full content with all fields and metadata. Both published and draft documents can be retrieved (drafts use the `drafts.` prefix).
  </Tab>

  <Tab title="List resources" icon="list">
    #### **List Resources**

    Retrieve a list of documents from your Sanity dataset.

    **Required inputs**

    * **Sanity Project** — Select the Sanity project you connected in Profound
    * **Dataset** — Select the dataset

    **Optional inputs**

    * **Document Type** — Filter by a specific Sanity document type, or leave as "All Types"
    * **Include drafts?** — Uses the raw perspective to include both published and draft documents
    * **Page** — Page number to retrieve (defaults to 1)
    * **Per Page** — Number of items per page (defaults to 100)

    The output is a structured list of documents ordered by creation date (newest first) that can be used in downstream Agent steps.
  </Tab>

  <Tab title="Publish resource" icon="globe">
    #### **Publish Resource**

    Publish a draft document to make it live.

    **Required inputs**

    * **Sanity Project** — Select the Sanity project you connected in Profound
    * **Dataset** — Select the dataset
    * **Draft ID** — The draft document ID to publish (must start with `drafts.`)

    Publishing replaces the published version with the draft content and removes the draft document. This mirrors the publish behavior in Sanity Studio.
  </Tab>
</Tabs>

***

## Key Concepts

### Documents and Types

Every document in Sanity has a `_type` field that determines its schema. Sanity types are the equivalent of "content models" or "templates" — they define the structure and fields a document can have.

When creating a document with the **Create Resource** step, the `_type` field in your data determines which schema the document follows. The type must already exist in your Sanity project's schema.

Common examples of document types:

| Type       | Example Use             |
| ---------- | ----------------------- |
| `post`     | Blog articles           |
| `page`     | Static pages            |
| `product`  | E-commerce products     |
| `author`   | Content creators        |
| `category` | Taxonomy/classification |

<Callout icon="lightbulb" color="#376CFF">
  **Tip:** To see which types exist in your project, use the **List Resources** step without a type filter — the returned documents will show the available `_type` values.
</Callout>

### Datasets

Sanity projects can have multiple datasets (e.g., `production`, `staging`, `development`). Each dataset is an independent content store. Always specify the correct dataset when configuring your Agent steps.

### Drafts vs. Published

Sanity uses a dual-ID system for content versioning:

* **Published documents** have a plain ID (e.g., `abc123`)
* **Draft documents** have the same ID prefixed with `drafts.` (e.g., `drafts.abc123`)

When you create a resource without enabling **Publish Resource**, Profound automatically creates it as a draft. You can later publish it using the **Publish Resource** step, or publish directly from Sanity Studio.

***

## Working with Portable Text (Rich Text)

Sanity uses [Portable Text](https://www.sanity.io/docs/block-content) as its native rich text format. Portable Text is a JSON-based specification that represents structured content as an array of blocks.

### Providing Rich Text Content

You have two options for providing rich text content to Sanity fields:

<Tabs>
  <Tab title="HTML input (recommended)">
    Use the **Rich Text Content** field to pass HTML strings. Profound automatically converts them to Portable Text blocks.

    Map field names to HTML strings:

    ```json theme={null}
    {
      "body": "<h1>Welcome</h1><p>This is a <strong>blog post</strong> with <em>formatting</em>.</p><ul><li>First item</li><li>Second item</li></ul>"
    }
    ```

    **Supported HTML elements:**

    | Element                | Portable Text equivalent  |
    | ---------------------- | ------------------------- |
    | `<h1>` through `<h6>`  | Heading styles            |
    | `<p>`                  | Normal paragraph          |
    | `<strong>`, `<b>`      | Bold mark                 |
    | `<em>`, `<i>`          | Italic mark               |
    | `<u>`                  | Underline mark            |
    | `<code>`               | Code mark                 |
    | `<a href="...">`       | Link annotation           |
    | `<ul>`, `<ol>`, `<li>` | Bullet and numbered lists |
    | `<blockquote>`         | Blockquote style          |
    | `<br>`                 | Line break                |

    <Callout icon="lightbulb" color="#376CFF">
      **Tip:** This is the easiest way to get rich text into Sanity. Generate HTML from an LLM step and pass it directly to Rich Text Content — Profound handles the conversion.
    </Callout>
  </Tab>

  <Tab title="Native Portable Text JSON">
    If you already have Portable Text JSON (for example, from a **Get Resource** step), you can pass it directly in the **Document Details** field:

    ```json theme={null}
    {
      "_type": "post",
      "title": "My Post",
      "body": [
        {
          "_type": "block",
          "_key": "abc123",
          "style": "normal",
          "markDefs": [],
          "children": [
            {
              "_type": "span",
              "_key": "def456",
              "marks": [],
              "text": "Hello world"
            }
          ]
        }
      ]
    }
    ```

    Each block requires:

    * `_type`: Always `"block"` for text blocks
    * `_key`: A unique string identifier
    * `style`: Block style (`"normal"`, `"h1"` through `"h6"`, `"blockquote"`)
    * `markDefs`: Array of complex mark definitions (e.g., links with `href`)
    * `children`: Array of spans with `_type`, `_key`, `text`, and `marks`

    Formatting marks include: `"strong"`, `"em"`, `"underline"`, `"code"`.

    For list items, add:

    * `listItem`: `"bullet"` or `"number"`
    * `level`: Nesting level (integer)
  </Tab>
</Tabs>

***

## Mapping Sanity Schemas to Agent Steps

If you have an existing Sanity schema (document type), here's how to map it to a **Create Resource** step in your Agent.

### Example: Blog Post Schema

Suppose your Sanity Studio has a `post` type with these fields:

```js theme={null}
// In your Sanity Studio schema
defineType({
  name: 'post',
  title: 'Post',
  type: 'document',
  fields: [
    defineField({ name: 'title', type: 'string' }),
    defineField({ name: 'slug', type: 'slug' }),
    defineField({ name: 'author', type: 'reference', to: [{ type: 'author' }] }),
    defineField({ name: 'body', type: 'blockContent' }),
    defineField({ name: 'publishedAt', type: 'datetime' }),
    defineField({ name: 'categories', type: 'array', of: [{ type: 'reference', to: [{ type: 'category' }] }] }),
  ],
})
```

### Step-by-Step Setup

1. **Add a Create Resource step** to your Agent and select your connected Sanity project from the **Sanity Project** dropdown.

2. **Select the Dataset** from the dropdown (e.g., `production`).

3. **Fill in Document Details** with your document fields as JSON. This is where you provide simple values like titles, slugs, references, and categories:

   ```json theme={null}
   {
     "_type": "post",
     "title": "My Post Title",
     "slug": {
       "_type": "slug",
       "current": "my-post-title"
     },
     "author": {
       "_type": "reference",
       "_ref": "author-id-123"
     },
     "publishedAt": "2025-01-15T10:30:00Z",
     "categories": [
       {
         "_type": "reference",
         "_ref": "category-id-456"
       }
     ]
   }
   ```

   To use dynamic values from upstream steps, type `/` inside the field to open the variable menu and select a variable. It will appear as a pill badge inline with your JSON — for example, you could replace `"My Post Title"` with a variable from a previous LLM step.

4. **Fill in Rich Text Content** for any Portable Text fields (like a blog body). Map the field name to an HTML string — Profound converts it to Sanity's format automatically:

   ```json theme={null}
   {
     "body": "<h1>Welcome</h1><p>This is my post content.</p>"
   }
   ```

   You can also insert a variable here to pass in HTML generated by a previous step. Type `/` to open the variable menu and select the output from an LLM or other upstream step as the value.

5. **Check or uncheck Publish Resource** — check it to publish immediately, or leave it unchecked to create a draft for review in Sanity Studio.

<Callout icon="lightbulb" color="#376CFF">
  **Tip:** Any text field in the node settings supports **variables** — type `/` to open the variable menu and insert outputs from upstream steps. Variables appear as interactive pill badges and are resolved at runtime.
</Callout>

### Field Type Reference

| Sanity Field Type     | JSON Format in Data                                                                           |
| --------------------- | --------------------------------------------------------------------------------------------- |
| `string`              | `"value"`                                                                                     |
| `text`                | `"multi-line value"`                                                                          |
| `number`              | `42`                                                                                          |
| `boolean`             | `true` / `false`                                                                              |
| `datetime`            | `"2025-01-15T10:30:00Z"`                                                                      |
| `date`                | `"2025-01-15"`                                                                                |
| `url`                 | `"https://example.com"`                                                                       |
| `slug`                | `{ "_type": "slug", "current": "my-slug" }`                                                   |
| `reference`           | `{ "_type": "reference", "_ref": "document-id" }`                                             |
| `image`               | `{ "_type": "image", "asset": { "_type": "reference", "_ref": "image-asset-id" } }`           |
| `blockContent`        | Use **Rich Text Content** field for automatic conversion, or pass Portable Text JSON directly |
| `array` of references | `[{ "_type": "reference", "_ref": "id" }]`                                                    |
| `object`              | `{ "fieldA": "value", "fieldB": 42 }`                                                         |

***

## Common Workflows

### Generate and Publish a Blog Post

1. **LLM Step** — Generate a title, slug, and HTML body from a prompt
2. **Create Resource** — Create a Sanity `post` document using the generated content
3. **Publish Resource** — Publish the draft (or set `publish_resource: true` in step 2)

### Update Existing Content

1. **Get Resource** — Fetch the current document by ID
2. **LLM Step** — Generate updated content based on the existing document
3. **Update Resource** — Patch only the fields that changed

### Content Migration

1. **List Resources** — Fetch documents from one dataset
2. **Loop** — Iterate over the list
3. **Create Resource** — Create each document in a different dataset

### Draft Review Pipeline

1. **Create Resource** — Create content as a draft (default behavior)
2. **Human Review** — Manual review step in Sanity Studio
3. **Publish Resource** — Publish approved drafts via the Agent

***

## Permissions and Roles

Profound validates that your API token has sufficient permissions on connection. The following Sanity roles are supported:

| Role              | Can Create | Can Update | Can Publish | Can Read |
| ----------------- | ---------- | ---------- | ----------- | -------- |
| **Administrator** | Yes        | Yes        | Yes         | Yes      |
| **Editor**        | Yes        | Yes        | Yes         | Yes      |
| **Developer**     | Yes        | Yes        | Yes         | Yes      |
| **Viewer**        | No         | No         | No          | Yes      |

<Callout icon="warning" color="#FF6B35">
  **Minimum required role:** Editor. Tokens with Viewer-only access will fail when attempting to create, update, or publish documents.
</Callout>

***

## Troubleshooting

<Accordion title="Error: Invalid Sanity API key or token has expired">
  Your API token is invalid or has expired. Generate a new token in your [Sanity management console](https://www.sanity.io/manage) under **API → Tokens** and reconnect.
</Accordion>

<Accordion title="Error: Insufficient permissions">
  Your API token doesn't have Editor-level access. Create a new token with **Editor** permissions and reconnect.
</Accordion>

<Accordion title="Error: Sanity project not found">
  The Project ID in your integration settings is incorrect. Verify the Project ID in your [Sanity management console](https://www.sanity.io/manage) — it's displayed at the top of your project page and in the URL.
</Accordion>

<Accordion title="Error: Document type (_type) must be provided">
  When using **Create Resource**, your Data field must include a `_type` property that matches a document type defined in your Sanity schema. For example: `{ "_type": "post", "title": "Hello" }`.
</Accordion>

<Accordion title="Error: Resource ID is not a draft">
  The **Publish Resource** step requires a draft document ID that starts with `drafts.`. If the document is already published, it doesn't need to be published again. Check that you're passing the draft ID, not the published ID.
</Accordion>

<Accordion title="HTML not converting to rich text correctly">
  Make sure you're using the **Rich Text Content** field (not the **Document Details** field) for HTML-to-Portable-Text conversion. The Rich Text Content field expects a JSON object mapping field names to HTML strings: `{ "body": "<p>Hello</p>" }`.
</Accordion>

***

## Additional Resources

Learn more about Sanity's content model and API:

* [Sanity Content Lake](https://www.sanity.io/docs/content-lake) — Understanding datasets and documents
* [Portable Text](https://www.sanity.io/docs/block-content) — Sanity's rich text format specification
* [GROQ Query Language](https://www.sanity.io/docs/groq) — Querying content in Sanity
* [HTTP API Reference](https://www.sanity.io/docs/http-api) — Full Sanity API documentation
* [Mutations API](https://www.sanity.io/docs/http-mutations) — Creating, updating, and deleting documents
