Skip to content

Building a module without writing code

This whole tour assumes you write code. A good share of the people who deploy an ERP do not, and still have a precise business need to cover. The Builder is for them: describe a module in the interface and get it live, immediately.

It is not a degraded mode. A Builder module produces exactly the same objects as a hand-written one.

What a Builder module produces

Here, run on a real instance, is what creating a “bindery workshop” module with one model and three fields gives:

POST /api/v1/admin/builder/modules
-> {"ok": true, "name": "reliure", "models": ["reliure_chantier"]}

A real table, with all of the product’s system fields:

id name recu_le etat
created_at created_by_id updated_at updated_by_id version
deleted_at deleted_by_id kws_custom_data

Timestamps, authorship, the version number for concurrency, the recycle bin, and the column for fields added at runtime. You asked for none of it: that is what every Kewos model carries.

A complete API, immediately, with no restart:

POST /api/v1/reliure_chantier {"name": "Dune, broken spine", "recu_le": "2026-09-06"}
-> {"id":1, "etat":"recu", "version":1, "created_by_id":1, ...}

The state is recu: the default declared in the form was applied by the server.

A screen, generated from the model:

GET /api/v1/views/reliure_chantier/effective?kind=list
-> columns: id, name, recu_le, etat ... each with its type and i18n key

No view was written. It is the same engine that renders hand-written modules’ screens.

The AI proposes, a human confirms

The Builder can describe a module from a sentence, but it never installs one on its own. The flow has two steps:

  1. POST .../modules/suggest returns a proposal as declarative YAML, which you read;
  2. POST .../modules creates and loads what you confirmed.

That is deliberate. An AI that creates tables without review is an AI that creates wrong tables without review. The intermediate YAML is the checkpoint: it is readable, editable, and it is what counts, not the original sentence.

Disabling deletes nothing

POST .../modules/reliure/disable -> {"state": "disabled"}
the model's API : 404
the data in the database : still there

The module disappears from the interface and the API, and the table stays intact. Enabling puts it back:

POST .../modules/reliure/enable -> {"state": "loaded"}
the model's API : 200

Same posture as suspending a customer: you cut access, you do not destroy data. A delete with purge exists, separately, and it is an explicit decision.

What the Builder does not do

  • It does not run code. A Builder computed field is an expression in a closed grammar, not Python (rule 37). There is no eval, so there is no arbitrary execution to secure.
  • It does not bypass permissions. Creating a module requires the kws_builder_editor group, and the models it produces go through the same record rules and ACLs as any other.
  • It is not sandbox-only. Creating tables is still a schema change: in development it applies directly, in production it takes the per-module migration path (rules 11 and 12).