Odoo AI agent tests: validate saved activities

Back
Kevin Riedl

11 min read · 5 Nov 2026
Last reviewed

Next
Made on your device, with no Instagram connection. We copy the post link for Instagram’s Link sticker.

Suppose an agent says it scheduled the follow-up. A new activity exists, the right salesperson owns it, and the deadline looks correct. The activity is attached to a different opportunity. A test that checks only whether something was created would accept the wrong result.

Test an Odoo AI agent against a written business-state contract. Specify the activity it may create, the records it must leave unchanged and when it must ask for clarification. Then test the result checker against deliberately wrong observations before using it to judge controlled runs on the actual installation.

Research checked: 5 November 2026. Product facts use official Odoo 20 documentation and source. We executed thirteen constructed JSON observations through a Python checker. We did not run Odoo, an AI model or a mail server. The downloadable native acceptance pack contains proposed checks, all marked NOT_RUN.

What should an Odoo AI agent test prove?

An Odoo AI agent test should establish that the permitted business outcome occurred within the agreed observation scope. The requested write must be correct, existing protected records must remain unchanged, and prohibited effects must be absent from the evidence. A successful conversation or tool response alone cannot establish those conditions.

A result checker, sometimes called an oracle, is the rule that compares observed evidence with an agreed expected outcome. Keep that rule outside the agent’s own explanation of its work. If the agent chooses the target and also decides whether its choice was right, an initial misunderstanding can pass through both steps.

Odoo’s AI server-action documentation assigns business-rule enforcement to tool code, while the AI action selects the tool and arguments. The acceptance reviewer still needs to examine the resulting business state.

Separate this task-level decision from architecture. Our agent harness guide explains the surrounding execution controls. Here, the question is narrower: what evidence would let you accept one scheduled CRM follow-up?

How do you specify one CRM follow-up activity?

Specify a CRM activity with an unambiguous opportunity reference, an approved assignee and an absolute deadline. Then define which existing fields must stay unchanged. Our fictional contract permits one call activity for OPP-42 in company A, assigned to user 7, due on 12 November 2026; it prohibits external email.

Odoo’s activity scheduling documentation includes both an assignee and a due date. Those are separate acceptance conditions: the correct date does not compensate for assigning the wrong colleague.

The fictional activity contract, agreed before any run
ConditionExpected resultReason to reject
TargetOne new call activity linked to OPP-42.A similarly named opportunity receives it.
CompanyThe linked opportunity belongs to company A.A reference in company B is used.
AssigneeFixture user 7.The caller or another salesperson is substituted.
Deadline2026-11-12.The observed date is 2026-11-13.
Protected stateThe selected opportunity fields and existing ACT-OLD activity remain unchanged.The opportunity stage or an existing deadline changes.
External effectNo outbound email event in the declared observation scope.The task produces an unapproved external message.
Ambiguous requestAsk which opportunity to use and make no business write.Guess an opportunity and create an activity.

The fixture also contains OPP-43 in company A and OPP-99 in company B. The pre-existing activity ACT-OLD belongs to OPP-43, is assigned to user 8 and is due on 10 November. These nearby records make a wrong match and an unrelated update visible.

The download uses normalized keys such as record_ref and assigned_user. They are not an Odoo API payload. In the inspected Odoo 20 activity source, document linkage uses model/reference fields; assignment and deadline use user_id and date_deadline. A native observer must map the installed schema into the agreed projection.

In this example, company belongs to the linked opportunity. The checker follows that relationship; it does not invent an activity-level company field. The projection also excludes technical bookkeeping such as chat records. Decide explicitly which additional business fields and notification effects your installation needs to observe.

Why must the result checker be tested first?

The result checker needs negative examples because a weak rule can make an incorrect workflow look reliable. Agree the expected classification before running the checker, and include outcomes where the requested activity is correct but another protected record changes. This tests the acceptance rule’s meaning, rather than its ability to recognize a happy example.

Our fixture labels are written separately from the checking function. The function reads the contract and before/after projections, then returns PASS, FAIL or UNKNOWN with reasons. It does not use the supplied assistant text or reported tool status as proof that a write occurred.

For example, a count-only checker would accept two activities if it merely required “at least one.” A field checker that searches only for the requested new row could miss an altered existing activity. The acceptance rule therefore compares the protected baseline as well as the new row.

That independence has a practical limit. Someone still has to approve the contract and validate the observer that builds the projection. A checker cannot detect a field its input omits, or prove that a file labelled “complete” contains every relevant side effect. Its scope must be visible in the release evidence.

What did the thirteen fixture checks show?

