Make your AI read the Odoo source before it writes code
Bắt AI đọc source Odoo trước khi viết code
Version-specific Odoo references, a trace-first workflow and two specialist agents. Every claim cites a file and a line, and every change is proven on a scratch database.
Tài liệu Odoo đúng phiên bản, quy trình tra source trước khi code và hai agent chuyên trách. Mọi khẳng định đều có file và dòng, mọi thay đổi đều được kiểm chứng trên database thử.
The problem
Vấn đề
AI writes Odoo code that looks right
AI viết code Odoo trông có vẻ đúng
It works from memory, not from your source, and the mistakes are always the same few.
Nó làm theo trí nhớ chứ không theo source của bạn, nên lỗi lúc nào cũng chỉ là vài kiểu quen thuộc.
Symbols that don't exist
Symbol không tồn tại
sale.order.delivery_datesales_team.group_sale_admin
Anchors from another module
Xpath bám vào module khác
The install stops at "cannot be located in parent view".
Cài module dừng ở lỗi "cannot be located in parent view".
The wrong hook
Override sai chỗ
It overrides action_confirm; the work is in _action_confirm.
Override action_confirm, trong khi việc thật nằm ở _action_confirm.
Data dropped
Mất dữ liệu
A stored field renamed without a migration.
Đổi tên field stored mà không viết migration.
An unchecked sudo()
sudo() không kiểm soát
No stated reason and no access check first.
Không nêu lý do, không kiểm tra quyền trước.
"Tests pass"
"Test pass rồi"
Exit code 0, though not a single test ran.
Exit code 0, dù chưa có test nào chạy.
Demo
See it work
Xem cách nó làm việc
Every terminal line in the video is real output on Odoo 18.
Mọi dòng terminal trong video đều là output thật trên Odoo 18.
How it works
Cách hoạt động
One workflow for every Odoo change
Một quy trình cho mọi thay đổi Odoo
odoo-workflow runs before any code is written, and again before anything is called done. The two gates let nothing through on a guess.
odoo-workflow chạy trước khi viết code, và chạy lại trước khi coi là xong. Hai cổng chặn không cho gì đi qua bằng phỏng đoán.
StepBước 0 / 6
Runtime and versionRuntime và phiên bản
Finds the core, the conf and the addons, and reads the version from odoo/release.py. Nothing is assumed.Tìm core, conf và addons, rồi đọc phiên bản từ odoo/release.py. Không giả định gì.
$ odoo_trace envversion 18.0 [odoo/release.py]addons r1 odoo/addons r2 addonsVERDICT: Odoo 18.0, 2 roots, 650 modules
StepBước 1 / 6
Trace
Looks up every model, field, method, view and xmlid the change touches, in your source.Tra mọi model, field, method, view và xmlid mà thay đổi đụng tới, ngay trong source của bạn.
$ odoo_trace field sale.order delivery_dateVERDICT: NOT FOUND; closest: commitment_date (label 'Delivery Date')$ odoo_trace field sale.order commitment_dateaddons/sale/models/sale_order.py:103 via=self Datetime$ odoo_trace xmlid sale.view_quotation_treeVERDICT: FOUND addons/sale/views/sale_order_views.xml:205
StepBước 2 / 6 · gate
Context Brief
One row per symbol, each with a file:line or NOT FOUND.Mỗi symbol một dòng, có file:line hoặc NOT FOUND.
- Every row answered: go onMọi dòng đều có câu trả lời: đi tiếp
- A symbol with no row: no codeSymbol chưa có dòng: không viết code
symbol sourceversion 18.0 odoo/release.pydelivery_date NOT FOUNDcommitment_date sale/models/sale_order.py:103quotation list sale/views/sale_order_views.xml:2054 rows, 4 answered
StepBước 3 / 6
PlanKế hoạch
Ten bullets at most, one commit per repository.Tối đa mười ý, mỗi repo một commit.
1. Show commitment_date on the quotation listHiện commitment_date trên danh sách báo giá optional="show" ontrên sale.view_quotation_tree2. No model change, no migrationKhông đổi model, không cần migrationcommit [IMP] sale_extra: show the delivery date on quotations
StepBước 4 / 6
ImplementTriển khai
The narrowest hook and the smallest change that does the job.Hook hẹp nhất và thay đổi nhỏ nhất đủ làm việc.
<record id="view_quotation_tree_delivery" model="ir.ui.view"> <field name="model">sale.order</field> <field name="inherit_id" ref="sale.view_quotation_tree"/> <field name="arch" type="xml"> <field name="commitment_date" position="attributes"> <attribute name="optional">show</attribute> </field> </field></record>
StepBước 5 / 6 · gate
Definition of doneĐịnh nghĩa "xong"
Install and test on a throwaway database.Cài và test trên database dùng xong bỏ.
- Installed, tests ran, none failed: doneCài được, test có chạy, không lỗi: xong
- Zero tests ran: not done, whatever the exit code0 test chạy: chưa xong, dù exit code là gì
$ odoo-bin -d scratch_sale_extra -i sale_extra \ --test-enable --test-tags /sale_extra \ --stop-after-init# installs on a database used oncecài được trên database chỉ dùng một lần# more than zero tests rancó hơn 0 test đã chạy# none failedkhông test nào lỗi
StepBước 6 / 6
Review
The odoo-code-review agent scores the diff against the rules of your version.Agent odoo-code-review chấm diff theo quy tắc của đúng phiên bản bạn dùng.
odoo-code-review · Odoo 18.0ORM & model methods 30%Views & XML 15%Fields 15%Decorators 10%Performance 10%Security 5% …blocking issues first, each with file:linelỗi chặn merge trước, mỗi lỗi có file:line
What's inside
Bên trong
The difference, part by part
Khác biệt khi có plugin, từng phần một
Same request, same assistant. On the left what it writes from memory, on the right what it writes with agent-skills installed.
Cùng một yêu cầu, cùng một trợ lý. Bên trái là thứ nó viết theo trí nhớ, bên phải là thứ nó viết khi đã cài agent-skills.
You askBạn hỏi"Show a priority on the quotation list, hidden once the order is confirmed." Odoo 18."Thêm cột priority vào danh sách báo giá, ẩn khi đơn đã xác nhận." Odoo 18.
<xpath expr="//tree" position="inside"> <field name="x_priority" attrs="{'invisible': [('state', '=', 'sale')]}"/></xpath>
<tree>is deprecated in Odoo 18<tree>đã bị thay ở Odoo 18attrs=is rejected since Odoo 17attrs=bị từ chối từ Odoo 17
<xpath expr="//list" position="inside"> <field name="x_priority" invisible="state == 'sale'"/></xpath>
<list>, as the Odoo 18 pack says<list>, đúng như gói Odoo 18 ghi- A direct expression instead of
attrsBiểu thức trực tiếp thay choattrs
From skills/odoo-18.0/references/api-highlights.md. Each version has its own pack.
Lấy từ skills/odoo-18.0/references/api-highlights.md. Mỗi phiên bản có gói riêng.
You askBạn hỏi"Add a stored field x_age_days on sale.order.line: days since create_date.""Thêm field stored x_age_days trên sale.order.line: số ngày kể từ create_date."
I assumed Odoo 18 (or 19). x_age_days = fields.Integer( compute='_compute_x_age_days', store=True) $ odoo-bin -u x_eval --test-tags /x_eval0 failed, 0 error(s) of 0 tests exit 0
- The version is guessed; nothing is citedPhiên bản là đoán; không trích dẫn gì
- Zero tests ran, and it still reads as greenKhông test nào chạy mà vẫn báo xanh
version 18.0 odoo/release.pyfield create_date odoo/models.py:288field x_age_days NOT FOUND, name is freemigration stored compute odoo/models.py:3474 → version 1.1 + pre-migrate.py done scratch_x_eval: 0 failed of N tests, N > 0
- Every row cited before a line of codeMọi dòng có nguồn trước khi viết code
- Proven on a throwaway databaseKiểm chứng trên database dùng xong bỏ
The README's measured task: the grader passed 2 of 3 expectations without the skill and 3 of 3 with it.
Task đã đo trong README: người chấm cho đạt 2/3 tiêu chí khi không có skill, 3/3 khi có.
You askBạn hỏi"What runs when a sale order is confirmed?""Khi xác nhận đơn bán hàng thì những gì chạy?"
action_confirm() in sale/models/sale_order.pysets the state to 'sale' and createsthe delivery.
- One module, from memoryMột module, theo trí nhớ
- Misses every hook other modules addBỏ sót hook mà các module khác thêm vào
$ odoo_trace method sale.order _action_confirm#1 website_sale_slides :10 _action_add_members#2 sale_project :125 _timesheet_service_generation#3 repair :26 _create_repair_order#4 sale_stock :180 _action_launch_stock_rule#5 sale_purchase :20 _purchase_service_generation#6 delivery :147#7 sale :1217 the base, no super()
- All 7 definitions, in the order they runĐủ 7 định nghĩa, đúng thứ tự chạy
- The hook each module addsHook mà từng module thêm vào
Real output on the Odoo 18.0 source, each line in that module's models/sale_order.py.
Output thật trên source Odoo 18.0, mỗi dòng nằm trong models/sale_order.py của module đó.
You askBạn hỏi"Review my diff before I merge it.""Review diff của tôi trước khi merge."
Looks good to me. Ship it.
- No criteria and no scoreKhông tiêu chí, không điểm số
- The unexplained
sudo()goes throughsudo()không lý do vẫn lọt qua
score 78 / 100ORM & model methods 26 / 30Views & XML 15 / 15Performance 6 / 10 search() in a loop :58Security 2 / 5 sudo(), no reason :42 blocking 1 suggestions 3
- Weighted criteria for your Odoo versionTiêu chí có trọng số theo phiên bản Odoo
- What blocks the merge, with file and lineChỉ rõ cái chặn merge, kèm file và dòng
The weights are the agent's own: ORM 30%, views 15%, fields 15%, performance 10%, security 5% and more.
Trọng số là của chính agent: ORM 30%, view 15%, field 15%, hiệu năng 10%, bảo mật 5% và các mục khác.
You askBạn hỏi"Commit this change.""Commit thay đổi này."
$ git add .$ git commit -m "update sale order"
- Stages every file in the treeStage mọi file trong thư mục
- No tag, no module, no reasonKhông tag, không module, không lý do
$ git add sale_extra/models/sale_order.py \ sale_extra/views/sale_order_views.xml$ git commit -F msg [IMP] sale_extra: add priority to quotations Sales sorts quotations by urgency.
- Staged file by fileStage từng file một
- Odoo's own
[TAG] module:formatĐúng kiểu[TAG] module:của Odoo
The rules come from Odoo's git guidelines, which odoo-commit follows.
Quy tắc lấy từ hướng dẫn git của Odoo, mà odoo-commit tuân theo.
Trace helper
It checks instead of remembering
Kiểm tra thay vì nhớ
odoo_trace.py parses your Odoo source with Python's ast and answers with an absolute file:line, or NOT FOUND with the closest real names.
odoo_trace.py phân tích source Odoo bằng ast của Python và trả về file:line tuyệt đối, hoặc NOT FOUND kèm các tên thật gần nhất.
- Read-only, standard library, no networkChỉ đọc, thư viện chuẩn, không gọi mạng
- Finds the core even outside the projectTìm được core kể cả khi nằm ngoài project
- Exit codes: 0 found, 1 not found, 2 setup errorExit code: 0 thấy, 1 không thấy, 2 lỗi cấu hình
- Version, core and rootsPhiên bản, core và roots
odoo_trace env - Does a field exist, and where?Field có tồn tại không, ở đâu?
odoo_trace field sale.order access_url - A method, in super() orderMột method, theo thứ tự super()
odoo_trace method sale.order _action_confirm - Does an xmlid exist?Xmlid có tồn tại không?
odoo_trace xmlid base.lang_vi_VN - Files a module never loadsFile mà module không bao giờ load
odoo_trace unlisted x_eval
One real task
Một task thật
Same model, same prompt, different result
Cùng model, cùng prompt, khác kết quả
"In module x_eval, add a stored computed integer field x_age_days on sale.order.line: days since the line's create_date." On Odoo 18 with the source outside the project, graded blind.
"Trong module x_eval, thêm field integer computed stored x_age_days trên sale.order.line: số ngày kể từ create_date của dòng." Trên Odoo 18, source nằm ngoài project, chấm mù.
release.py18.0, đọc từ release.pyfile:line3 lần gọi tool, không có file:lineBenchmarks
Đo lường
Measured on real Odoo source
Đo trên source Odoo thật
Run on Odoo 18 and 19 with Claude Opus agents and a blind grader.
Every result is published.
Chạy trên Odoo 18 và 19, với agent Claude Opus và người chấm mù.
Mọi kết quả đều công khai.
Trace questions answered
Câu hỏi trace trả lời đúng
Expectations met
Tiêu chí đạt
Blind grader, 32 pairs
Chấm mù, 32 cặp
The trade-off: about twice the output tokens, because it reads before it writes. Labels and typos take a fast path.
Đánh đổi: khoảng gấp đôi token đầu ra, vì nó đọc trước khi viết. Sửa nhãn hay lỗi chính tả thì đi đường tắt.
Install
Cài đặt
Up and running in a minute
Cài xong trong một phút
Pick the route for your assistant.
Chọn cách cài hợp với trợ lý của bạn.
Skills and agents together. Add --scope project to record it in the project.
Cài cả skill lẫn agent. Thêm --scope project để ghi vào project.
Pick odoo-workflow and the pack for your version. Skills only: the agents need Claude Code.
Chọn odoo-workflow và gói đúng phiên bản. Chỉ cài skill: agent cần Claude Code.
Copies one pack to where your assistant reads it; versions skills lists them.
Chép một gói vào chỗ trợ lý của bạn đọc; versions skills liệt kê các gói.
FAQ
Frequently asked questions
Câu hỏi thường gặp
Something else? Ask on GitHub Issues.
Còn thắc mắc khác? Hỏi trên GitHub Issues.
What is Agent Skills for Odoo?Agent Skills cho Odoo là gì?
odoo-workflow skill with a read-only trace helper, and two agents, odoo-code-tracer and odoo-code-review. It is not an Odoo module: nothing is installed in your database.odoo-workflow kèm helper trace chỉ đọc, và hai agent odoo-code-tracer, odoo-code-review. Đây không phải module Odoo: không cài gì vào database của bạn.How do I use Claude Code with Odoo?Dùng Claude Code với Odoo như thế nào?
odoo.conf.claude plugin marketplace add unclecatvn/agent-skillsclaude plugin install agent-skills@unclecat-agent-skillsodoo.conf của bạn.claude plugin marketplace add unclecatvn/agent-skillsclaude plugin install agent-skills@unclecat-agent-skillsDoes it work with Cursor, Codex and other AI assistants?Có dùng được với Cursor, Codex và trợ lý AI khác không?
Which Odoo versions are supported?Hỗ trợ những phiên bản Odoo nào?
odoo/release.py, never assumed, and the matching pack is loaded. The workflow and its helper are checked against the Odoo 18 and 19 source.odoo/release.py của core, không bao giờ đoán, rồi nạp đúng gói tài liệu. Quy trình và helper được kiểm tra trên source Odoo 18 và 19.What do I need on my machine?Cần chuẩn bị gì trên máy?
scratch_* databases for the tests; Node.js 18 or later only for the npx routes.scratch_* để chạy test; Node.js 18 trở lên chỉ khi cài bằng npx.Will it touch my database or send my code anywhere?Nó có đụng vào database hay gửi code đi đâu không?
scratch_<module> database that is dropped afterwards, and the assistant is told never to install or upgrade on a named database unless you ask. What your assistant sends to its model is up to the assistant.scratch_<module> dùng xong bỏ, và trợ lý được dặn không bao giờ cài hay nâng cấp trên database có tên trừ khi bạn yêu cầu. Trợ lý gửi gì cho model là do trợ lý quyết định.How is it better than asking the AI directly?Hơn gì so với hỏi AI trực tiếp?
sale.order.delivery_date, xpaths that stop the install, "tests pass" when no test ran. With it, every symbol gets a file:line or NOT FOUND before any code is written, and the change is proven on a scratch database. A blind grader preferred it 16 times to 6 over 32 pairs.sale.order.delivery_date, xpath làm cài module lỗi, "test pass" khi chưa test nào chạy. Có nó, mọi symbol đều có file:line hoặc NOT FOUND trước khi viết code, và thay đổi được kiểm chứng trên database thử. Người chấm mù chọn nó 16 lần, so với 6, trên 32 cặp.How do I update it?Cập nhật như thế nào?
Is it free?Có miễn phí không?
Odoo Debug
A free Chrome extension that shows why Odoo does what it does, in a panel right on the Odoo page.
Extension Chrome miễn phí cho bạn thấy vì sao Odoo làm như vậy, ngay trong một panel trên trang Odoo.

