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

# Variables

Most of what a [knowledge article](/docs/how-membrane-works/knowledge) says is prose. Some of it is a specific value the work actually turns on — how long to wait before following up, the amount above which something needs a second approval, which day of the month the reporting period closes. A variable lifts that value out of the sentence and makes it a thing in its own right: named, typed, and traceable to whoever put it there.

That traceability is the point. Half the numbers a job runs on are your decisions, and half are assumptions Membrane started with because nobody had answered yet. A variable makes the difference visible everywhere the number is used, instead of leaving it buried in a paragraph.

## Assumptions and answers

There are exactly two states a variable can be in, and the difference is simply whether anyone has answered it:

* **An assumption** — nobody has set a value. The variable reads as its declared `default`, and its `description` says what would settle it.
* **An answer** — someone stored a value. It stands on its own, and the article's history says who set it and when.

Nothing records this as a separate label, because nothing needs to. An unanswered variable has no stored value at all; that absence *is* the assumption. It also means an assumption can never be mistaken for someone's decision — there is no stored value to mistake it for.

## Declaring a variable

Declarations live on the article and edit with it. They are standard JSON Schema, with the article's variables as properties:

```json theme={null}
{
  "type": "object",
  "properties": {
    "followUpAfterDays": {
      "type": "integer",
      "title": "Follow up after (days)",
      "description": "How long should we wait for a reply before following up?",
      "minimum": 1,
      "maximum": 60,
      "default": 5
    }
  },
  "propertyOrder": ["followUpAfterDays"]
}
```

Each declaration is an ordinary data schema — the same schema vocabulary Membrane uses for commands, connectors, and data tables — so a variable can be a scalar, an `object` with named `properties`, or an `array` of `items`. The fields you will use most:

* **`type`** — `string`, `number`, `integer`, `boolean`, `object`, or `array`. A declaration may also omit it to accept any shape, or list several acceptable types.
* **`title`** is the human name and leads the row wherever the variable is shown. A unit belongs here, by convention: "Follow up after (days)".
* **`description`** says what the value is, and doubles as the question that would settle it.
* **`enum`**, **`minimum`** / **`maximum`**, **`minLength`** / **`maxLength`**, and **`format: "date"`** constrain what may be written. Every write is checked against the declared type and these constraints, and a value that fails is rejected rather than stored.
* **`properties`** (for objects) and **`items`** (for arrays) describe the nested shape a structured value follows.
* **`default`** is the assumption to start from.
* **`propertyOrder`** is the order the variables are displayed in.

## A default has to say what would settle it

An assumption nobody is being asked about isn't a default; it's just a number someone made up. So a `default` is only accepted when its declaration carries a `description`, and an article that breaks that rule is rejected. Answering is what turns the value from Membrane's into yours.

If a value genuinely has no question behind it — a limit published by the service you work through, a floor below which a measurement means nothing — then it isn't a default. Set it as a value.

## Answering, changing, and clearing

Writing a value validates it against the declaration and records the change in the article's history alongside everything else that changed in the same edit.

* **Answering** stores the value. The variable stops being an assumption even if the value you chose happens to equal the default.
* **Clearing** — writing `null` — removes the stored value, and the variable goes back to being an assumption reading its default. There is no separate "reset" action; deleting the value is the reset.
* **Writing the same value again does nothing.** No new version, no change of authorship. Only a real change is recorded.

An empty string is an ordinary string value, not a way of clearing.

A variable is never locked to whoever wrote it last. Anyone who can edit the article can answer.

## Changing the declaration

Declarations are edited like any other part of an article, and the values reconcile to the new declaration:

* A variable that is still declared keeps its value, re-checked against the new rules — a value the new rules reject fails the edit.
* A variable that is no longer declared loses its value.
* A newly declared variable starts as an assumption on its `default`, and needs its description like any other default.

## History

Variables live in the article's [version history](/docs/how-membrane-works/knowledge) the same way its prose does. Each version holds the whole article as it stood — title, body, declarations, and values — so "who set this number, and when" is answered by the same record that answers "who wrote this paragraph". One edit is one version, however many variables it touched.

## Reading variables

Declarations and current values come back with the article, over the API and to the agent when it reads one. A variable with no stored value reads as its declaration's `default`, so the agent always has an effective value to work with, and can tell an assumption from an answer by whether a value was stored at all.
