# Design custom Dimensions

> What a custom prompt is, the output types and field patterns to use, and how to design Dimensions that give reliable, useful labels on your own data.

The Dimensions you design for your business are where most of the value comes from. [Standard Dimensions](/dimensions/standard) give you a baseline, but generic labels like topic and sentiment are rarely specific enough to act on. You don't need them for a first answer. Once you've had one, custom prompts are where most of the value comes from.

In the platform, custom Dimensions are made with **Custom Prompts** (often just **Prompts**). Standard Dimensions are **System Prompts**. The **Prompts** tab lists every prompt, yours and the standard ones.

You design and save a prompt with the agent, using **Prompt Designer**: a setting in the agent. Turn it on in the agent's settings, and the agent can draft, test and save prompts with you. With it off, the agent can talk a prompt through but can't save it.

## What a custom prompt is

A custom prompt is an analytical task you define. It tells the model exactly what to look for in each conversation, and each field in it becomes a new column (a Dimension) in your enriched data.

If the standard Reason asks *"What is this conversation about?"*, a custom prompt can ask something only your business cares about:

- *Did the customer mention a specific product feature?*
- *Is there a billing dispute in this conversation?*
- *What stage of the customer journey does this interaction represent?*
- *How satisfied was the customer with the agent?*

Each answer is a column you can filter, cross with every other Dimension, and chart.

A prompt is applied to the sources you choose when you save or backfill it, and you can apply the same prompt to several sources: one prompt can cover your chat, email and survey sources, so the results compare. When you connect a new source later, apply your prompts to it too.

On a live integration, a saved prompt runs every day on new conversations. File uploads, history and conversations you already have need a [backfill](/dimensions/backfill). See [When enrichment runs](/dimensions/when-enrichment-runs).

### What you need to tell the model

At its simplest, a custom Dimension needs two things:

1. **What information to extract:** an effort score, a set of categories, a journey stage, a product line.
2. **How to classify it:** true or false, a list of options, a score, or open-ended text.

## When to use one

