# Making changes

> How writes work: simulate, show the diff, confirm with expected_version, handle version_conflict, and find every change in the audit log.

An assistant never changes your configuration in one step. Every configuration write is simulated first, you see the diff, and only a second call with the version you saw applies it. If someone else changed the zone in between, nothing is applied.

## The arguments of every write

| Argument | Meaning |
|---|---|
| `zone` | The zone, by domain or id |
| `reason` | Required, 1–500 characters. It is kept in the version and in the audit log |
| `confirm` | `false` by default: simulate. `true`: apply |
| `expected_version` | The zone version the simulation returned. Required with `confirm: true` |

## Simulate, review, confirm

1. **Simulate.** With `confirm` false (the default) the tool runs the write as a dry run and **applies nothing**. It returns `applied: false`, `current_version` (the zone's current version), `new_version`, the full plan (`plan`: diff and warnings) and what to call next. If you already pass `expected_version`, it is checked too.
2. **Show the diff.** The assistant must show the plan to you before confirming; the server's instructions and every tool description tell it so. Read the diff: it is exactly what will change.
3. **Confirm with the version.** With `confirm: true` the tool requires `expected_version` (without it, error `expected_version_required`) and sends it to the API as `If-Match`. If all goes well: `applied: true`, `version` (the new one) and `result` (the REST response).


## Version conflicts

If the zone changed after the simulation, nothing is applied: the tool answers `version_conflict` (HTTP 412) with the `current_version`, and the text asks to simulate again and review the new plan.

```json
{"error":{"code":"version_conflict","message":"the configuration changed: the current version is 2"},"current_version":2,"status":412}
```

## Example

**You:** add `www` pointing to 192.0.2.10 in example.com

1. The assistant calls `create_record` with `{"zone":"example.com","type":"A","name":"www","content":"192.0.2.10","reason":"add www from MCP"}` and receives:

   ```text
   Simulation only: nothing was applied. The zone is at version 1; applying creates version 2: 1 change:
   add "records[id=…]": {"content":"192.0.2.10",…,"name":"www.example.com",…,"type":"A"}
   To apply, call create_record again with the same arguments, confirm=true and expected_version=1.
   ```
2. It shows you the change, and you confirm.
3. It calls again with `"confirm": true, "expected_version": 1` and receives `Applied: the zone is now at version 2.`
4. A second write with `expected_version: 1` fails with `version_conflict (HTTP 412): the configuration changed: the current version is 2` and the hint to simulate again.


## Exceptions

- `add_zone` has no previous version: it is confirmed without `expected_version`.
- `revert_zone` simulates against the current version if `expected_version` is not given.
- `check_zone` and `agent_readiness_scan` change no configuration: no reason, no confirmation.
- `purge_cache`, `create_origin_cert`, `revoke_origin_cert` and the egress tools are not versioned configuration: `confirm=false` checks, `confirm=true` acts, without `expected_version`.

## Errors

A failure is a result with `isError: true` whose `structuredContent` is the API error envelope plus the HTTP status, with the same codes and messages as the API: `invalid` (with `field`), `reason_required`, `forbidden`, `not_found` (also for zones of another organization or outside the token's scope), `zone_exists`, `missing_certs`, `org_suspended`, `unavailable` and so on. Arguments that do not match the schema, such as an unknown record type or an empty reason, are rejected before the API is called.

## Audit log and history

Changes made over MCP are audited like API changes: actor `token:<id>` and, in the entry data, `"channel": "mcp"` plus `reason`, `version` and `from_version`. The zone's version history shows the same actor and reason. The assistant itself can read them with `audit_log`, `zone_history` and `zone_diff`.

## Undo a change

`revert_zone` restores the configuration of an earlier version (records, edge settings and rules) as a **new** version; it is destructive because the changes made after that version are undone. It follows the same simulate → confirm protocol, so you see the diff before anything is restored.