What is this field?Field này là gì?
Its type, value and module, and what recomputes it.Kiểu, giá trị, module của nó, và cái gì tính lại nó.
Why is this field read-only?Vì sao field này chỉ đọc?
The condition, its value right now, and the view that set it.Điều kiện, giá trị lúc này, và view đã đặt ra nó.
What did that call send?Lệnh gọi đó đã gửi gì?
Edit it and send it again right there, or copy it as cURL.Sửa rồi gửi lại ngay tại chỗ, hoặc copy thành cURL.
Why can't this user open it?Vì sao user này không mở được?
The rule that refuses, and the group that would let them in.Rule nào chặn, và group nào sẽ cho phép.
Where does this text come from?Chữ này từ đâu ra?
Pick it on the page: its source, and where to change it.Chọn ngay trên trang: nguồn của nó và chỗ để sửa.
What will this install bring?Cài app này kéo theo gì?
Every module it installs and auto-installs.Mọi module nó cài và tự cài kèm.
Where is that technical screen?Màn hình kỹ thuật đó ở đâu?
Models, views, rules, crons: one click, no debug mode.Model, view, rule, cron: một cú bấm, không cần debug mode.
Why is this screen slow?Vì sao màn hình này chậm?
An N+1, the line running it, and where the time goes.Lỗi N+1, dòng code gây ra nó, và thời gian đi đâu.
What would this change do?Thay đổi này sẽ làm gì?
A Python dry run: see the result, nothing is saved.Chạy thử Python: thấy kết quả, không lưu gì.
Stop guessing. Read the source.
Đừng đoán. Hãy đọc source.
Free and open source, for Odoo 16 to 19.
Miễn phí, mã nguồn mở, cho Odoo 16 đến 19.