Technical alpha · Odoo 19
The context layer for Odoo.
AI gets Odoo wrong for one reason that compounds: technical schema does not explain business meaning. This is the verified meaning layer that fixes it. A connector moves records; the context layer tells any AI what they mean, which ones count, and whether an action is safe, before it reads or writes anything.
Not a UI. A verified layer any AI reads before it touches Odoo. No screenshots, deliberately.
For developers
Slot it in. Keep your stack.
OCL is not a connector and not a model. Your AI agent asks it for meaning and safety, and keeps using the Odoo connector it already has. Works with any model, any agent, any connector.
Apache-2.0 Odoo 19 MCP · REST · Python · TS public on GitHub
$ git clone https://github.com/Nantiai/ocl-standard.git $ python reference/python/ocl_examples.py get-context "What is revenue?" $ python -m pip install -e sdk/python Runs against ten public candidate examples. No key, no account.
Give any MCP agent the OCL operations. The public example server answers over the ten candidate entries.
Available now{
"mcpServers": {
"ocl-public-examples": {
"command": "python",
"args": [
"/absolute/path/to/ocl-standard/reference/python/ocl_examples.py",
"serve-mcp"
]
}
}
}
Public operations: get_context · resolve_noun ·
explain_field. The full contract adds get_join_path and
validate_write_intent, served by the verified runtime.
Clone the standard and inspect context packs and entries from the terminal.
Available nowgit clone https://github.com/Nantiai/ocl-standard.git
cd ocl-standard
python reference/python/ocl_examples.py get-context "What is revenue?"
python reference/python/ocl_examples.py resolve-noun "vendor bill"
python reference/python/ocl_examples.py explain-field account.move invoice_user_id Every command runs against the ten public candidate examples. No key, no account.
Validate your own entries against the format with the reference validator.
Available nowfrom ocl_spec import validate_entry, ValidationError
# document = your entry; schema = the loaded entry JSON Schema
errors = validate_entry(document, schema) The typed integration contract for a running OCL service. The same five operations, ready for the verified runtime.
Contract now · runtime with accessconst client = new OCLClient(baseUrl);
await client.getContext(question, scope);
await client.resolveNoun(noun, scope);
await client.explainField(model, field, scope);
await client.getJoinPath(fromModel, toModel, scope);
await client.validateWriteIntent(model, operation, scope); The client ships in the repo as the contract. It is not on npm yet: a stable endpoint comes with verified runtime access.
Keep the connector you already have. OCL supplies meaning; your connector still moves the data.
Works with any connector# 1. ask OCL for the smallest verified context
context = ocl.get_context(question, scope)
# 2. let your model reason, using your existing Odoo connector as its tools
answer = model.run(question, context, tools=your_odoo_connector) Any provider, any connector, any MCP server for transport. OCL adds the layer they never carried.
- Clone the standard, run the CLI, wire the example MCP
- Ten candidate example entries across every knowledge kind
- The format spec, JSON Schemas, validator, and conformance suite
- The 44-entry verified registry, on your real Odoo 19 data
- A running service for all five operations, and a hosted endpoint
- Tenant overlay and memory for your customizations
Any model, any setup
An Odoo connection is not Odoo understanding.
Point ChatGPT, Claude, or Codex at Odoo through an MCP server, official or third-party, or wire your own workflow. Whichever you use, a capable model can follow a technically valid field or join and still answer the wrong business question. The gap is missing business context, not model size. The context layer supplies the verified meaning the model was never given.
ChatGPT Claude Codex your own agent any Odoo MCP a custom workflow
-
Who are my top salespeople this quarter?
Without the context layerSure. Your top people are Cafe Mujica, Panaderia Los Andes, and Verduleria del Sur.
With the context layerwrong nounThose are customers, read off partner_id. Your salespeople are the users in invoice_user_id, a different business noun. Here are the actual reps.
context supplied by OCL, verified on Odoo 19 -
Which customers bought this product?
Without the context layerHere they are. I counted every sale.order.line for the product across your customers.
With the context layerwrong populationMany of those lines are draft quotes and cancellations, not purchases. Count confirmed orders, and I should ask whether “bought” means ordered, delivered, or invoiced.
context supplied by OCL, verified on Odoo 19 -
How much of this can we sell right now?
Without the context layerPlenty. I summed stock.quant.quantity for the product across the database.
With the context layerwrong scopeOn-hand is not available-to-sell. Scope this company, warehouse, and location, and net out what is already reserved: the sellable number is much lower.
context supplied by OCL, verified on Odoo 19
The context layer helps stop answers that are technically valid and business wrong. It advises on company scope and write risk. Odoo still decides which records a user may see.
The gap
Schema tells AI what fields exist. Not what they mean.
Odoo exposes technical structure, and technical structure does not encode business meaning. Hand an AI raw schema and records and you buy three costs, every day.
-
Wrong interpretation
A plausible-looking field can be the wrong business field, and a valid relational path can still produce the wrong metric. The answer looks right and is wrong.
-
Rediscovery, every time
Raw schema means large prompts and the same discovery work repeated on every question, in every tool, in every session. Nothing learned is kept.
-
Unsafe actions that validate
A write can be semantically wrong and still technically valid. State, company, currency, and record rules change what an action means.
The state of a record, the company, the currency, and the record rules all change what the answer should be. None of that lives in the schema.
Made concrete
One table. Several business documents.
Take one Odoo model, account.move. Its schema lists the fields. It
never says that the same table is customer invoices, vendor bills, refunds, and journal
entries at once. Pick a reading and see the trap, then the verified rule.
Read account.move as “the invoices” and sum them.
A customer invoice is an account.move where move_type = 'out_invoice'
Vendor bills, refunds, and journal entries all live in the same table.
Assume a supplier invoice is a different model.
A vendor bill is the same account.move where move_type = 'in_invoice'
One table, discriminated by move_type. The noun decides the filter.
Sum amount_total as revenue across every move.
Accounting impact needs posted moves: state = 'posted'
And amount_total is not a universal revenue metric. Different document types and definitions make one total field the wrong number. Add posted only when the task needs accounting impact.
Read partner_id and return the name on the invoice.
The salesperson on an invoice is invoice_user_id
partner_id is the customer, a different business noun. The salesperson is a user, not the party being billed.
The idea
Transport, meaning, reasoning.
The context layer does not move data and does not reason. It is the missing middle: the verified meaning between a connector and a model.
- Connector transport
Moves records in and out of Odoo. It answers how an AI can read or write. It does not say what the records mean.
- Context layer meaning
Supplies the smallest verified context for the question: which records count, which fields mislead, how they join, whether an action is safe.
- AI reasoning
Answers or acts, with fewer unsupported assumptions, on whatever model you choose. Any provider, any connector.
question the connector exposes Odoo OCL supplies the smallest verified context the AI answers or acts
Seven shapes of meaning
What the layer adds.
Not one kind of fact. Each is a different shape of meaning an AI needs and raw schema does not carry. Every example below is a real entry from the public format examples.
-
Noun mapping
“Customer invoice” maps to account.move where move_type = out_invoice.
-
Negative knowledge
amount_total is not a universal revenue metric. The trap, written down.
-
Field semantics
The salesperson is invoice_user_id, a user, not the customer on partner_id.
-
Join paths
sale.order.line → order_id → sale.order → partner_id → res.partner.
-
Security and company
Records visible under allowed_company_ids are not proof of complete records.
-
Disambiguation
“Revenue” can mean ledger revenue or invoiced sales. Ask which.
-
Write risk
Posting a move is critical: prefer the business method, require approval.
See the difference
Same question. One reads meaning.
Same model, same connector, same data. Ask both for revenue this month. Watch which rows of
account.move each one counts.
What is revenue this month?
And it does things a raw-schema AI cannot do at all.
- ambiguity
Asks, not guesses
“Revenue: ledger or invoiced?”
- write risk
Blocks unsafe writes
Posting is critical. Approve first.
- security
Carries boundaries
Company and currency, every time.
- memory
Keeps what it learns
Confirmed once, never re-derived.
The bar
What “verified” actually means.
“Verified” must never mean “an LLM wrote plausible YAML.”
Every fact carries evidence and executable checks: code that proves the claim on real Odoo 19. A claim that code cannot fully prove needs source evidence or explicit human review. No entry reaches verified because a model judged its own output, and confidence is tracked separately from verification.
An entry moves through explicit states. It never skips to the end.
-
draft -
evidence_attached -
asserted -
verified
Releases are immutable and content-hashed: pin a release and the meaning you read today is byte-for-byte the meaning you read last week.
{
"type": "noun_mapping",
"claim": {
"business_noun": "customer invoice",
"model": "account.move",
"domain": [["move_type", "=", "out_invoice"]]
},
"evidence": [{
"kind": "source_code",
"locator": "odoo/account_move.py#L142-L159"
}],
"assertions": [
{ "kind": "selection_contains", "mode": "snapshot" },
{ "kind": "domain_executes", "mode": "live_read" }
],
"confidence": { "score": 0.99, "basis": "pinned_official_source" },
"provenance": { "created_by": "source-normalizer" }
} Public format example, trimmed for reading. Not one of the released 44.
The alpha, today
What it actually ships.
Substantial and honest. A released kernel on real machinery, with edges we name plainly.
- 44 verified entries
A use-case-focused semantic kernel: an accounting truth kernel, focused sales and inventory bridges, and a deep purchase kernel. Not complete coverage.
- 4 verification anchors
Every release is re-proven against release-day and current Odoo 19, Community and Enterprise, so it is not verified against one moving target.
- 6 consumption surfaces
MCP, REST, Python, TypeScript, static context packs, and signed offline caches. Connector-independent, model-independent.
Underneath: executable verification, immutable content-hashed release locks, provenance, deterministic retrieval over released content, and risk-preserving context assembly, where a critical warning is never dropped to fit a token budget. The full inventory is in the coverage and release status docs.
How it is measured
A fair test, honestly reported.
Three arms, one model, one connector, one set of permissions. Only the context changes, so any difference is the context layer and nothing else.
- A
Connector only. Tool descriptions and returned records. No schema dump, no OCL.
- B
Connector plus raw schema. The strongest realistic schema and generic Odoo guidance. The primary baseline.
- C
Exactly B, plus OCL. The same connector, tools, and permissions, with an assembled context pack.
B versus C is the comparison that matters. Live model runs exist, and independent blind human scoring is the final gate. It is pending, so we publish no accuracy figure, no chart, and no “gate passed” claim. The methodology is public; results are forthcoming.
The moat, in the open
Open standard, verified registry.
The format is open so anyone can build on it. The verified registry that proves the meaning is the commercial product. Adopting the standard never requires our registry.
- The format specification and JSON Schemas
- The validator and conformance suite
- Reference Python and TypeScript SDKs
- Ten candidate example entries and an example MCP server
- The complete curated, verified registry
- The verification harness and release matrices
- The private retrieval index and ranking
- The tenant overlay and memory system
The open kit is live at github.com/Nantiai/ocl-standard, Apache-2.0. Adopt the format today; the verified registry comes with runtime access. See the open format.
Straight about status
Where this stands.
An early technical alpha, and we want that unmistakable. Here is what is real, and what is not, with no counts we would have to walk back.
- The open standard is on GitHub, Apache-2.0: clone it, run the CLI, wire the example MCP with ten candidate entries, and validate your own entries today
- A verified semantic kernel of 44 entries is released on Odoo 19, loaded through immutable, content-hashed release locks
- Verification is executable: entries carry evidence and checks that run against real Odoo 19, plus provenance
- The format is an open specification (v0) with JSON Schemas, a validator, conformance tests, reference SDKs, and exemplar entries
- The verified 44-entry runtime and a hosted endpoint are not public yet: they come with verified runtime access, granted directly
- No benchmark result: live model runs exist, but independent blind scoring is pending, so no accuracy figure is published
- The tenant system (overlay, memory) is an implemented foundation, not a finished hosted product
- Odoo 19 only, stock. Custom modules, localizations, company, and currency can change the answer
- No screenshots: this is not a UI product. And no final name yet: “context layer” is the working label
Plain answers
Asked, answered.
What is a context layer for Odoo?
It is the meaning system between an AI and Odoo. A connector moves records; the context layer explains what they mean and how to use them: which records count, which fields are misleading, how tables join, and whether an intended action is safe. The AI loads that context before it reads or writes anything.
How is it different from a connector?
A connector answers how an AI can read or write Odoo records. The context layer answers what those records mean, which of them count, and how they combine into a correct answer. The two work together: the connector is transport, the context layer is interpretation.
Is this RAG over Odoo documentation?
No. Documentation describes what Odoo generally does; it does not know your version, your modules, or your customizations. Every entry in the context layer carries evidence, executable applicability checks, and a confidence level, so meaning is proven for your setup, never pasted from a manual.
Does it replace Odoo permissions or business rules?
No. Odoo remains the authority for permissions and execution. The context layer supplies interpretation and safety context on top: it can warn that an intended action looks risky, but it never bypasses or replaces access rights, record rules, or business methods.
Which Odoo versions does it cover?
The technical alpha targets Odoo 19, Community and Enterprise. It releases a use-case-focused semantic kernel: an accounting truth kernel, focused sales and inventory bridges, and a deep purchase kernel. That is a focused kernel, not complete coverage of any module, and Odoo 19 is the only current version target. We state exactly what is proven, never "all modules supported".
What does "verified" mean here?
Every entry carries evidence and executable checks that run against real Odoo 19. An entry is only called verified after it passes its full release policy, including live checks and human review where needed, never because a language model judged its own output. Confidence is tracked separately from verification: sounding sure is not the same as being right.
Will it only work with nanti.ai products?
No. Our own products consume it first, and it is connector-independent and model-independent by design, so external AI stacks, connectors, and Odoo-native agents can consume the same contracts. One verified layer of meaning, whatever is asking.
I use ChatGPT, Claude, or Codex with an Odoo MCP server. Does this help?
Yes, that is exactly the case it is built for. An Odoo connection is not Odoo understanding. Whatever the model, and whether it reaches Odoo through the official MCP server, a third-party one, or your own custom workflow, it can follow a technically valid field or join and still answer the wrong business question: returning the customer on partner_id when you asked for the salesperson, counting draft quotes as purchases, or reading on-hand stock as available to sell. The context layer supplies the verified business meaning the model was never given, alongside the setup you already have. It advises on company scope and write risk; Odoo still decides which records a user may see.
Is there a benchmark?
Yes, a fair three-arm design: a strong connector with raw schema, then the same setup plus the context layer, holding the model, permissions, and tasks constant so only the context differs. Live model runs exist, but independent blind human scoring is still pending, so we publish no accuracy figure, chart, or "gate passed" claim yet.
Is the format open?
Yes, and it is public today. The open standard lives at github.com/Nantiai/ocl-standard under Apache-2.0: the experimental specification (v0), JSON Schemas, a validator, conformance tests, reference Python and TypeScript SDKs, ten candidate example entries, and an example MCP server. You can read, validate, and produce entries without our registry. The verified registry itself is the commercial product.
When can I use it?
Right now, for the open standard. Clone github.com/Nantiai/ocl-standard, run the CLI, and wire the example MCP server (get_context, resolve_noun, explain_field) over ten candidate example entries in minutes, with no key and no account. The verified 44-entry runtime over your real Odoo 19 data, and a hosted endpoint, come with verified runtime access, which we grant directly.
Build on it
Get in on the alpha.
Building AI on Odoo, or shipping a connector or ISV product? Start with the open standard today, then ask us for the verified runtime when you need real Odoo 19 data.
One email when the verified runtime opens. No newsletters, no spam.