All thirteen constructed observations received their expected classification in our local checker run: two PASS, ten FAIL and one UNKNOWN. This establishes the behavior of the supplied Python demonstration on those inputs. It does not measure how often an Odoo agent succeeds, because no agent generated the observations.

Executed checker self-test, using invented observations
CaseConstructed final observationExpected / observed
S01The correct new activity; protected state unchanged.PASS / PASS
S02A completion message, but no new activity.FAIL / FAIL
S03The activity points to OPP-43 in the same company.FAIL / FAIL
S04The activity points to OPP-99 in company B.FAIL / FAIL
S05The new activity is assigned to user 8.FAIL / FAIL
S06The deadline is 13 November instead of 12 November.FAIL / FAIL
S07Two new activities are created.FAIL / FAIL
S08The correct activity exists, but OPP-42's stage becomes won.FAIL / FAIL
S09The correct activity exists alongside a synthetic outbound email event.FAIL / FAIL
S10An ambiguous request leads to a guessed target and a write.FAIL / FAIL
S11The ambiguous request gets the required clarification; no business state changes.PASS / PASS
S12The final observation is unavailable.UNKNOWN / UNKNOWN
S13The correct new activity exists, but ACT-OLD’s deadline changes.FAIL / FAIL

Download the checker and case file into one directory. Python’s standard library is sufficient:

python3 state-oracle.py

Compare the output with the recorded results. The process exits successfully when all expected classifications match, including the deliberate FAIL cases. A successful script exit therefore means the checker recognized the supplied examples; it does not mean thirteen business tasks passed.

The clarification branch uses an illustrative reviewed_disposition label. In a real test, a reviewer or separately validated adapter must establish that the agent asked for the missing opportunity reference. The script does not understand the quality of a natural-language question, and this label is not a documented Odoo response field.

When is UNKNOWN the correct result?

UNKNOWN is correct when the observer cannot establish the required final state. An inaccessible record, incomplete side-effect evidence or an unresolved observation window leaves the acceptance question open. Preserve what is known and investigate the observation failure before deciding whether the business action needs recovery; a missing read is not proof that no write happened.

Evidence boundaries for the result checker
ObservationWhat it can establishWhat remains open
Complete agreed business projectionWhether the included records satisfy the contract.Excluded fields and external effects.
Tool response or chat textWhat the system reported.Whether the expected result persisted.
Controlled mail-sink and transport evidenceObserved message attempts within the tested route.Any unobserved connector or alternate route.
Failed or incomplete final readThe evidence is insufficient.The business outcome, which stays UNKNOWN.

The synthetic outbound_events list is only a stand-in for external-effect evidence. An empty list cannot enforce a mail restriction. In a native rehearsal, route messages to an approved test destination and inspect the relevant transport evidence. If activity-assignment notifications conflict with the no-email requirement, resolve that behavior before accepting the workflow.

Choose an observation window that covers the task’s actual completion boundary. A queue still working at the cutoff is unresolved, not automatically successful or permanently failed. Record the query scope and cutoff with the result so the reviewer can distinguish late work from missing work.

Do not repeat an uncertain write to obtain a friendlier response. The Odoo write-recovery example explains the duplicate risk and recovery decision separately.

Which tests still need the actual Odoo installation?

Native acceptance must exercise the configured agent and its available tools on the actual Odoo build under review. Use approved test identities and verify the observation adapter against known records. Then compare the resulting evidence with the contract, keeping the fixture checker’s success separate from the agent’s ability to perform the task.

The native acceptance pack starts with sixteen proposed cases. Execution status is NOT_RUN, acceptance is PENDING, and observed values are empty. Adapt the cases to your installed modules and task before recording a result.

Native evidence required before task acceptance
Test areaEvidence to captureDecision it supports
Observation adapterKnown native records compared with the normalized projection.The checker reads the intended fields and relationships.
Ordinary taskInitial snapshot, exact request, final activity and protected records.The configured agent can complete the permitted task.
Identity and companyAgent user, company context, allowed target and refused alternative.The run uses the intended authority.
AmbiguityA request matching two opportunities, the clarification and unchanged business state.The workflow waits for missing information.
External effectsControlled delivery route and observed message attempts.The actual notification behavior meets the contract.
Interrupted observationKnown run identity, incomplete evidence and the recovery decision.Unknown outcomes do not become blind retries.
Changed configurationBuild/tool/prompt identity and the repeated accepted cases.A previous result still applies to the revised workflow.

Use the launch QA checklist for the wider release decision. This task pack addresses the activity workflow and its observation evidence.

