# Extensions

> The ext object, namespaces, and how a consumer treats data it does not know.

Every entity in a document MAY carry an `ext` object. It holds what a producer knows that the specification does not cover, such as a queue priority, a trace id or a framework's own state name, without inventing new fields.

```json
{
  "id": "implement.a1",
  "node": "implement",
  "status": "done",
  "cost": {
    "input_tokens": 12000, "output_tokens": 18500, "basis": "allocated",
    "ext": { "dev.loopmath.logmatch": { "tier": "heuristic" } }
  },
  "ext": {
    "com.example.scheduler": { "queue": "gpu", "priority": 2 }
  }
}
```

## Namespaces

- An `ext` key SHOULD begin with a reverse-domain namespace the producer controls, such as `com.example.` for a tool at example.com, so that two producers never collide.
- A consumer MUST ignore namespaces it does not understand, at every level, and MUST NOT fail on them.
- A producer SHOULD put its own data in `ext`, not in new fields next to the specification's.
- Under the `full` [privacy profile](https://orchestrationcontextprotocol.io/specification/0.3/privacy), text MAY appear in `ext`; under `metadata_only`, `ext` is bound by the same rule as every other field.

| Prefix | Owner | Status |
|---|---|---|
| `io.orchestrationcontextprotocol.` | The specification | The specification's own namespace. |
| `dev.loopmath.` | loopmath | loopmath's namespace from 0.3. |
| `dev.dagr.` | loopmath, before its rename | Still read through 0.4, with warning [W182](https://orchestrationcontextprotocol.io/specification/0.3/conformance#w182). Write `dev.loopmath.`. |
| `ocp.` | none | Retired. An error ([E181](https://orchestrationcontextprotocol.io/specification/0.3/conformance#e181)); write `io.orchestrationcontextprotocol.`. |
| `dagr.` | none | Retired. An error ([E181](https://orchestrationcontextprotocol.io/specification/0.3/conformance#e181)); write `dev.loopmath.`. |

## Extensions that change meaning

An extension is ignorable by definition, with one exception so far: `control.ext["dev.loopmath.gate_rules"]` maps a gate to a rule other than its role's default. A different gate rule changes what ran, so this key is part of the [configuration id](https://orchestrationcontextprotocol.io/specification/0.3/configuration#configuration-id). A reader that ignores it can still read the document, but cannot recompute the id.

loopmath writes a few other keys that a reader may find useful:

| Key | Where | What it records |
|---|---|---|
| `dev.loopmath.gate_rules` | `control.ext` | Non-default gate rules; part of the configuration id. |
| `dev.loopmath.migration` | `run.ext` | `{"from": <version>}` on a document that `loopmath ocp migrate` upgraded. |
| `dev.loopmath.inferred` | `configuration.ext` | The confidence of a workflow inferred from logs, with `tier: heuristic`. |
| `dev.loopmath.logmatch` | `cost.ext` | A cost matched to its attempt from logs by a heuristic, which allows `basis: allocated` ([E171](https://orchestrationcontextprotocol.io/specification/0.3/conformance#e171)). |

## From extension to field

When several producers write the same kind of data in their own namespaces, it is a candidate for the core format. A [proposal](https://orchestrationcontextprotocol.io/community/proposals) can promote it to a field in a minor version; producers then write the field and MAY keep writing the extension for older readers.
