Ask in plain language. Approve before it posts.
ODXPilot is an AI assistant for day-to-day Odoo administration. Your team asks for the work; ODXPilot prepares it in Odoo as a plan of drafts, checks it against your roles and procedures, and waits for a person to approve.
request
“bill the PO we received from PT Contoh Logistik”
SOP · vendor-bill-from-po · a41c07e2…
- 1readpurchase.order — received vs. invoiced
- 2checkvendor NPWP on file, period open
- 3createaccount.move — vendor bill, draft
- 4postaction_post — needs finance_manager
Requested by Rina (accountant)
Send for approvalIllustration of the planned interface.
The problem
AI can do the back-office work. Plugging it straight into Odoo isn’t safe.
Recording vendor bills, drafting invoices, matching payments, reconciling bank lines: routine work that still needs someone who knows Odoo, where a mistake is expensive. A general-purpose agent with an Odoo key can do it quickly — and gets it wrong in ways accounting can’t accept.
It guesses the schema
Model and field names differ per Odoo version, per installed app and per Studio customisation. A guessed field name is a failed write — or a wrong one.
The prompt is the only guard
“Don't post payments” in a system prompt is a suggestion, not a control. Text inside a PDF or an email can talk the model out of it.
It runs with a big key
Agents are usually wired up with an Odoo admin key, so one bad plan can touch anything in the database.
Odoo can't tell people apart
Teams share Odoo users, so Odoo's groups and history describe the shared user — not the person who asked the agent to act.
No segregation of duties
Nothing stops the same person, or the agent, from adding a vendor's bank account and then paying it.
Your way of working isn't in the model
Every company has its own procedures, localisation and chart of accounts. Best practice for VAT in one country isn't in the next.
How it works
The model plans. Deterministic code decides.
ODXPilot keeps the model’s job small — understand the request, propose a plan — and puts every decision that matters in code it can’t talk its way around.
1
Ask
In plain language, in a chat pinned to one company.
2
Map to an SOP
One of your own procedures from ODXDocs, filtered to this Odoo instance and company. No confident match: ODXPilot stops and asks.
3
Plan
Each step validated against the live fields of your instance, and dry-run through your role policy.
4
Approve
The right person, in the right company, re-authenticates and reviews the diff.
5
Execute
Through ODXProxy, as drafts by default, with the company context set by ODXPilot — not by the model.
6
Record
Audit log plus a chatter note on the Odoo record: who asked, who approved, which SOP.
| The model | ODXPilot — deterministic | |
|---|---|---|
| Understands the request | Yes | — |
| Picks the procedure (SOP) | Describes the task | Maps it to one published SOP version — or stops |
| Writes the plan | Yes | Validates every model and field against live fields_get |
| Decides permissions | Never | Role policy, default deny |
| Sees bank numbers, salaries, keys | Never | Masked before the data reaches the model |
| Posts, pays, reconciles | Never on its own | Only after a person with the right role approves |
Where it fits
Built on ODXProxy, ODXBrain and ODXDocs. One stack per Odoo instance.
ODXPilot asks ODXBrain which Odoo model holds the data and which of your SOPs applies, fetches that SOP from ODXDocs, then reads live fields and records through ODXProxy — the only component that talks to Odoo. Odoo stays the engine and the gatekeeper.
Each Odoo instance gets its own ODXPilot, ODXProxy and ODXBrain, serving every company in that database. Nothing is shared between customers, so one company’s procedures never leak into another’s.
Your people
sign in with your identity provider
ODXPilot
plans · policy · approvals · audit
which model? which SOP?
ODXBrain
model names · SOP ids
ODXDocs
your SOPs, exact versions
fields_get · read · drafts
ODXProxy
one safe JSON-RPC seam
Odoo
the engine & gatekeeper
SOP mapping · with ODXDocs
Every request mapped to a procedure your people wrote.
ODXPilot doesn’t improvise accounting. Your accountants and developers write each procedure once in ODXDocs, the SOP manager that comes with ODXBrain: the business rules, the technical steps, and the phrases people use to ask for it. ODXPilot maps every request to exactly one published version of one SOP — or stops and asks.
+++ id = "vendor-bill-from-po" title = "Record a vendor bill from a received purchase order" intents = [ "create a bill from a purchase order", "record a supplier invoice against a PO", "enter a vendor bill after goods are received", ] [applies_to] odoo_min = "17.0" edition = "enterprise" modules = ["account", "purchase"] +++ ## Business rules (Accountant) - Only bill what was received. - Bills above IDR 50,000,000 need CFO approval before they are posted. - The vendor's NPWP must be on the partner record. If it is missing, stop and ask Finance. - Never post a bill dated in a closed period. ## Technical notes (Developer) - Create it with purchase.order.action_create_invoice. - Compare qty_received with qty_invoiced first. - Post with account.move.action_post. Ask the user to confirm before posting.
How a request finds its SOP
- 1
Describe
ODXPilot turns the request into a short task description: “record a vendor bill for a received purchase order”.
- 2
Rank
ODXBrain ranks your published SOPs by their titles and intents, filtered to this instance: Odoo version, edition, installed modules — localisation included — and company.
- 3
Stop if unsure
No confident match means ODXPilot stops and asks you. It never runs the nearest procedure instead.
- 4
Check the operation
The chosen SOP's title is checked against the task, because “cancel a bill” and “record a bill” look alike to a search.
- 5
Fetch that exact version
The procedure comes from ODXDocs by id and version. There is no “latest”, so a publish mid-task can't swap it.
- 6
Plan and log
The plan follows the SOP's rules, and the run records the SOP id, its version and the hash of the published set.
Written by accountants and developers
Each SOP has two parts: the business rules, owned by an accountant, and the technical notes, owned by a developer. Both kinds of expertise, in one file.
Plain Markdown in git
One file per procedure. Review changes in a pull request, see every edit in a diff, and undo by publishing an earlier commit.
Self-tested before it goes live
Every phrase people use to ask for an SOP is held out in turn and must still find that SOP. A failing set can't be published — there is no override.
Every version kept
An SOP's version is the hash of its content, and every version ever published stays available. Any run can be replayed against exactly what the agent followed.
Scoped to your instance
An SOP declares the Odoo versions, edition, modules and companies it applies to. A procedure that doesn't fit this instance is never offered.
Yours alone
We ship no SOP library. Your procedures are your company's, live in your own stack and never mix with another customer's.
Bodies stay with ODXDocs
ODXBrain only ever sees an SOP's title and intents, to find it. The procedure itself is stored on your premises and handed out by ODXDocs.
A browser editor
See which SOPs are live, changed or new, try how a draft ranks before you save it, and publish through the same self-test.
ODXDocs exists today: SOPs are written, self-tested, published and served from the command line or its browser editor. Connecting it to ODXPilot is on the roadmap. How SOPs work →
Designed for accounting
The AI does the prep work. Your people keep the signature.
Draft by default
Accounting records are created as drafts. The agent prepares the work; a person posts it. Posting, payments and reconciliation each need an explicit approval.
Segregation of duties, on the person
Whoever asked for a change can't approve it — checked on the real person, not the shared Odoo user. The approver must hold the approver role in that company.
Permissions in code, not in the prompt
A policy engine checks every tool call against the person's role before anything leaves ODXPilot. Default deny. A denied call never reaches ODXProxy.
People, not Odoo users
Roles live in ODXPilot per person and per company, optionally synced from your identity provider. A few least-privilege Odoo users can serve the whole team, and every action is still attributed to a person.
Live schema, every time
Fields come from fields_get on your instance and are re-checked right before every write, so a Studio field added since the plan is seen, not guessed.
Your SOPs, not its imagination
Every request is mapped to a procedure your accountants and developers published in ODXDocs. With no confident match, ODXPilot stops and asks instead of improvising.
Masked before the model sees it
Bank account numbers, salaries and keys are masked inside ODXPilot, so the AI provider never receives them — even when the Odoo user could read them.
Multi-company aware
A chat is pinned to one company. ODXPilot sets the company context itself, and every plan step and approval carries a company badge.
Your Odoo keys stay server-side
Write-only once entered: never in a token, the browser, a log, a URL or a prompt — not even visible to your own admins.
Roles
Roles per person, per company.
The same person can be finance manager for one subsidiary and accountant for another in the same Odoo database. Roles are defined in ODXPilot — assigned there or mapped from your identity provider’s groups — and they can only narrow what the agent may do, never widen it.
Never through the agent, for any role: managing Odoo users and groups, or deleting accounting records.
- auditor
- Reads accounting data, bank numbers masked. No writes.
- billing_clerk
- Drafts customer invoices and vendor bills, edits partners (not bank fields).
- accountant
- Adds draft journal entries and reconciliation. No bank changes, no posting payments, no taxes or lock dates.
- finance_manager
- Posts, registers payments, approves bank account changes, sets lock dates. Still bound by segregation of duties.
- tenant_admin
- Manages users, roles, connections, policies and SOPs. No accounting rights unless also given a finance role.
Best practices
Putting AI on Odoo? Twelve rules we build ODXPilot by.
They hold whether you use ODXPilot or build your own agent on ODXProxy.
01
Never give an agent an admin key
Create one Odoo user per role tier — read-only, bookkeeper, manager — with the narrowest groups that work, and let the agent act through the tier that matches the person. Odoo's own access rules then stay a real backstop.
02
Draft first, post by hand
Let the agent create drafts and prepare reconciliations. Posting, paying, reconciling and resetting to draft are separate, explicitly approved steps.
03
Enforce permissions in code
A rule in the prompt can be argued away — by a user, or by text hidden in an invoice PDF or an email. A check in front of the API can't. Allow-list models and methods per role, default deny, fail closed.
04
Read the schema live — and again before writing
Call fields_get on the instance instead of trusting a field list. Re-fetch it right before a write that was approved hours later. On an unknown-field error, re-plan; never retry blindly.
05
Maker ≠ checker, per company
The person who asked can't approve. The approver needs the approver role in the company the change belongs to, and must have signed in again recently.
06
Treat vendor bank changes as a fraud signal
Changing a partner's bank account always needs a second person, and payments to that vendor are flagged for a while afterwards. It's the classic payment-fraud path.
07
Set the company context yourself
Send allowed_company_ids from the person's access, not from what the model suggests, and check company_id on every write. Pin each conversation to one company.
08
Mask before inference
Strip bank numbers, IBANs, salaries and tokens from tool results before they enter the model's context. What the provider never receives, it can't leak.
09
Follow a written procedure, or stop
Map each request to one approved, versioned procedure and log which one ran. When nothing matches confidently, ask a person — never run the nearest procedure.
10
Cancel or reverse, never delete
Keep unlink on accounting records out of the agent's reach entirely. Corrections go through cancellation, credit notes and reversals, like an accountant would do them.
11
Attribute every write to a person
Log who asked, under which role and connection, in which company, with which SOP and approver — and leave a chatter note on the Odoo record so the trail lives in Odoo too.
12
Keep Odoo keys server-side
Odoo API keys belong in a vault on the server: never in a browser, a token, a log line or a prompt. Short-lived tokens for people, and keys rotated before they expire.
Status
Early. Here’s exactly what exists.
Everything above is how ODXPilot is designed to work. Today it’s a model you can talk to, running on the architecture the rest will be built on. It doesn’t do Odoo work yet.
Built today
- ODXDocs: write, self-test, publish and serve SOPs, from the command line or a browser editor
- Chat pipeline end to end: an orchestrator that streams replies, an MCP server, a terminal client
- Claude (Anthropic) and Gemini on Google Vertex AI behind one router, chosen per chat
Roadmap
Odoo tools through ODXProxy
Reading and drafting in Odoo through the same JSON-RPC seam every ODXProxy client uses.
Roadmap
ODXBrain integration
Finding the right Odoo model for a request before reading its live fields.
Roadmap
Policy engine & approvals
Roles per person and company, segregation of duties, masking, the approval queue.
Roadmap
Sign-in with your identity provider
OIDC and SAML, AD / LDAP through a broker, MFA for anyone who writes or approves.
Roadmap
Web app
One question box; answers come back as plan cards with an approve step.
Roadmap
SOP mapping in every request
ODXPilot resolving each request through ODXBrain and following the exact SOP version from ODXDocs.
Roadmap
Local inference
Run the AI model on your own hardware, so your Odoo data doesn't go to a hosted AI provider.
FAQ
- Will ODXPilot post or pay anything on its own?
- No. It is designed to create drafts and prepare work; posting, payments and reconciliation each need approval from a person with the right role in that company.
- Does the AI decide what I'm allowed to do?
- No. Permissions are checked by a policy engine in code, against roles you define, before any call is sent to Odoo. The model only proposes a plan.
- Which AI models does it use, and what do they see?
- Claude (Anthropic) or Gemini on Google Vertex AI, chosen per chat. Your request and the Odoo data the task needs are sent to that provider; fields your policy masks — bank numbers, salaries, keys — are not.
- Can it run fully on-premises or air-gapped?
- Not yet. Today ODXPilot uses hosted AI models. Support for local inference — running the model on your own hardware — is next on the roadmap. ODXBrain, which ODXPilot uses to find Odoo models, already runs fully offline.
- Where do the SOPs come from?
- From your own team. Accountants and developers write them in ODXDocs, test them and publish them. We don't ship an SOP library: every company's way of working is its own.
- What happens when no SOP matches a request?
- ODXPilot stops and asks. It shows the closest procedures for a person to look at, but never runs one that isn't a confident match.
- Does every person need their own Odoo user?
- No. People sign in to ODXPilot with your identity provider and get roles there. ODXPilot acts through a small set of least-privilege Odoo users you register, and still records the real person on every action. Per-person Odoo users work too.
- Does it know our custom fields and Studio changes?
- Yes — it reads them live with ODXProxy's fields_get on your instance, and re-checks right before every write.
- Is it shared between customers?
- No. Each Odoo instance gets its own ODXPilot, ODXProxy and ODXBrain. Your SOPs, policies and history never mix with anyone else's.
- Does ODXPilot change ODXProxy?
- No. ODXPilot is a client of ODXProxy like any other. The proxy stays a fast, thin forwarder, and existing ODXProxy users are unaffected.
- How do I see it? What will it cost?
- Request a demo and we'll walk you through it. Availability and pricing aren't decided yet.
Running your back office on Odoo?
See ODXPilot in a demo. Tell us which processes eat your team’s week, or start building on ODXProxy today.