The observer needs authorized access to the test population. Its broader view, if required for reconciliation, must not be confused with the agent’s operating permissions. The separate Odoo 20 company-access tests own that native authorization matrix.

Record model or provider metadata when the tested route exposes it; mark unavailable details as unavailable. Preserve the tool configuration and prompt revision even when the model identity is opaque. A test record should describe the observed configuration and mark any unverified service details.

How should you review repeated agent runs?

Review repeated agent runs individually before summarizing them. Each record needs the starting fixture, exact request and observed outcome, with a reason for any FAIL or UNKNOWN. Agree the repetitions and acceptable variation for the task’s consequences before execution; the thirteen checker examples provide no statistically justified production threshold.

Start repeated trials from an equivalent baseline unless the case explicitly tests existing work. Otherwise, the second run may encounter yesterday’s activity and test a different question. If repeated delivery is part of the workflow, define whether it should reuse an existing activity, ask for confirmation or create another one.

Track business-state correctness separately from communication quality. An agent can leave the correct record while giving the user an unhelpful explanation. Conversely, a polished explanation cannot rescue a wrong assignee. Both matter, but combining them into one impression makes defects harder to diagnose.

Keep a forbidden external write visible as its own failed condition. It should not disappear inside an average of easy tasks. For contractual measures and response ownership, use the agent SLA template; this article supplies one bounded task’s acceptance evidence.

What would we approve for release?

We would approve only the bounded activity task whose expected outcome, observation scope and native evidence have been accepted by the responsible owner. The fixture checker is useful preparation because it exposes weak acceptance rules cheaply. It becomes release evidence only alongside successful observation of the actual configured workflow and its required failure handling.

Begin with the ordinary activity and the wrong-target counterexample. Add the case where the new row is correct but an existing activity changes. That combination forces the team to state both what the agent may do and what must remain protected.

If you need an independent release decision, Wavect’s software quality assurance service can help define and review that evidence. Bring the task contract, your installed configuration and the cases that remain unresolved. A green demonstration is most useful when the reviewer can explain exactly what it proves.

Odoo AI agent testing FAQ

Does a successful tool call prove the activity was created correctly?
It proves only what the tool response reports unless independent evidence establishes the requested result. Check the target opportunity, assignee and deadline, then inspect the protected records and declared side effects. The acceptance contract determines which observations are necessary; a generic success flag cannot replace them.
Is a screenshot enough evidence?
A screenshot can help a reviewer understand what a user saw, but it may omit record identity, filtered rows or an unexpected update elsewhere. Preserve the exact test request and a reproducible observation of the agreed business fields. Use screenshots as supporting evidence when the interface itself is part of acceptance.
Can a second language model grade the result?
A model can help review ambiguous prose, but exact record references and deadlines are suitable for deterministic comparisons. Keep the expected state under independent ownership and validate the observer. If a model judges communication quality, record that judgment separately from the business-state result and include human review where the label remains uncertain.
Does the fixture PASS rate measure Odoo’s AI?
No. The thirteen observations were constructed deliberately, and no AI generated them. Two are intended to satisfy the contract, ten are intended to fail it, and one lacks final evidence. The successful checker run means all thirteen classifications matched their labels. It says nothing about an agent’s success frequency.
Must every agent use the exact same tools?
Different implementations can reach the same permitted business outcome. Test the final-state contract while also enforcing the approved tool and authority boundaries for each implementation. Different sequences may meet the contract. An unapproved external message or excessive authority remains relevant even when the requested activity looks correct.
Why include clarification as a passing outcome?
Some requests do not identify a unique permitted action. In the ambiguous fixture, success means asking for the missing opportunity reference while leaving business records unchanged. A reviewer must verify the clarification evidence. Creating a plausible activity before resolving the ambiguity fails that contract, even if the agent sounds confident.
Should you rerun the task after an inconclusive observation?
First determine what is already known about the original run. The write may have completed even though its observation failed. Preserve the run identity, investigate the target state and follow the workflow’s recovery rule. Repeating a write without resolving that uncertainty can create another activity and turn an observation problem into a business defect.

Production AI help

Building an AI product and worried about inference cost, architecture, or production readiness? Wavect helps founders turn AI prototypes into reliable production systems.

Explore the service path:

Inbox, without the noise

Follow the work that matters to you

Get a short email when we publish something new. Follow the whole blog or only the problems you care about.

What would you like to receive?
Choose your topics

Free, double opt-in, no tracking pixels.

Back
Kevin Riedl

11 min read · 5 Nov 2026
Last reviewed

Next

Get the next Delivery and QA field note

One concise email when we publish. No tracking pixels, and no inbox filler.

Free, double opt-in, no tracking pixels.