Loading
Alireza Shokrani

Digital Architect

AI Solutions Engineer

Founder @ CoreBiz ERP

GenAI & RAG Specialist

Full-Stack Systems Developer

Alireza Shokrani

Digital Architect

AI Solutions Engineer

Founder @ CoreBiz ERP

GenAI & RAG Specialist

Full-Stack Systems Developer

Solution

Transforming Static Enterprise Data into Decision Engines: Bridging ERP Workflows with Context-Aware AI Copilots

September 11, 2026 AI Engineering & Architecture
Transforming Static Enterprise Data into Decision Engines: Bridging ERP Workflows with Context-Aware AI Copilots

How to build the integration layer between static financial/inventory data and dynamic AI reasoning — where natural language prompts become validated, safe SQL/API calls inside complex organizational workflows.

Introduction — The ERP Data Paradox

Enterprise Resource Planning systems hold the most valuable data in the organization: financial ledgers, inventory records, procurement history, customer transactions. Yet this data is trapped in static forms — accessed through rigid UI screens, pre-built reports, and SQL queries that only technically-trained staff can write.

The result is a structural inefficiency:

  • Decision-makers need answers that require data they cannot access directly

  • Analysts spend hours writing queries instead of analyzing results

  • The data exists — but it does not act. It sits, waiting for a human to translate a business question into a technical query.

This is the gap that AI copilots for ERP are designed to close.

But the gap is not closed by simply connecting an LLM to a database. A naive “chat with your data” implementation is a liability in enterprise contexts. The engineering challenge is the integration layer — the middleware that translates natural language into validated, safe, auditable actions inside systems where errors carry financial and regulatory consequences.

This article is about architecting that layer:

From static data to decision engines — how to build context-aware AI copilots that safely bridge natural language and enterprise ERP workflows.

Part 1 — Why “Chat With Your Data” Fails in Enterprise

The demo is seductive: point an LLM at a database, ask a question, get an answer. But in an ERP context, naive text-to-SQL fails for predictable, architectural reasons.

The Failure Modes

Failure ModeConsequence
Schema hallucinationLLM invents tables/columns that don’t exist → query fails
Write operationsLLM generates UPDATE/DELETE → data corruption
Permission bypassQuery returns data the user shouldn’t see
Unbounded executionQuery scans entire tables → database lock → production outage
No audit trailCannot explain who asked what, or what data was accessed 
Prompt injectionMalicious input manipulates the agent into unauthorized actions 

An LLM without guardrails is not a copilot. It is an uncontrolled actor with database credentials.

The OWASP Framing: LLM03 — Excessive Agency

The OWASP Top 10 for LLM Applications 2026 elevated Excessive Agency (LLM03) to reflect the growing risk of AI systems that can access data and take actions. In ERP contexts, this is not theoretical — a copilot with write access to financial records is a high-risk AI system under the EU AI Act .

Engineering implication: The integration layer must be designed with the assumption that the LLM will attempt unauthorized actions — and the system must prevent them, not rely on prompts to do so.

Part 2 — The Safe Architecture: Layers of Containment

The production architecture for ERP AI copilots requires defense in depth — multiple layers of validation between the user’s natural language and the database.

