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

# Variables and parameters

> Placeholders in content: variables are filled from the user with a required fallback; parameters are facts you fix that every variant reproduces.

Arm content can contain placeholders written as `{{name|fallback}}`. Two things fill them, and they are kept apart on purpose.

```json theme={null}
{
  "control": "Hi {{first_name|there}}, your {{plan}} trial ends in {{days_left}} days",
  "variables": ["first_name"],
  "parameters": { "plan": "Pro", "days_left": 14 }
}
```

## Variables: filled from the user

A **variable** is substituted at decision time from the user's stored `identifiers` and `attributes`: `{{first_name|there}}` renders `Hi Alice` for a user whose `first_name` is known and `Hi there` otherwise. The fallback after the `|` is required, because an empty substitution renders broken copy.

`variables` lists the names content may reference. On the first call for an element it defaults to the identifier and attribute keys you sent on that call, so any of those is available at once. Later calls update the list in place; existing arms keep rendering correctly under any list because every placeholder has a fallback. Names match `^\w+$`.

Variables are how content is personalized without the identifiers ever reaching the model: an email address can appear in copy and still never be a feature.

## Parameters: facts you fix

A **parameter** is a fact about the content that every variant must reproduce verbatim: a plan name, a price, a date, a count. Curious substitutes it into the placeholder exactly as declared and generates variants that keep it. Keys match `^\w+$`; values are any JSON, but only non-null scalars are substituted, while structured values are visible to generation as context.

All parameters are required-display by definition. A fact that variants may mention or omit is not a parameter; put it in `instructions` instead.

Parameters are fixed for the experiment's life. Any change supersedes the experiment, because the arms were generated against the declared facts. The history of a parameter is the chain of experiments.

## The two namespaces never overlap

A name is either a variable or a parameter. A declaration that lists the same name in both is a `400`.

## Where substitution happens

In the `content` of every decision response, before it reaches you. The stored arm keeps its placeholders. See [Serve a decision](https://docs.trycurious.ai/guides/decide.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.