Odoo 19 · verifying the write

How do you verify what an AI agent actually wrote to your Odoo?

Short answer: you re-read the record from the database on a fresh, independent cursor after the transaction commits, and compare it field by field against what the agent was asked to do. A success message is the tool’s own claim, not a fact the database confirmed. Everything else, approvals, dry-runs, and logs, is worth having but answers a different question.

A log tells you what the agent tried. An approval tells you what a write would do. Only verification tells you what the database now holds.

This is the one property the "safe AI writes to Odoo" conversation keeps skipping. Approval and dry-run check before the write. Logs record the attempt. Neither re-reads the committed row, so neither catches the write that stored the wrong value and still reported success. Here is the distinction, made plainly, and what verification has to do to be real.

Written by nanti.ai. Odoo quotes are verbatim from Odoo’s documentation; the rest are findings we read in the Odoo 19 Enterprise source. We build the Execution Layer for Odoo, which exists to verify the write path, so read us knowing that. Corrections welcome at hello@nanti.ai.

Three checks, three different jobs

Before, tried, and after.

Three things get called "verification" and only one of them is. The gap between them is where a wrong value hides. Line them up on a single axis, when each one looks, and the distinction is unmistakable.

Before commit

Approval and dry-run

checks what would happen

An approval step or a dry-run inspects the write before it lands and asks whether it should go ahead. It is a good control, and it catches a bad plan. But it examines a proposal, not the row the database ends up holding, so it cannot tell you what actually persisted once the transaction commits.

The attempt

The audit log

records what the agent tried

A log captures what the agent asked for and what the tool returned. That is worth having. But what the tool returned is the tool’s own claim, so if the tool reports a success the record never received, a faithful log records that false success perfectly. A log tells you what was attempted, not what is now true.

After commit

Post-commit verification

confirms what the database now holds

Verification re-reads the committed row from the database on a fresh, independent cursor after the transaction closes, and compares it field by field against what the agent was asked to do. It is the only one of the three that reports what the database actually contains, rather than what the write meant to do or claimed it did.

Approval and the log are necessary, and a serious system keeps both. But an approval waved a plan through, and a log recorded the success the tool announced. Only re-reading the committed row can tell you the row does not say what everyone was told it says.

The answer, in mechanism

Re-read the row, field by field.

Verification is not a feeling of confidence or a green checkmark in a chat window. It is a specific, checkable procedure, and none of its parts come free with a connection.

  1. 01

    Wait for the transaction to actually commit

    Verification happens after the write closes, not during it. A read inside the same transaction sees the transaction’s own uncommitted changes, not what persisted, so it confirms intent rather than reality.

  2. 02

    Re-read the record on an independent cursor

    The committed row is read back from the database on a fresh connection, outside the transaction that wrote it. Looking from outside is what makes the read a check on the database rather than a check on the write.

  3. 03

    Compare each field to the intent, and name any that disagree

    Every field the write was meant to change is compared against what the caller intended and the value read back in-transaction. If any disagrees, the write is reported failed with the offending field named, not dressed up as a blanket success.

Why it is the only check that matters here

The wrong value that reported success.

There is one failure that an approval cannot see and a log cannot catch, because both trust the write’s own account of itself. It is also the most dangerous, because everyone downstream is told it went fine.

What everyone was told

The agent asked to set a value, the tool returned success, the approval had already passed, and the log recorded a clean write. Every surface a human or a model can see says the change landed.

What the database says

The row holds a different value, or the old one. A lock date, a business rule, a silent coercion, or a write to the wrong record left the database saying something other than what was reported. Only a post-commit re-read compares the two and refuses the false success.

This single case, success reported over a write that did not land as intended, is the whole reason verification exists. If your AI can write to Odoo and nothing re-reads the row, this failure is invisible until the numbers stop reconciling.

How the Execution Layer does it

Proven by breaking it on purpose.

The Execution Layer for Odoo is built to this exact standard, and it is designed so you do not have to take the claim on faith.

The mechanism

Every write is verified after commit on an independent database cursor, and each field is compared against both the in-transaction read-back and the caller’s declared intent. When they disagree, it returns VERIFICATION_FAILED naming the offending field, not a happy echo.

The proof

The behaviour is proven by deliberate fault injection: a test corrupts the stored value behind a write, and the product refuses to return the success echo, reporting the mismatch instead. Releases are gated on that adversarial test suite.

What you can check

The enterprise modules are source-available, so you can read exactly how verification behaves rather than trust a description of it. It is available now on Odoo 19 Community and Enterprise, and the failure suite ships with it, so you can verify the behaviour on your own staging before production.

