data_patch_schema
Change a datastore's schema BY KEY, without rewriting the whole field list. Prefer this over data_set_schema for any EDIT: set REPLACES, so rebuilding the list from what you know silently drops the per-field settings you did not restate (labels, help, max_length, pattern, width, options) — same call, same success, no way to tell. fields merges by key: listed properties overwrite, unlisted ones are PRESERVED, unknown keys are appended. remove: ["key", …] is the explicit deletion (a wrong key is refused, never silently ignored) — it takes the field out of the SCHEMA; to erase the column from the rows' DATA, that is data_drop_column. remove_attrs: {"column": ["attr", …]} takes attributes off columns that STAY — merging only completes, so this is the only way to drop one declaration without reposting the whole schema; an unknown column or attribute is refused, and key cannot be dropped. key/new_rows change the head keys, untouched when omitted — key names the BUSINESS KEY: A write that DESIGNATES by the key — key= passed to the call (a batch, or a single row naming this key), or any write without id on a CLOSED table — modifies the row of an existing key value and creates a new one. A write that ADDS (neither id nor key=) with a key value already present is REFUSED unless it passes upsert=true, which merges onto that row — data_write, REST and oto_upload_url alike. The key never duplicates: its UNIQUE index guarantees it. new_rows: "reject" CLOSES the table (a write designating no existing row is refused), "create" reopens it. ⚠️ A column the schema does NOT declare is REFUSED at write, on EVERY table: declaring a column (data_patch_schema(fields=[{"key": …}])) is the ONLY way to add one. ⚠️ The declared format is a CONTRACT on every table: top-level options are enforced, the SHAPE of text/url/object/list/enum values is checked, an unknown layer is refused and a declared sub-record refuses an attribute it does not declare. There is NO head setting for it any more: unknown_columns was REMOVED on 2026-10-05 and is refused — columns and values are always checked. To ADD a column, list it in fields ({"key": …, "type": …}): it is appended, the others are untouched; to ACCEPT a value its options refuse, list the column again with the full options. key_required was REPLACED by new_rows on 2026-10-02 (refused with its exact equivalent); strict, unknown_fields and unknown_columns are refused: no head setting decides what is checked any more. Per field, readonly: true locks a value once SET (layers such as .comment stay open); a cell with NO value — key absent, null or "" — can still be filled once, so a column locked after its import is not empty for good, while @empty counts as set — the table's OWNER, or whoever GOVERNS it, can still replace such a value with data_write(readonly_override=true), for that one call and journaled, so locking a column never means nobody can correct it again. On the field that carries lifecycle, the block merges KEY BY KEY and its transitions merge STATE BY STATE: naming one state leaves the others alone, so declaring a way OUT of a terminal state is one line and costs nothing else. Each state maps to a LIST, even for one destination — transitions: {"won": ["lost"]}; a bare string is refused. Taking one out is explicit — transitions: {"lost": null} drops that state's exits, lifecycle: {transitions: null} drops the whole table. labels (the displayed name of each state) merges STATE BY STATE too: lifecycle: {labels: {"lost": "Lost"}} names that step and keeps the others' labels, {"lost": null} drops that one label. A key that its level does not admit (head, column, sub-field, of, lifecycle) is REFUSED when the patch posts or changes it — the refusal names the path, the key and the closest known one; an unknown key ALREADY stored and left untouched does not block a patch of another column, and remove_attrs takes it off. Your own annotations go in meta (an object, at every level, carried as is, never read, at most 4096 bytes as JSON; a patch replaces it whole); help text goes in description (note, help, hint, placeholder are refused). Field ORDER is never reshuffled. Returns the resulting schema plus {added, updated, removed} and any warning the schema raises, and existing_violations: per path (contacts[].email), how many rows ALREADY IN PLACE break the resulting schema, a sample of their ids and the consequence (blocking_rows accept no write at all until fixed) — clean them before arming the guard. existing_violations_scope.complete: false means the row cap was hit: the counts are floors.
Tool call template
Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.
{
"id": 1,
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"arguments": {
"datastore": "<datastore>"
},
"name": "data_patch_schema"
}
}Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| key | No | ||
| _org | No | ||
| _group | No | Équipe (id) de CET APPEL, sous son org parente. | |
| fields | No | Merges BY `key`: the properties you list overwrite, the ones you omit are PRESERVED, an unknown key is appended. Send only what changes. | |
| remove | No | Keys to take out of the SCHEMA (a key that is not there is refused, never silently ignored). It does not touch the rows' DATA — that is `data_drop_column`. | |
| _run_id | No | OBLIGATOIRE à chaque appel dès `run_start` ou `data_claim_next` : sans lui, l'écriture sur une ligne réservée est refusée. Hérité seulement si le serveur tient un run actif — n'y compte pas. | |
| _project | No | Projet (id) de CET APPEL — jeton PRIMAIRE. `oto_project(op='list')`. | |
| new_rows | No | Whether a NEW row may be born: `"create"` (the default) or `"reject"` — CLOSES the table: a write designating no existing row (no `id`, no key value the table already carries) is refused; needs `key`. Omitted leaves it untouched. | |
| datastore | Yes | ||
| remove_attrs | No | Attributes to take off columns that STAY: `{"column": ["attr", …]}`. Merging only completes, and `remove` drops a whole column — without this, taking one attribute off meant reposting the entire schema, which silently drops every declaration you did not resend. An unknown column or attribute is refused, never silently ignored. `key` cannot be taken off: it is the column's identity, not one of its properties. |