Blog · Architecture
Building an AI Layer for ERPNext: Using Frappe as the Execution Engine
The principle behind Noviz's design is simple to state and easy to violate in practice: the LLM should reason about what a person is asking for, but it should never become the database, the reporting engine, or the visualization engine. ERPNext already does all three of those jobs well. The job left for an AI layer is to interpret intent and orchestrate ERPNext's own machinery correctly, not to rebuild it in a prompt.
Three layers, three jobs
The system splits cleanly into three responsibilities that never blur together:
- The LLM / AI layer interprets what the user wants, reasons about which operation actually answers it, selects the right tool, and decides the filters and metrics that operation needs. It never touches raw records directly.
- The Frappe execution layer does the actual work: DocType queries, aggregations, and analytics, all running under Frappe's own permission checks. This is where determinism lives, the same query with the same inputs always produces the same result, independent of anything the model does.
- ERPNext itself stays the single source of truth for the data, the relationships between records, and who is allowed to see what. The AI layer never gets its own separate copy of any of that.
Efficient reporting without shipping the whole dataset to the model
A tempting but expensive pattern is dumping a full dataset into the model's context so it can "reason" over it directly. Noviz's execution layer instead returns compact, already-computed representations: aggregated summaries, counts, and pagination metadata, which are what the model actually needs to reason correctly and answer in words. The complete underlying result set still exists and stays available for presentation, a table, a chart, a generated PDF, without ever being re-read into the model's own context to get there.
One query result, several presentations
Because tables, charts, and PDFs all consume the same underlying query result rather than three separately hard-coded AI features, the model's real job narrows to a single decision: what needs to be calculated, and how the result should be presented. Everything downstream of that decision is deterministic execution, not another round of generation.
Why this keeps token cost sane
Multi-step operations are where naive designs get expensive fast: fetch a large record set, put it in context, ask the model to summarize it, repeat. Separating retrieval, processing, and reasoning into distinct steps means large record sets never have to sit in the model's context just to get counted, filtered, or aggregated. The model reasons about compact results, not raw rows.
Permissions stay Frappe's job, not the AI layer's
Every operation executes under the requesting user's own authenticated Frappe session, so ERPNext's native permission system is the actual enforcement boundary, the same one already governing the desk UI. There's no separate permission model for the AI layer to get subtly wrong, because there isn't one; it inherits the real one.
The shape of the whole thing is: a user request reaches the LLM/AI layer, which picks a tool and call spec, hands it to Frappe's execution layer, which reads real ERPNext data under real permissions and returns a result, which then feeds a table, a chart, or a report/PDF as needed. That structure is what lets increasingly sophisticated natural-language workflows get built on top, while the execution underneath stays deterministic, permission-aware, and cheap in terms of what actually has to pass through the model.