- **Few survey answers.** If your CSAT response rate is low, add a [predicted CSAT](/dimensions/predicted-scores#predicted-csat) score so every conversation has one.
- **Journey stages.** Label each support conversation with the stage of the customer journey it belongs to.
- **Emerging topics.** A Dimension with dynamic labels surfaces new topics and themes as they appear.
- **An existing taxonomy.** Put your current categories into a category list, and every conversation gets tagged with your own labels.

## How a prompt is built

A prompt groups related fields so they run together on each conversation. It has two parts:

- **Context:** a short description of the data, including who the incoming and outgoing sides are and what your organization does. This is the background the model needs to read the data correctly. See [Write the context](#write-the-context).
- **Fields:** the individual tasks. Each has a name, a description of what to extract, and an output type. Each field is one Dimension.

The exact JSON is on the [config reference](/dimensions/config-reference) page.

### Example: why customers contact support

An e-commerce company wants to know why customers contact support. One prompt with six fields gives it six new Dimensions on every conversation:

| Field | What it extracts | Output type |
|---|---|---|
| `engagement_reason` | A concise label for why the customer reached out | Dynamic label |
| `engagement_category` | The main topic of the interaction | Fixed category |
| `issue_detected` | `true` if the customer reports a problem or expresses frustration | Boolean |
| `issue_reason` | A short description of the issue | Dynamic label |
| `issue_verbatim` | The customer's own words describing the issue | Verbatim quote |
| `csat` | Predicted customer satisfaction on a 1 to 5 scale | Score |

## Output types

These are the five [output types](/dimensions#output-types) used across these docs.

| Output type | JSON type | Use it for |
|---|---|---|
| Dynamic label | string | Discovery: labels written from what the text says |
| Fixed category | string with an `enum` list | Consistent groupings from a list you define |
| Boolean | boolean | Whether a condition is present |
| Score | integer | A rating on a defined scale |
| Verbatim quote | string | The customer's exact words on a topic |

Fields of different types can sit in the same prompt and work together.

### Dynamic labels

The model writes a label from what it finds. There is no list, so the output reflects the actual content of the conversation. A `contact_reason` field might return `order tracking inquiry`, `refund request`, `product availability question` or `shipping delay complaint`.

Dynamic labels are best for discovery: the model isn't limited to a list, so it can surface themes you didn't expect. Ask the agent to group them into broader themes once you see what comes back.

### Fixed categories

The model picks one value from a list you define. Use this when you already have a taxonomy or need stable groupings for reporting. For example, `engagement_category` with `billing_and_payments`, `account_access`, `product_setup`, `returns_and_refunds` and `none_detected`.

Every list ends with `none_detected` for conversations where nothing fits. Add an `other` value only if you'll read what lands in it.

### Booleans

`true` or `false`: is a condition present? `issue_detected` returns `true` if the customer reports a problem or expresses frustration, `false` otherwise.

Booleans often act as gates for other fields: `issue_reason` and `issue_verbatim` only need an answer when `issue_detected` is `true`. See [Conditional fields](#conditional-fields).

### Scores

A whole number on a defined scale, such as predicted CSAT from 1 to 5 (1 = very dissatisfied, 5 = very satisfied) or a satisfaction rating from 1 to 10. Say in the description when to leave the score empty, for example *"Leave empty if there is not enough signal"*. The model leaves it empty only when the description tells it to, and empty scores keep averages clean. [Predicted scores](/dimensions/predicted-scores) covers scoring in depth.

### Verbatim quotes

The model copies the customer's words that are most relevant to a topic. For example, `issue_verbatim` quotes what the customer said about their problem, in fewer than 30 words, taken only from the customer's (incoming) messages.

Verbatims keep the customer's own language, which makes them useful for reading behind a number and for quoting in a report.

## Field blocks: a pattern that repeats

Prompts work best when related fields come in consistent **blocks**, one block per signal:

| Field suffix | Type | What it holds | Example |
|---|---|---|---|
| `_detected` or `_mention` | Boolean | Whether the signal is present | `issue_detected` |
| `_reason` | Dynamic label | A short dynamic label for the signal | `issue_reason` |
| `_verbatim` | Verbatim quote | The customer's own words about it | `issue_verbatim` |
| `_category` | Fixed category | A fixed classification of it | `issue_category` |

Repeat the block for each signal you track: issues, friction points, product mentions, feature requests. Consistent names make the results predictable to query, and the agent can tell at a glance which fields belong together.

## Conditional fields

Fields in a block usually depend on their boolean. `issue_reason` only has an answer when `issue_detected` is `true`. When the condition isn't met, the dependent fields return `none_detected`, and a dependent score is left empty.

Say this in each dependent field's description, for example: *"If issue_detected is false, return 'none_detected'."* Then when you filter to conversations where `issue_detected` is `true`, every one of them has a real `issue_reason` and `issue_category`.

:::note
Older Dimension Labs guides told you to return null for an unmet condition. The convention now is `none_detected` for category and text fields, and an empty value for scores. Don't use placeholder strings such as `N/A` or `none`.
:::

## Start from the decision

Write down the question the Dimensions have to answer, and who acts on it. *"Which delivery problems make customers cancel, so operations can fix the worst one first"* leads to very different Dimensions than *"What do customers talk about?"*.

## Read the data first

We suggest reading at least 100 to 200 records from across the whole file, not just the first page. Note the kinds of records, the shorthand people use, and which signals actually appear. A Dimension for something that never appears in the text will be `none_detected` everywhere.

## Design rules

- **One question per Dimension.** Don't fuse two things in one list ("late and damaged"). Make two Dimensions.
- **One boolean per product or feature.** When you track mentions, give each product or feature its own boolean, so a conversation that mentions two of them is counted for both.
- **Categories need an exit.** End every list with `none_detected`, and add an "other" value only if you'll read what lands in it.
- **Pair a judgement with a quote.** For anything subjective, such as a complaint reason or a churn risk, add a companion verbatim Dimension that copies the customer's exact words. It makes every label checkable.
- **Write the description as instructions.** Say what counts, what doesn't, and give two or three phrases from your data for each value.
- **Name the values the model tends to invent.** If you know it will be tempted by `neutral` or `general`, write "Do not use `neutral`; use `none_detected`."
- **Read only the customer when it matters.** In bot and chat transcripts, speaker labels such as "Maya (AI):" can leak into persona or brand Dimensions. Say "ignore speaker labels; score only from the customer's own words."
- **Mark priority when several apply.** For "the single most important reason", say which reason wins when there are two.
- **Text only.** Don't design a Dimension for something already in a column (rating, channel, date). Join that column instead.
- **Plan the crosses.** Think about which fields you'll read together. An `engagement_category` (what the customer is talking about) crossed with an `issue_category` (what needs to change to fix it) shows patterns neither field shows alone.

## Write the context

Every prompt has a `context`: the instructions sent with every conversation. Put it in this order:

1. What one record is and who wrote it, including who the incoming and outgoing sides are and what your organization does.
2. Any redaction markers the model will see, such as `[REDACTED]`.
3. A glossary of abbreviations and jargon from your data.
4. Common record shapes (an automated message, a one-word answer).
5. Terms that mean two things, and how to tell them apart.
6. Ground rules: use only what the text states, return `none_detected` when there's no signal.

## Common use cases

### Product and feature mentions

Detect when customers mention specific products, features or services. Define each one as its own boolean, so mentions that occur together are each captured.

### Issue and friction detection

Find when customers hit a problem, what the problem is, and how to categorize it for whoever fixes it. Combine a boolean with a reason, a verbatim and a root-cause category: the field block above.

### Customer journey stage

Label which stage of the customer lifecycle an interaction belongs to, such as onboarding, active use, renewal or churn risk, and watch how topics shift between stages.

### Satisfaction and quality scoring

Predict customer satisfaction, agent helpfulness or support quality on a defined scale, then compare across segments, periods and categories. See [Predicted scores](/dimensions/predicted-scores).

### Signals specific to your industry

Compliance mentions in financial services, safety concerns in healthcare, revenue opportunities in sales conversations, competitor mentions in product feedback.

## Custom prompts and standard Dimensions

Standard and custom Dimensions run on the same data, and the agent can cross them. Start with the standard set for a baseline, then build custom prompts to go deeper where it matters most. The differences are in the table on [What a Dimension is](/dimensions#standard-and-custom-dimensions); the one that matters here is that custom prompts are analyzed at session level only.

## Getting started

1. **Name the objective.** Which business questions do you need answered, and which decisions will the Dimensions support?
2. **Choose the fields.** Decide what to extract: topics, issues, products, scores, verbatims, or a mix.
3. **Bring your taxonomy.** If your organization already has categories, product lines or classification schemes, use them in your category lists.
4. **Write the prompt.** Turn on **Prompt Designer** in the agent's settings, then describe the Dimensions to the agent, or paste a prompt written to the [config reference](/dimensions/config-reference). The agent drafts the JSON with you.
5. **Test and refine.** Check it on a varied sample and adjust descriptions, category lists and conditional logic. See [Test before you run](/dimensions/test-before-you-run).
6. **Save it.** Ask the agent to save the prompt and choose the sources to apply it to. It then appears on the **Prompts** tab.
7. **Backfill it.** On the **Backfill** tab, run it over the conversations you already have. See [Backfill](/dimensions/backfill).

Your Dimension Labs team can also design prompts with you to fit your sources and goals. Email support@dimensionlabs.io.

## Worked example: a competitor Dimension on two years of history

A team wants to know how often customers mention a competitor, which one, and why, across two years of support tickets.

**1. Get the history in.** Upload the two years of tickets under **Data Sources > Unstructured data**, or send them to `/trackhistorical`. New tickets come in from a live integration. See [Upload a file](/data/upload-a-file).

**2. Design the block.** Turn on **Prompt Designer** in the agent's settings and ask the agent to draft one block of four fields. A boolean plus a name field counts every mention and still tells you which competitor:

| Field | What it extracts | Output type |
|---|---|---|
| `competitor_mentioned` | `true` if the customer names or clearly refers to a competitor | Boolean |
| `competitor_name` | Which competitor, from your own list: `acme`, `globex`, `initech`, `other_competitor`, `none_detected` | Fixed category |
| `competitor_reason` | Why the competitor came up, for example `cheaper plan elsewhere` | Dynamic label |
| `competitor_verbatim` | The customer's exact words about the competitor, at most 30 words | Verbatim quote |

The three dependent fields say *"If competitor_mentioned is false, return 'none_detected'."* The competitor names here are examples: use your own list. If a customer often names two competitors and you need both counted, use one boolean per competitor instead of `competitor_name`.

**3. Test it.** Ask the agent to label a varied sample: *"Pick 40 tickets from across the two years, including some that mention a competitor, and show me how this prompt labels them."* Fix the descriptions and test again. See [Test before you run](/dimensions/test-before-you-run).

**4. Save it.** Ask the agent to save the prompt and apply it to both sources: the upload with the history and the live integration. It appears on the **Prompts** tab, and from now on the live integration's new tickets are enriched with it every day.

**5. Backfill the two years.** Open the **Backfill** tab, choose the prompt, choose the history source (and the live source, for the days before you saved the prompt), and set the date range to cover the two years. Start it and watch its status on the tab.

**6. Check coverage.** When it has finished, ask the agent: *"How many tickets from [start date] to today have a value for competitor_mentioned, and how many have none?"* If part of the range is missing, backfill that gap. Then read a few `competitor_verbatim` values to check the labels hold up.
