# Update Schema

Use this when the app already exists and the task is only about fields.

## Minimal sequence

1. `app_resolve`
2. `app_get_fields`
3. `app_schema_apply`

## Example

Do not add platform system fields as form controls: `数据ID`, `编号`, `申请人`, `申请时间`, `创建人`, `创建时间`, `提交人`, `提交时间`, `更新时间`, `更新人`, `当前流程状态`, `当前处理人`, `当前处理节点`, `流程标题`. They are generated by Qingflow; use readback/list fields when you need them.

Field patch rules:

- Re-read fields first, then choose `add_fields`, `update_fields`, or `remove_fields`. If a field already exists, use `update_fields` instead of adding a duplicate.
- Drafts may use intuitive type aliases: `multiline -> long_text`, `select -> single_select`, `checkbox -> multi_select`, `currency -> amount`, `mobile -> phone`. Readback canonical types are normal and do not prove a failed update.
- `title` and `label` are accepted aliases for `name`, but the preferred public key is `name`.
- Keep exactly one top-level data title field after the patch. `as_data_cover` is optional and only valid on top-level `attachment`.
- Select fields must keep a clear `options` set. Sample data and filters should use those option labels or ids.
- Relation fields must use `target_app_key` for existing apps, or `target_app_ref` only in same-batch app creation. `display_field` and `visible_fields` are selector objects such as `{"name": "客户名称"}`, not bare strings.
- Do not impose a one-relation-field limit when updating schema; add the relation fields the business needs and rely on backend validation/readback.

Read current fields first:

```json
{
  "tool_name": "app_get_fields",
  "arguments": {
    "profile": "default",
    "app_key": "APP_123"
  }
}
```

Apply the patch:

```json
{
  "tool_name": "app_schema_apply",
  "arguments": {
    "profile": "default",
    "app_key": "APP_123",
    "publish": true,
    "add_fields": [
      {"name": "跟进日期", "type": "date"},
      {"name": "数据封面", "type": "attachment", "as_data_cover": true}
    ],
    "update_fields": [
      {"selector": {"name": "金额"}, "set": {"name": "订单金额", "required": true}},
      {"selector": {"name": "客户名称"}, "set": {"as_data_title": true}}
    ],
    "remove_fields": [
      {"name": "旧字段"}
    ]
  }
}
```

## Common failures

### `FIELD_NOT_FOUND`

The selector did not match current schema. Re-read with `app_get_fields` and use `name`, `field_id`, or `que_id`.

### `DUPLICATE_FIELD`

The field already exists with a different shape. Switch from `add_fields` to `update_fields`.

### `SCHEMA_APPLY_FAILED`

Treat it as uncertain write state. Read back with `app_get_fields` before retrying.

## Notes

- `title` and `label` are accepted aliases for `name`
- `textarea -> long_text`
- `multiline` / `multiline_text -> long_text`
- `currency -> amount`
- `mobile -> phone`
- `select/radio -> single_select`
- `checkbox -> multi_select`
- `as_data_title: true` marks the app data title; the final form must have exactly one top-level data title field
- `as_data_cover: true` marks the app data cover; the cover is optional and must be a top-level `attachment` field
- `数据ID`, `编号`, applicant/creation/update time, and workflow status fields are system-generated and must not appear in `add_fields`
