FIELD NOTE · IMPLEMENTATION EVIDENCE

Why Odoo ACLs are necessary but not enough for AI writes

Odoo ACLs decide whether the connected user may write. They do not decide whether an AI agent should make this change now, with this payload, without a person seeing it first.

Published: August 18, 2026 · Last updated: August 27, 2026

MCP endpoint: https://mcp.erpipe.com/mcp

Answer first

Odoo ACLs answer whether the connected user may write. They do not answer whether an AI agent should make this change now, against these records, with this payload. ERPipe keeps writes off by default and can layer preview, field policy, validation, and a consume-once human decision in front of Odoo. Odoo's own access checks still run.

This is the hosted product at https://erpipe.com/, not a change to the MCP URL. Clients still call https://mcp.erpipe.com/mcp.

Environment and method

This field note describes ERPipe's hosted write path as implemented and tested through its preview, validation, approval, execution, audit, and ambiguous-outcome checks. The Odoo connection still uses a real Odoo user; the gateway does not use approval to bypass groups, ACLs, record rules, or field access.

The method was deliberately narrow: start with writes disabled, prepare the exact model, record ids, fields, and values, run policy checks, require one human decision, execute once, then inspect the recorded outcome. It is not a benchmark and it is not evidence that every Odoo business workflow is safe to automate.

Why a person is still in the loop

An agent can draft a correct invoice date and a disastrous partner change with the same confidence. Human approval is the visible lock: the owner sees the model, method, ids, and payload, then approves once or rejects. The grant does not silently widen.

Chatter notes and allowlisted methods can use separate gates so a comment is not treated like a stock move.

A finance-shaped path

That is the loop. It is not “the model posts whatever it wants after you clicked Connect.”

Result

The useful boundary is two independent decisions. Odoo answers may this user perform the operation? The gateway answers should this client and proposed payload be allowed to attempt it now? A human approval can narrow the second decision, but it cannot widen the first.

Keeping those decisions separate made revocation and failure handling clearer. A connection can be paused without changing Odoo groups. A rejected payload stays rejected. An uncertain result is recorded as unknown instead of being treated as a reason to post again.

What the owner actually sees

StepWhat happensWhat does not happen
PreviewPayload and target ids are shownOdoo is not changed
ValidateField policy and allowlists runA timeout is not retried blindly
ApproveOne owner decisionTeammates do not inherit a wider grant
ExecuteThe approved write runs onceAmbiguous results are not auto-replayed

If the Odoo call returns an unclear outcome, ERPipe marks it unknown. That is safer than posting twice because a gateway timed out.

Example: change a follow-up date

  1. Connection writes are still off. The agent can only search and read.
  2. You enable writes and keep owner approval on for create/write/unlink.
  3. The agent calls preview, then validate, then waits.
  4. You tap Approve in email or open /app/approvals.
  5. The write runs as the same Odoo user. Record rules still apply.

If you reject, nothing is posted. If you pause the connection, later tool calls get a paused error instead of a silent success.

Failure modes

How this differs from “the model asked me in chat”

Chat confirmation inside ChatGPT is not an owner inbox. Anyone with the chat can type “yes”. ERPipe’s approval is a workspace-owner decision on a specific previewed payload. The grant does not widen because the model sounded confident.

Original hosted fact (2026-08-18): when execute_approved_write returns HITL_APPROVAL_REQUIRED, that is a short wait, not a failure and not a reason to end the chat. Keep the same approval object, tell the owner to Approve, sleep 5–10 seconds, then poll get_write_approval_status (or retry execute with the same approval). After about 30–45 seconds if it is still pending, leave it in Approvals. The poll tool is hosted-only; it is named on the catalog.

Ambiguous Odoo results are marked unknown. The gateway does not blindly retry a posting because a timeout happened.

Limits

Human approval reduces one class of risk; it does not prove that the proposed accounting, inventory, or customer action is correct. Owners still need an appropriate Odoo user, backups, business controls, and a workflow-specific review. High-volume or time-critical processes may need a different control than approving each row.

This note covers ERPipe's current hosted behavior, not every MCP server. Inspect the implementation and test revocation, rejection, and unknown outcomes before enabling writes in another gateway.

Sources and related evidence

FAQ