What Are Natural Language Queries for Odoo?
Instead of building reports in Odoo's UI, writing SQL, or navigating complex filter menus, you simply ask a question in plain English: "What were our top 10 customers by revenue last quarter?" An AI agent translates this into the appropriate Odoo ORM query or SQL statement, executes it against your database, and returns a formatted answer.
This is not a gimmick — it is a genuine productivity multiplier. Business users who would never write SQL or build Odoo reports can get answers in seconds. Managers get instant dashboards without waiting for IT. Finance teams can explore data without learning the reporting interface.
How It Works
The Translation Pipeline
- Natural language input — User asks: "Show me unpaid invoices over $5,000 grouped by customer"
- Intent extraction — LLM identifies: model=account.move, filter=payment_state != paid AND amount_total > 5000, group_by=partner_id
- ORM query generation — Agent generates the Odoo domain and read_group call
- Execution — Query runs against the database via XML-RPC with read-only access
- Formatting — Results returned as a table, chart description, or narrative summary
# What the agent generates internally:
result = models.execute_kw(db, uid, pwd,
'account.move', 'read_group',
[[('payment_state', '!=', 'paid'),
('amount_total', '>', 5000),
('move_type', '=', 'out_invoice')]],
['partner_id', 'amount_total'],
['partner_id'],
orderby='amount_total desc')Example Queries and Results
Sales Questions
- "What is our total revenue this month?" →
sale.order read_groupwith date filter - "Which salesperson has the highest average deal size?" →
sale.order read_groupgrouped by user_id - "Show me all quotes pending for more than 7 days" →
sale.order searchwith date_order filter - "Compare Q1 vs Q2 revenue by product category" → Two
read_groupcalls with different date ranges
Inventory Questions
- "What products are below reorder point?" →
stock.warehouse.orderpointvs current quantity - "Show me inventory value by warehouse" →
stock.valuation.layer read_group - "Which items have not moved in 90 days?" →
stock.movewith date filter, exclude active items
Accounting Questions
- "What is our accounts receivable aging?" →
account.move.linewith date buckets - "Show me our monthly expenses by category" →
account.move.line read_group - "What is our cash position across all bank accounts?" →
account.journalwith balance computation
HR Questions
- "How many employees joined this quarter?" →
hr.employee search_count - "What is our leave balance by department?" →
hr.leave.allocation read_group - "Show me overtime hours by team this month" →
hr.attendanceaggregation
Building the Analytics Agent
Architecture
┌────────────────────────┐
│ User Question │
│ "Top 10 customers │
│ by revenue Q3" │
└──────────┬─────────────┘
▼
┌────────────────────────┐
│ LLM + Schema Context │
│ Knows Odoo models, │
│ field names, types │
└──────────┬─────────────┘
▼
┌────────────────────────┐
│ Query Generator │
│ Produces ORM domain │
│ or read_group call │
└──────────┬─────────────┘
▼
┌────────────────────────┐
│ Read-Only Execution │
│ XML-RPC with limited │
│ user permissions │
└──────────┬─────────────┘
▼
┌────────────────────────┐
│ Result Formatter │
│ Table, chart, or │
│ narrative summary │
└────────────────────────┘Key Implementation Details
- Read-only access — The analytics agent should NEVER have write access. Create a dedicated Odoo user with read-only permissions.
- Schema context — Feed the LLM your model field definitions so it knows the correct field names and types
- Query validation — Validate generated domains before execution to prevent injection
- Result limits — Always set a limit on returned records (default: 100) to prevent memory issues
- Caching — Cache frequent queries (daily revenue, monthly KPIs) to reduce database load
Common Challenges
Ambiguous Questions
"Show me sales" — which model? sale.order or account.move? What time period? The agent should ask clarifying questions when the query is ambiguous.
Computed Fields
Some Odoo fields are computed and not stored. The agent cannot use them in read_group or search domains. It must know which fields are stored and which need to be calculated from raw data.
Multi-Company Data
In multi-company setups, the agent must ensure queries respect company boundaries. Always include company_id filters.
Performance
Complex aggregation queries on large datasets can be slow. The agent should use read_group instead of reading individual records whenever possible, and warn users when queries touch large tables.
Security Considerations
- Use a dedicated read-only Odoo user for the analytics agent
- Restrict accessible models — not all data should be queryable (e.g., exclude user passwords, API keys)
- Log all queries for audit purposes
- Set query timeout to prevent long-running queries from affecting the server
Getting Started
To start querying your Odoo data with natural language, you need: a running Odoo instance (deploy on DeployMonkey for the easiest setup), an LLM with API access (Claude or GPT-4), and a connection script that bridges the LLM to Odoo's XML-RPC API. DeployMonkey's built-in AI agent already provides natural language data exploration as part of the platform.