---
title: persona_create
description: 'Add a persona to a brand: an audience that the brand talks to.'
---

Ask for a new audience on a brand. The agent creates a persona from what you say.

> "Add a persona to Acme: runners aged 28 to 45 who buy the same shoe again. They fear that a new model is worse."

The agent calls `persona_create` with the age range and the frictions that you gave. You then see the new persona on Acme, for example Loyalists. Its other sections stay empty until you write them.

The job guide [Describe a brand](/mcp/tools/describe-a-brand) shows each step of the job.

## Reference

Create a persona on a brand — an audience archetype describing who the brand talks to (not the voice it speaks in, which is the brand's own 'voice' section). Every section and both age bounds are optional; a persona is authored incrementally. The slug is unique within the brand, so two brands may each have a 'loyalists'.

### Input

| Argument | Type | Required | Description |
| --- | --- | --- | --- |
| `age_max` | integer, 0 to 120 | no | Upper age bound. Omit for "and older". |
| `age_min` | integer, 0 to 120 | no | Lower age bound. Omit for "and younger". |
| `brand_name` | string | yes | The slug of the brand this persona belongs to. |
| `description` | string | yes | One-line summary used to pick this persona from a list. |
| `frictions` | string | no | What stops them: objections, doubts, perceived risk, inertia. |
| `language` | string | no | The words the audience itself uses for the problem — verbatims and vocabulary, in their own register. This is not a locale. |
| `motivations` | string | no | What they want: jobs to be done, triggers, the outcome they picture. |
| `name` | string | yes | Display name, e.g. "Time-poor Parent". |
| `profile` | string | no | Who they are: life stage, situation, role, context. |
| `slug` | string | no | Optional explicit slug handle; normalized to kebab-case. Defaults to one derived from the name. |

### Output

A successful call returns this object in `structuredContent`.

| Field | Type | Always present | Description |
| --- | --- | --- | --- |
| `persona` | object | yes | The persona in full. |
| `persona.ageMax` | integer, 0 to 120 or null | yes | The highest age of the audience. `null` when the range has no upper bound. |
| `persona.ageMin` | integer, 0 to 120 or null | yes | The lowest age of the audience. `null` when the range has no lower bound. |
| `persona.brandId` | string | yes | The brand that owns the persona (`brd_…`). |
| `persona.createdAt` | number | yes | Milliseconds since the Unix epoch, in UTC. |
| `persona.createdBy` | string | yes | The user who created the record (`usr_…`). |
| `persona.description` | string | yes | One line about the persona. An agent picks a persona on it. |
| `persona.frictions` | string or null | yes | What stops the audience: objections, doubts, perceived risk. Markdown. `null` when the section is not written. |
| `persona.id` | string | yes | The id of the persona (`psn_…`). |
| `persona.language` | string or null | yes | The words that the audience uses for the problem. It is not a locale. Markdown. `null` when the section is not written. |
| `persona.motivations` | string or null | yes | What the audience wants: jobs to be done, triggers, outcomes. Markdown. `null` when the section is not written. |
| `persona.name` | string | yes | The display name. |
| `persona.profile` | string or null | yes | Who the audience is: life stage, situation, role. Markdown. `null` when the section is not written. |
| `persona.revision` | number | yes | The version of the record. Each change adds 1. Send it as `base_revision` to update or delete the record. |
| `persona.slug` | string | yes | The handle of the persona. It is unique in its brand, not in the organization. The tools take it as `persona_name`. |
| `persona.updatedAt` | number or null | yes | Milliseconds since the Unix epoch, in UTC. `null` until the first change. |

### Failure codes

A failed call has `isError` set, and `structuredContent.error` holds one of these codes. [Errors](/mcp/errors) describes the shape of a failed call.

- `not_found`
- `invalid_slug`
- `invalid_age_range`
- `slug_conflict`
- `forbidden`
- `invalid_request`
- `internal_error`

### Scope

The token must hold `brand:write`. [Auth & scopes](/mcp/auth) lists each scope.

### Annotations

A client reads these hints. A hint that the tool does not declare has the default value of the MCP specification.

- **Writes.** The tool can change data.
- **Destructive.** The tool can make a change that you cannot undo. A client can ask you to confirm before it calls the tool.
- **Not idempotent.** A second call with the same arguments can change more.
- **Closed world.** The tool reads and writes the data of AdCrunch only.

### Example

The arguments:

```json
{
  "age_max": 45,
  "age_min": 28,
  "brand_name": "acme",
  "description": "Runners who already own a pair, and who buy the next one without looking at another brand.",
  "frictions": "They fear the new model is worse than the one they know. A change of sole or of last reads to them as a risk, not as progress.",
  "name": "Loyalists"
}
```

The result, in `structuredContent`:

```json
{
  "persona": {
    "ageMax": 45,
    "ageMin": 28,
    "brandId": "brd_6a9c33",
    "createdAt": 1790000000000,
    "createdBy": "usr_4d8b12",
    "description": "Runners who already own a pair, and who buy the next one without looking at another brand.",
    "frictions": "They fear the new model is worse than the one they know. A change of sole or of last reads to them as a risk, not as progress.",
    "language": null,
    "motivations": null,
    "profile": null,
    "id": "psn_8c4a20",
    "name": "Loyalists",
    "revision": 1,
    "slug": "loyalists",
    "updatedAt": null
  }
}
```
