Skip to content

RAG for Odoo: Building a Knowledge-Aware Coding Agent

DeployMonkey Team · March 22, 2026 13 min read

Why RAG Matters for Odoo

Large language models generate impressive Odoo code — until they get the version wrong. Claude might generate attrs={'invisible': [...]} for an Odoo 19 project because it saw that pattern more in its training data. GPT-4 might use <tree> tags for an Odoo 18 project. The solution is RAG: Retrieval-Augmented Generation, where the LLM is given relevant, version-specific documentation at query time.

With RAG, your Odoo coding agent does not rely on its training data for API details. It retrieves the correct documentation for your specific version and uses that as context. The result: accurate code for Odoo 14, 15, 16, 17, 18, or 19 — every time.

The RAG Architecture for Odoo

┌──────────────────────────────────────┐
│  Developer Query                      │
│  "Create a computed field in Odoo 19  │
│   that calculates order total"        │
└──────────┬───────────────────────────┘
           ▼
┌──────────────────────────────────────┐
│  Retrieval Layer                      │
│  1. Parse query → extract version,   │
│     topic (ORM, computed fields)      │
│  2. Search vector DB for relevant     │
│     Odoo 19 ORM documentation        │
│  3. Return top-k chunks              │
└──────────┬───────────────────────────┘
           ▼
┌──────────────────────────────────────┐
│  Generation Layer (LLM)               │
│  System: "You are an Odoo 19 dev."   │
│  Context: [retrieved KB chunks]       │
│  Query: [developer question]          │
│  → Generates version-correct code    │
└──────────────────────────────────────┘

Building the Knowledge Base

Source Material

For a comprehensive Odoo RAG system, index these sources:

  • Version-specific KB files — ORM API, fields, views, security, controllers, reports, testing, performance, patterns, anti-patterns (66,000+ lines across Odoo 14-19)
  • Official Odoo documentation — Developer docs, reference manual
  • Odoo source code — Key model definitions from the Odoo codebase
  • Migration guides — Breaking changes between versions

Chunking Strategy

Odoo documentation should be chunked by topic, not by arbitrary character count:

  • Per-section chunks — Each H2 section in a KB file becomes one chunk
  • Code block preservation — Never split a code example across chunks
  • Metadata tags — Each chunk tagged with: version, edition (community/enterprise), topic, model references
# Example chunk metadata:
{
    "chunk_id": "v19_orm_computed_fields",
    "version": "19.0",
    "edition": "community",
    "topic": "ORM API",
    "subtopic": "Computed Fields",
    "models_referenced": ["fields.Char", "fields.Integer", "api.depends"],
    "text": "In Odoo 19, computed fields use the @api.depends decorator..."
}

Indexing with a Vector Database

import chromadb
from sentence_transformers import SentenceTransformer

# Initialize
model = SentenceTransformer('all-MiniLM-L6-v2')
client = chromadb.PersistentClient(path="./odoo_kb_db")
collection = client.create_collection("odoo_docs")

# Index KB files
for chunk in parsed_chunks:
    embedding = model.encode(chunk['text'])
    collection.add(
        ids=[chunk['chunk_id']],
        embeddings=[embedding.tolist()],
        documents=[chunk['text']],
        metadatas=[{
            'version': chunk['version'],
            'topic': chunk['topic'],
            'edition': chunk['edition'],
        }]
    )

Retrieval at Query Time

def retrieve_context(query: str, version: str, top_k: int = 5) -> list:
    """Retrieve relevant Odoo documentation chunks."""
    query_embedding = model.encode(query)

    results = collection.query(
        query_embeddings=[query_embedding.tolist()],
        n_results=top_k,
        where={"version": version},  # Filter by Odoo version
    )

    return results['documents'][0]

The version filter is critical — it ensures the agent only receives documentation for the correct Odoo version, preventing version confusion.

Generation with Retrieved Context

import anthropic

client = anthropic.Anthropic()

def generate_with_rag(query: str, version: str) -> str:
    # Retrieve relevant context
    context_chunks = retrieve_context(query, version)
    context = "\n\n".join(context_chunks)

    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=4096,
        system=f"""You are an Odoo {version} developer.
        Use ONLY the following documentation as reference.
        Do not use patterns from other Odoo versions.

        Documentation:
        {context}""",
        messages=[{"role": "user", "content": query}]
    )
    return response.content[0].text

Real-World Improvement

ScenarioWithout RAGWith RAG
Odoo 19 computed fieldMay use deprecated @api.oneUses correct @api.depends
Odoo 18 list view50% chance of using <tree>Always uses <list>
Odoo 17 form viewOften includes attrs=Uses direct invisible/readonly
Odoo 19 constraintMay use _sql_constraintsUses Constraint() class
Version migrationMisses breaking changesIdentifies all version-specific changes

Advanced: Hybrid RAG

For the best results, combine multiple retrieval strategies:

  • Vector search — Semantic similarity for conceptual queries
  • Keyword search — Exact matching for API names and error messages
  • Metadata filtering — Version + edition + topic filtering
  • Code search — Search Odoo source code for actual implementations

Getting Started

The DeployMonkey AI agent already uses a RAG-like approach — it has access to a 66,000-line knowledge base covering Odoo 14-19 and retrieves relevant context when answering your questions. For custom agents, build your own RAG pipeline using the architecture above. The knowledge base is the most important investment — without it, even the best LLM generates unreliable Odoo code.