┌─────────────────────────────────────────────────────────────────────────────┐
│                         USER INTERFACE LAYER                                │
│              (Chat widget, natural language input)                          │
├─────────────────────────────────────────────────────────────────────────────┤
│                         INTENT & ROUTING LAYER                              │
│         (Classify query: read-only vs. action, simple vs. complex)          │
├─────────────────────────────────────────────────────────────────────────────┤
│                         SCHEMA CONTEXT LAYER                                │
│         (Retrieve relevant tables/columns — NOT full schema)                │
├─────────────────────────────────────────────────────────────────────────────┤
│                         LLM GENERATION LAYER                                │
│              (Generate SQL/API call from context + question)                │
├─────────────────────────────────────────────────────────────────────────────┤
│                         SAFETY VALIDATION LAYER                             │
│    (SQL Guard: SELECT-only, schema check, LIMIT injection, timeout)         │
├─────────────────────────────────────────────────────────────────────────────┤
│                         PERMISSION ENFORCEMENT LAYER                        │
│              (User's role → allowed tables, rows, fields)                   │
├─────────────────────────────────────────────────────────────────────────────┤
│                         EXECUTION SANDBOX                                   │
│              (Read-only connection, row limits, query timeout)              │
├─────────────────────────────────────────────────────────────────────────────┤
│                         AUDIT & OBSERVABILITY                               │
│         (Every query, every result, every user — logged, traceable)         │
└─────────────────────────────────────────────────────────────────────────────┘

Architectural principle: The LLM is one component in this pipeline — not the decision-maker. Its output is treated as untrusted input until validated by deterministic layers .

Part 3 — The SQL Safety Layer: SELECT-Only Validation

The most critical safety control is SQL query validation before execution.

The SELECT-Only Guard

Production text-to-SQL systems enforce a strict rule: only read queries are allowed.

Allowed:    SELECT ... FROM ...
Blocked:    INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE
Blocked:    GRANT, REVOKE, EXEC, CALL
Blocked:    Multiple statements (semicolon-delimited)

Implementation pattern:

import sqlglot

def validate_query(sql: str) -> tuple[bool, str]:
    """Validate SQL is a single SELECT statement."""
    try:
        parsed = sqlglot.parse_one(sql)
    except Exception as e:
        return False, f"SQL parse error: {e}"
    
    # Check statement type
    if not isinstance(parsed, sqlglot.exp.Select):
        return False, f"Only SELECT statements allowed. Got: {type(parsed).__name__}"
    
    # Check for forbidden keywords in raw SQL
    forbidden = ['INSERT', 'UPDATE', 'DELETE', 'DROP', 'ALTER', 
                 'CREATE', 'TRUNCATE', 'GRANT', 'REVOKE']
    upper_sql = sql.upper()
    for kw in forbidden:
        if kw in upper_sql:
            return False, f"Forbidden keyword detected: {kw}"
    
    # Ensure LIMIT exists (inject if missing)
    if not parsed.args.get('limit'):
        parsed = parsed.limit(1000)  # Default safety limit
    
    return True, parsed.sql()

Why sqlglot: Parsing the SQL into an AST — rather than string matching — catches obfuscated attacks (comments, whitespace manipulation, case variation) that regex-based filters miss .

LIMIT Injection

Even SELECT queries can cause damage if they scan entire tables:

-- User asks: "Show me all invoices"
-- LLM generates: SELECT * FROM invoices
-- Guard transforms: SELECT * FROM invoices LIMIT 1000

Engineering rationale: A query returning 10 million rows will exhaust memory, saturate the network, and block the database. LIMIT injection is a hard safety requirement .

Execution Sandboxing

The database connection used for AI queries should be read-only and isolated:

ControlImplementation
Connection typeRead-only replica or role with SELECT-only privileges
Statement timeoutSET statement_timeout = '5s' — kill long-running queries
Row limitMaximum rows returned per query
Resource isolationSeparate connection pool from application traffic 

Part 4 — Schema Context: The Retrieval Problem in Text-to-SQL

The LLM cannot generate valid SQL without knowing the schema. But passing the entire schema to the LLM creates two problems:

  • Token cost — enterprise ERP schemas can have hundreds of tables

  • Accuracy degradation — irrelevant tables confuse the model

Schema Linking via RAG

The solution is schema retrieval — dynamically selecting the relevant tables and columns for each query:

User Question: "What's the current stock level for SKU ZX-447?"

Step 1: Retrieve relevant schema
  → Tables: inventory, products, warehouses
  → Columns: sku, quantity, warehouse_id, reorder_level

Step 2: Build context for LLM
  → "Available tables: inventory(sku, quantity, warehouse_id), 
     products(sku, name, category), ..."

Step 3: LLM generates SQL with correct table/column names

Implementation: Index table and column descriptions as embeddings; retrieve top-k relevant schema elements for each query .

The Knowledge File Pattern

Production systems augment schema retrieval with domain knowledge — synonyms, business terms, and example queries:

# knowledge.yaml
synonyms:
  "stock level": "inventory.quantity"
  "reorder point": "inventory.reorder_level"
  "SKU": "products.sku"

example_queries:
  - question: "What's the stock for SKU X?"
    sql: "SELECT quantity FROM inventory WHERE sku = 'X'"

Engineering impact: The knowledge file bridges the semantic gap between how business users speak and how the database is structured .

Part 5 — Permission Enforcement: Row-Level Security for AI

A critical — and often overlooked — requirement: the AI copilot must respect the same permissions as the user .

The Permission Problem

User A (Sales Manager): Can see all customer data
User B (Sales Rep): Can see only their assigned customers
User C (Finance): Can see all financial data, no customer PII

Naive copilot: Executes same query for all users
→ Data leakage

Role-Aware Query Rewriting

The integration layer must inject permission filters into every query:

-- User asks: "Show me all orders"
-- LLM generates: SELECT * FROM orders
-- Permission layer rewrites based on user role:

-- Sales Rep (user_id=42):
SELECT * FROM orders WHERE sales_rep_id = 42

-- Regional Manager (region='EMEA'):
SELECT * FROM orders WHERE region = 'EMEA'

-- Admin:
SELECT * FROM orders

Implementation pattern:

  • Define permission mappings (role → allowed tables, row filters, column masks)

  • Before execution, parse the LLM-generated SQL and inject WHERE clauses

  • For column-level security, replace sensitive columns with NULL or masked values 

Field Whitelisting

Beyond row filters, column-level access control prevents PII exposure:

Blocked columns (per configuration):
  - password, api_key, token
  - ssn, tax_id, bank_account
  - salary (unless HR role)

The permission layer validates that no blocked column appears in the generated SQL .

Part 6 — The Audit Layer: Compliance as Architecture

Under the EU AI Act, AI systems operating in financial and employment contexts are high-risk and must maintain audit logs that allow post-hoc verification of decisions .

The Audit Requirement

For every AI-generated query, the system must log:

FieldPurpose
User identityWho asked
Natural language promptWhat they asked (raw)
Generated SQLWhat was executed
Validation resultWas it blocked? Why?
Permission contextWhat filters were applied
Execution resultRows returned, execution time
TimestampWhen it happened

Engineering rationale: In a regulated context, “the AI said so” is not an acceptable answer. The system must be able to reconstruct the reasoning chain .

Tamper-Evident Logging

For high-risk contexts (credit decisions, employment recommendations), logs should be cryptographically signed:

import hmac
import hashlib

def sign_audit_record(record: dict, secret: bytes) -> str:
    """Generate HMAC signature for audit tamper-evidence."""
    canonical = json.dumps(record, sort_keys=True)
    return hmac.new(secret, canonical.encode(), hashlib.sha256).hexdigest()

Why HMAC: Ensures audit records cannot be altered retroactively without detection — a requirement for regulatory compliance .

Part 7 — Agent Orchestration: When Queries Become Actions

Not every question is a simple read. Enterprise copilots increasingly need to execute multi-step workflows:

User: "Evaluate the bids for RFQ 000012 and recommend a supplier."

This requires:
  1. Read RFQ data (retrieval)
  2. Read supplier bid data (retrieval)
  3. Read evaluation criteria (retrieval)
  4. Score each bid (reasoning)
  5. Generate recommendation (reasoning)
  6. Present for human approval (HITL gate)
  7. Create purchase order (action — requires approval)

The LangGraph Pattern for ERP Agents

LangGraph provides the stateful orchestration required for multi-step ERP workflows:

┌─────────────┐
│   Router    │ ← Classify query type
└──────┬──────┘
       │
       ▼
┌─────────────┐
│  Retriever  │ ← Fetch relevant context
│  (Schema +  │
│   Data)     │
└──────┬──────┘
       │
       ▼
┌─────────────┐
│  Reasoner   │ ← Generate SQL / plan
└──────┬──────┘
       │
       ▼
┌─────────────┐
│  Validator  │ ← SQL Guard + Permission Check
└──────┬──────┘
       │
       ├── BLOCKED → Return error to user
       │
       ▼ (valid)
┌─────────────┐
│  Executor   │ ← Run query in sandbox
└──────┬──────┘
       │
       ▼
┌─────────────┐
│  Formatter  │ ← Present results
└─────────────┘

Human-in-the-Loop for Write Operations

For actions that modify data (create invoice, update inventory), a human approval gate is mandatory:

Agent proposes action: "Create purchase order for 500 units from Supplier X"
       │
       ▼
┌─────────────────┐
│  Human Review   │ ← User must explicitly approve
│  (Approval UI)  │
└────────┬────────┘
         │
    APPROVED → Execute via ERP API
    REJECTED → Log rejection, no action

Engineering rationale: The EU AI Act requires human oversight for high-risk AI systems. The approval gate is not a UX feature — it is a compliance requirement .

Part 8 — The Complete Integration Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                              ERP SYSTEM                                     │
│  ┌─────────────────┐  ┌─────────────────┐  ┌─────────────────────────────┐ │
│  │  Financial DB   │  │  Inventory DB   │  │  Business Logic (APIs)      │ │
│  └────────┬────────┘  └────────┬────────┘  └──────────────┬──────────────┘ │
└───────────┼────────────────────┼──────────────────────────┼────────────────┘
            │                    │                          │
            ▼                    ▼                          ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                         INTEGRATION MIDDLEWARE                              │
│  ┌───────────────────────────────────────────────────────────────────────┐ │
│  │  SAFETY LAYER: SQL Guard (SELECT-only) │ Permission Injector │ Audit  │ │
│  └───────────────────────────────────────────────────────────────────────┘ │
│  ┌───────────────────────────────────────────────────────────────────────┐ │
│  │  INTELLIGENCE LAYER: Schema Retriever │ LLM Orchestrator │ Validator  │ │
│  └───────────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
            │
            ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                         AI COPILOT INTERFACE                                │
│              Chat UI │ Approval Gates │ Result Presentation                 │
└─────────────────────────────────────────────────────────────────────────────┘
            │
            ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│                              USERS                                          │
│         Finance │ Operations │ Management │ Procurement                     │
└─────────────────────────────────────────────────────────────────────────────┘

Technology Stack (Reference)

LayerTechnology Options
OrchestrationLangGraph, LangChain 
SQL Validationsqlglot (AST parsing) 
Schema Retrievalpgvector, Elasticsearch 
LLMOpenAI, Anthropic, local (vLLM)
AuditPostgreSQL, HMAC signing 
ERP IntegrationREST APIs, MCP servers 

Part 9 — When to Use This Architecture (and When Not To)

Build an ERP AI copilot with this architecture when:

  • ✅ Users need natural language access to ERP data

  • ✅ Safety and auditability are non-negotiable

  • ✅ The ERP has well-defined APIs or database access

  • ✅ Role-based permissions must be enforced

  • ✅ Compliance (EU AI Act, SOX, GDPR) applies

  • ✅ The organization has engineering capacity to maintain the middleware

Do NOT build it when:

  • ❌ The ERP already provides adequate reporting for user needs

  • ❌ No dedicated engineering team exists to maintain safety layers

  • ❌ The use case involves high-stakes autonomous decisions without human oversight

  • ❌ Latency requirements cannot accommodate LLM inference + validation

A copilot without safety layers is not an assistant. It is a liability with database credentials.

Conclusion — From Data Storage to Decision Infrastructure

ERP systems store data. They do not, by themselves, generate decisions.

The integration layer between static data and dynamic AI reasoning is where the value is created — or where the risk is introduced. The difference is architectural discipline:

  • SQL safety is not optional — it is the boundary between a copilot and a threat

  • Permission enforcement is not a feature — it is a security requirement

  • Audit logging is not overhead — it is compliance infrastructure

  • Human oversight is not friction — it is the legal basis for deployment

The ERP already knows the answer. The copilot’s job is to ask the right question — safely, auditable, and within the boundaries of what the user is allowed to know.

Author’s Note

This article reflects architectural patterns developed while building Binesh AI — a custom AI framework with RAG pipelines, agent orchestration, and enterprise integration layers. For collaboration on ERP AI copilot architecture, reach out via the contact page.

Tags:
Write a comment