Plain answers

Asked, answered.

How do you verify what an AI agent actually wrote to your Odoo?

You re-read the record from the database on a fresh, independent cursor after the transaction commits, and compare it field by field against what the agent was asked to do. A success message is the tool’s own claim, not a fact the database confirmed. Verification is the step that turns "the tool said it worked" into "the row now holds this value", and it is the only check that can tell the difference. Reading the row back inside the same transaction is not enough, because that read sees what the transaction wrote, not what finally committed.

Isn’t an audit log enough to prove what the AI wrote?

No. An audit log records what the agent tried and what the tool returned, which is the tool’s own account of events. If a write lands on the wrong record, or a success sentence is composed from what the action intended rather than from a database read, a faithful log records that false success exactly as it was reported. A log is a record of the claim; verification is a check of the fact. You want both, but only one of them catches a wrong value that stored and still reported success.

Doesn’t an approval or dry-run step already confirm the write?

No, and this is the distinction most tools blur. An approval or a dry-run runs before commit: it checks what a write would do and asks whether to proceed. That catches a bad plan, and you should use it. But it inspects a proposal, not the row the database ends up holding, so it cannot see a value that drifts or lands wrong at commit time. Checking beforehand and confirming afterward are two different jobs, and only the second one is verification.

What can post-commit verification catch that a log and an approval cannot?

The silent wrong value: a write that stored something other than intended, or did not store at all, while the tool still reported success. An approval waved through a plan that looked fine. A log recorded the success the tool announced. Only re-reading the committed row from the database and comparing it to the intent reveals that the row does not say what everyone was told it says. That single case, success reported over a write that did not land as intended, is the whole reason verification exists.

What does field-by-field verification mean?

It means every field the write was supposed to change is checked against two things: the value the caller intended, and the value read back inside the transaction, both compared to the value the database holds after commit. If any field disagrees, the write is reported as failed and the offending field is named, rather than a single blanket "success" or "failure". Naming the field is what makes a verification failure something you can act on instead of a mystery.

Why re-read on a separate, independent connection?

Because a read inside the same transaction sees the transaction’s own uncommitted changes, not what actually committed to the database. To confirm what persisted, you have to look from outside the transaction that wrote it, on an independent cursor, after commit. Verifying from inside the write is like proofreading your own sentence in your head: it confirms what you meant, not what landed on the page.

Can you verify what Odoo 19’s native AI wrote?

Be fair first: Odoo 19 ships a real, capable AI agent, and for reading and drafting it is well fenced. But on the write path there is no read-back. We read the Odoo 19 Enterprise source: when a server action returns nothing, Odoo composes a success sentence from what the action intended, so the record is not re-read to confirm the change landed. That means the native agent reports success from intent, not from a verified database read, and post-commit verification is exactly the property it does not provide on its own.

What does nanti.ai do about this?

The Execution Layer for Odoo verifies after commit on an independent database cursor, comparing each field against both the in-transaction read-back and the caller’s intent, and reports VERIFICATION_FAILED naming the offending field rather than returning a happy echo. The behaviour is proven by deliberate fault injection: a test corrupts the stored value behind a write, and the product refuses to report success. Releases are gated on that adversarial test suite. It is available now on Odoo 19 Community and Enterprise, with the enterprise modules source-available so you can read exactly how it behaves, and the failure suite ships with the product so you can run it on your own staging. See the Execution Layer for Odoo (nanti.ai/execution-layer).

The proof layer

Confirm it from the database.

A log records the claim. Verification checks the fact. The Execution Layer for Odoo re-reads every AI write from the database after commit and refuses the success echo when the row disagrees. See also can AI write to Odoo safely, which Odoo AI tools actually verify what they wrote, does Odoo’s native AI have an audit trail, and Odoo MCP servers, compared.

Evaluating an AI tool that writes to your Odoo?

Name it. We read its public docs and your description and tell you, in writing within five working days, whether it checks the proposal before it writes, logs the result, or re-reads the committed row after. Sourced line by line, using the same pre-registered method as our public write-verification census. Free, no pitch, and we tell you the truth even if the tool is not ours.

Get the Write-Check

Our own write-verification, the Execution Layer for Odoo, is available now. The verdict stays honest either way.

Not ready to talk? Follow what we ship.

An email when something real ships. No newsletters, no spam.

Living this problem every day and want to shape what comes next? We work closely with a small number of Odoo teams on the Execution Layer for Odoo, the ones who need to know the row the database kept matches what the AI reported. Tell us about your Odoo setup.