Early access · Odoo 19
Trust what AI tells you about your Odoo.
The Context Layer for Odoo: the verified meaning layer that tells any AI which records count, which fields mislead, and whether an action is safe.
AI gives confident, wrong answers about your own business, and you cannot tell which answers are wrong. The reason compounds: a schema says which fields exist, never which records count or what they mean. This is the verified layer that fixes it, before any AI reads or writes anything. Live now, in early access, with a free 7-day trial.
Not a UI: a verified layer any AI reads before it touches Odoo. The open standard is on GitHub today; the verified runtime opens with a free 7-day trial. Format v0, a technical alpha that can change.
account.move -
move_type = out_invoicecustomer invoice -
move_type = in_invoicevendor bill -
move_type = out_refundcredit note -
amount_totalnot revenue -
invoice_user_idthe salesperson
Verified against Odoo 19 · hash-verified
You connected Odoo to your AI
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. The founder’s note on why this is a knowledge gap, not an intelligence one: intelligence isn’t knowledge.
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 against 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 against 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. free_qty is on-hand minus reserved; virtual_available forecasts planned moves. Scope the company, warehouse, and location: the sellable number is much lower.
context supplied by OCL, verified against 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.
A query can be technically perfect and commercially wrong. 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, receipts, 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.
Treat a refund as a normal invoice and let it inflate the total.
A customer credit note is account.move where move_type = 'out_refund'
Vendor credit notes are in_refund. Refunds change the population: decide whether to net them before you count.
Sum amount_total as revenue across every move.
Accounting impact needs posted moves: state = 'posted'
And amount_total is a document total, not a universal revenue metric. Add posted only when the task needs accounting impact.
Group by create_uid, or read the name off partner_id.
The salesperson on an invoice is invoice_user_id
partner_id is the customer; create_uid is who keyed the record. In Odoo 19, user_id is a related alias to invoice_user_id, not a separate owner.
The long version, with Odoo’s own docs and the source: why AI gets Odoo revenue wrong.
The idea
Reaching Odoo isn’t understanding it.
You plug an AI into Odoo through MCP or tools, and it can read and write records. That is access, not understanding. The context layer is the missing middle: the verified meaning between the AI and the data it can already reach.
- Access plugged in
You wire an AI to Odoo through MCP, tools, or a workflow. It can read and write records. That is reach, not meaning.
- 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.
- Answer reasoning
The AI answers or acts correctly, with the meaning it was missing. Any model, any setup.
Meaning is half of trust. The other half is proof: its sibling, the Execution Layer for Odoo, available now on Odoo 19, so every AI action is validated, executed atomically, read back, verified, and receipted. Meaning before the action, proof after it. Re-reading the row after a write is the rarest check in the category, and we counted it in the Odoo AI write-verification census.
Who it’s for
Built for four kinds of people.
The same missing meaning bites everyone who points an AI at Odoo, differently. Here is the real failure each one hits today, and what the layer hands back.
- Business owners
Answers you can act on
You connected Odoo to ChatGPT or Claude and asked a plain question. It answered with confidence, and it was wrong.
- Revenue that counts posted customer invoices and nets refunds, not every row in
account.move - Your salespeople from
invoice_user_id, not the customers onpartner_idor whoever last edited the record - A question back when “revenue” or “available” is ambiguous, instead of a confident guess
- Revenue that counts posted customer invoices and nets refunds, not every row in
- Odoo engineers & implementers
Stop rediscovering the same traps
You already know account.move is four documents in one table. The model does not, and neither does the next session.
- Verified join paths for Odoo 19: purchase line → vendor bill via
purchase_line_id, not the display text ininvoice_origin - The negative knowledge:
invoice_date_dueis the last installment, on-hand is not available-to-sell - Safe write methods (
action_post,button_confirm), never a blind write tostate
- Verified join paths for Odoo 19: purchase line → vendor bill via
- Enterprise
Scope and safety in every answer
Multi-company, multi-currency, record rules, and writes that must not fire blind. Meaning has to carry those boundaries.
- Company-security context travels with the answer, and it warns against
sudoto make results look complete - Document vs company currency kept distinct (
amount_residualvsamount_residual_signed) - Advisory write-risk on critical actions, and provenance on every pack: entry, revision, release, confidence
OCL makes scope, currency, write risk, and provenance visible. Odoo stays the enforcement authority.
- Company-security context travels with the answer, and it warns against
- Product developers & ISVs
Raise your product’s accuracy
You are building your own AI feature or agent on Odoo, and accuracy is capped by missing business meaning.
- Adopt the open standard free, Apache-2.0: schemas, validator, clients, conformance, ten examples
- Evaluate the verified runtime in early access: the same five operations over MCP or REST
- Consume it beside the model and Odoo access your product already ships, no ontology to build
Production embedding is a licensed conversation, not part of alpha access.
For developers and AI teams
Live in early access. Wire it in.
The verified runtime is hosted at api.context.nanti.ai. Try one
decision with no login, get a free 7-day universal key from a single email, then let any AI
ask OCL for meaning before it reads Odoo the way it already does. Works with any model, any
agent, any setup.
- 01
See it refuse to guess
Open the live revenue decision. No login, no key. Watch OCL decline to invent a formula and return the warning against summing amount_total as revenue.
Try the live demo - 02
Get a free universal key
One email, no verification step, no sales call. An active seven-day key appears on the next screen: one universal Bearer token that covers both Odoo 19 editions, all released modules, every operation, and every interface (MCP, REST, Codex, Claude Code, Python). No Odoo credentials, no customer data.
Get your key - 03
Point your AI at it
Add the remote MCP URL, or call REST. Your agent asks OCL for meaning and safety first, then reads Odoo the way it already does, under your real permissions.
Read the setup guide
Add the remote OCL server to Claude Code with your issued token. It then calls OCL before it reads your Odoo data.
Free trial · universal keyexport OCL_TOKEN="<your-issued-token>"
claude mcp add --scope user --transport http ocl \
https://api.context.nanti.ai/mcp \
--header "Authorization: Bearer $OCL_TOKEN" Your token is a secret. Claude Code stores the header in its user config: never commit or share it.
Register OCL as a remote MCP server in the Codex CLI, reading the token from the environment.
Free trial · universal keyexport OCL_TOKEN="<your-issued-token>"
codex mcp add ocl \
--url https://api.context.nanti.ai/mcp \
--bearer-token-env-var OCL_TOKEN Launch Codex from the same environment so it can read OCL_TOKEN.
Call the operations directly over HTTPS with a Bearer token. The response is a context pack: facts, warnings, unknowns, and provenance.
Free trial · universal keyexport OCL_URL="https://api.context.nanti.ai"
export OCL_TOKEN="<your-issued-token>"
curl "$OCL_URL/v1/get-context" \
-H "Authorization: Bearer $OCL_TOKEN" \
-H "Content-Type: application/json" \
--data '{
"question": "Which invoices are unpaid?",
"odoo_version": "19.0",
"edition": "community",
"modules": ["account"]
}'
Five routes under /v1/: get-context · resolve-noun ·
explain-field · get-join-path · validate-write-intent.
Write validation is advisory and always returns authorized: false.
The reference Python client wraps the same operations. Point it at the hosted runtime with your token.
Free trial · universal keyimport os
from ocl_spec import OCLClient
ocl = OCLClient(os.environ["OCL_URL"], os.environ["OCL_TOKEN"])
pack = ocl.get_context(
"Which invoices are unpaid?",
odoo_version="19.0",
edition="community",
modules=["account"],
) Public source client, not a published package: install it editable from the clone (pip install -e sdk/python).
Any MCP host can reach the runtime over Streamable HTTP. All five operations are discovered as tools.
Free trial · universal key{
"mcpServers": {
"ocl": {
"url": "https://api.context.nanti.ai/mcp",
"headers": { "Authorization": "Bearer ${OCL_TOKEN}" }
}
}
} Use the host’s secret-environment method for the token rather than committing it. No OCL package is required for remote MCP.
No key needed. Clone the Apache-2.0 standard and run the example server over ten public candidate entries.
Available now · no keygit clone https://github.com/Nantiai/ocl-standard.git
cd ocl-standard
python reference/python/ocl_examples.py get-context "What is revenue?"
The public example server exposes get_context · resolve_noun ·
explain_field over ten candidate examples. It is the format, not the verified 171.
- Clone the standard, run the CLI, wire the example MCP, validate your own entries
- Ten candidate example entries across every knowledge kind
- The format spec, JSON Schemas, validator, conformance suite, and reference clients
- One email issues a universal 7-day key: both editions, every module, every interface
- The 171-entry verified registry over REST or remote MCP, all five operations, returning warnings, required clarification, and provenance
- Request-scoped meaning: no bulk export, no registry download, no production SLA
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 type from the format.
-
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 action_post, require approval.
See the difference
Same question. One reads meaning.
Same model, same setup, 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 against 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
Released entries are immutable and hash-verified against release locks before serving: pin a release and the meaning you read today is the meaning you read last week. And when a question is ambiguous, the runtime does not guess. It tells the AI what must be decided first.
{
"request": { "question": "What was our revenue this month?" },
"facts": [{
"entry_id": "…account.disambiguation.revenue",
"status": "verified", "confidence": 0.99,
"rendered": "“Revenue” is ambiguous: ledger accrual,
invoiced sales, or cash received."
}],
"warnings": [{
"entry_id": "…account.negative.amount_total_as_revenue",
"severity": "high", "status": "verified",
"rendered": "Do not sum account.move.amount_total
across records as revenue."
}],
"unknowns": [{
"code": "revenue_basis",
"message": "GL accrual, invoiced sales, or cash?",
"required_action": "clarify_before_execution"
}],
"provenance": { "release": "verified",
"runtime_index_sha256": "…",
"truncation": { "truncated": false } }
} Representative shape. Selected entries, ids, and limits are dynamic. The service returns provenance, never the private evidence or harness.
Early access, today
What it actually ships.
Substantial and honest. A released kernel on real machinery, verified against Odoo 19, with the edges named plainly.
- 171 verified entries
Focused coverage across Accounting, Sales and Inventory, Purchase, Sales-to-Fulfillment, CRM, Manufacturing, and Project and Helpdesk. Verified against Odoo 19, with edition and module applicability enforced. Not complete coverage.
- 4 verification anchors
Every release is re-proven against release-day and current Odoo 19, Community and Enterprise, so meaning is not pinned to one moving target.
- 5 live operations
get_context, resolve_noun, explain_field, get_join_path, and validate_write_intent, all live over authenticated REST and remote MCP.
Underneath: executable verification, immutable hash-verified release locks, provenance, deterministic retrieval over released content, and risk-preserving 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 set of Odoo tools, one set of permissions. Only the context changes, so any difference is the context layer and nothing else.
- A
Tools only. Tool descriptions and returned records. No schema dump, no OCL.
- B
Tools plus raw schema. The strongest realistic schema and generic Odoo guidance. The primary baseline.
- C
Exactly B, plus OCL. The same 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, and the two stay clearly separate: the ten public examples are the format, not the verified 171.
- The format specification and JSON Schemas
- The validator and conformance suite
- Reference Python and TypeScript source clients
- Ten candidate example entries and an example MCP server
- The curated, verified 171-entry registry
- The verification harness and release matrices
- The private retrieval index and assembly
- The tenant overlay and memory foundation
The open kit is live at github.com/Nantiai/ocl-standard, Apache-2.0. Adopt the format today; the verified registry comes with a free universal runtime key. See the open format.
Straight about status
Where this stands.
A self-serve early access with a free trial, and we want the edges unmistakable. Here is what is real, and what is not, with no counts we would have to walk back.
- The verified runtime is live at api.context.nanti.ai: start a free 7-day trial, then call all five operations on Odoo 19 meaning over REST or remote MCP
- Try one verified decision with no login, no key, at api.context.nanti.ai/demo/revenue
- The open standard is on GitHub, Apache-2.0: clone it, run the CLI, wire the example MCP over ten candidate entries, and validate your own
- A verified library of 171 entries across eight coverage packs, hash-verified against immutable release locks before serving
- The 171-entry registry is not public, downloadable, or enumerable: you reach it only through the request-scoped runtime. The trial runs without a request-count meter, but burst, context-size, and anti-extraction limits keep it from becoming a bulk export
- No accuracy figure: live model runs exist, but independent blind scoring is still pending, so we publish no benchmark number
- Odoo 19 only, stock, Community and Enterprise, with per-entry applicability enforced. Custom modules, localizations, company, and currency can change the answer, and it is not verified against your specific instance
- No production SLA, no PyPI or npm packages yet, and no hosted tenant overlay or memory. The v0 format is a technical alpha and can change
- No screenshots: this is not a UI product. And no final name: “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. An AI plugged into Odoo can read 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.
My AI is already connected to Odoo. Why isn’t that enough?
Because reaching your records is not the same as understanding them. However you plugged the AI in, through MCP or tools, it can read and write Odoo data but cannot see which records count, which fields mislead, or whether an action is safe. It follows a technically valid field or join and answers the wrong business question. The context layer supplies exactly that missing meaning, so access becomes understanding.
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?
Early access targets Odoo 19, Community and Enterprise. It releases 171 verified entries across focused coverage: Accounting, Sales and Inventory, Purchase and Purchase-to-Accounting, Sales-to-Fulfillment, CRM, Manufacturing, and Project, Timesheets and Helpdesk. Every entry is qualified through release-day and current Odoo 19 anchors, with edition and module applicability enforced, so some entries apply only to one edition (Helpdesk is Enterprise-only, for example). That is focused coverage verified against Odoo 19, 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. Released entries are immutable and hash-verified against release locks before serving, so pinning a release means the meaning does not shift under you.
Will it only work with nanti.ai products?
No. Our own products consume it first, and it is model-independent by design and works however your AI reaches Odoo, so external AI stacks, agents, and Odoo-native tools 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: strong raw Odoo tools with 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 source clients, ten candidate example entries, and an example MCP server. You can read, validate, and produce entries without our registry. The clients are source, not published PyPI or npm packages yet, and the verified registry itself is the commercial product.
Is there a hosted API, and how do I get access?
Yes. The verified runtime is live at api.context.nanti.ai. Try one verified decision with no login at api.context.nanti.ai/demo/revenue, then start a free 7-day trial at api.context.nanti.ai/request-access. It takes one email, with no verification step and no sales call, and an active seven-day key appears on the next screen. The key is universal: one Bearer token that covers both Odoo 19 editions, all released modules, every operation, and every interface (MCP, REST, Codex, Claude Code, Python). It never asks for Odoo credentials or customer data. The trial runs without a request-count meter, though burst, context-size, and anti-extraction limits still apply, the 171-entry registry is not downloadable or enumerable, and there is no production SLA during early access.
Does it connect to my Odoo database?
The hosted runtime does not. It asks for no Odoo credentials and never reads your database. It returns verified meaning about Odoo 19: which records count, which fields mislead, how they join, and whether an action is safe. Your own AI then reads the real records the way it already does, through MCP or tools, under your real permissions. There is an optional local metadata collector, opt-in and separate, that can read allowlisted Odoo metadata to tune context for your instance; if you use it, its Odoo credential stays on your side. Meaning is verified against Odoo 19, not against your specific instance, so custom modules, localizations, company, and currency can still change the answer.
When can I use it?
Now. The open standard is public today: 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 171-entry runtime is live too, in early access: try the no-login demo at api.context.nanti.ai/demo/revenue, then start a free 7-day trial with one email for a universal key, and call all five operations over REST or remote MCP beside however your AI already reaches Odoo.
Some questions deserve a whole page. These have one:
Get in early
See it decide.
Try the live decision in a browser, clone the open standard, then start a free 7-day trial when you want the verified runtime on real Odoo 19 meaning. Building an AI product on Odoo? Come in early.
One email when the verified runtime opens wider. No newsletters, no spam.
