MCP Tools Reference¶
Oduflow exposes 108 tools. They are reachable from any MCP client (Cursor,
Cline, Amp, Claude Code, …), locally with oduflow call, against a remote
Oduflow server with oduflow client, and — for a subset — over the
REST API.
Every tool below is documented with its parameters, defaults and the situations it is meant for. Jump straight to one from the index, or read a category end to end.
Locking
Many tools acquire a lock on exactly what they touch: one environment,
one production, one service / volume / database / template, the
team's credential store — or the whole team, for the few operations
that really are team-wide (the template mutations that remount other
environments' filestores). Each tool's section states its lock. Operations on different resources run in parallel. If another
operation on the same resource is already in progress, the call is
rejected with BusyError, naming the operation holding the lock and how
long it has held it (e.g. "Another operation on environment 'main'
(pull_and_apply, running for 4m12s) is in progress"), so a long install is
distinguishable from a hung one. A lock is released when its operation
finishes — including when the client that started it timed out and stopped
waiting, which is why restarting the environment is the wrong response.
Signatures straight from the server
oduflow list prints the current tool list, and oduflow list --verbose
adds descriptions — always in sync with the running version.
Tool index¶
-
create_environment·delete_environment·list_environments·get_environment_info·start_environment·stop_environment·restart_environment·update_environment·switch_branch -
pull_and_apply·install_odoo_modules·upgrade_odoo_modules·run_odoo_tests·list_installed_modules·get_environment_logs·read_output -
odoo_schema·odoo_search_read·odoo_create·odoo_write·odoo_unlink·odoo_call·run_db_query -
read_file_in_odoo·write_file_in_odoo·search_in_odoo·run_odoo_command·run_odoo_shell·http_request_to_odoo·reset_admin_password·connect_as_user -
-
save_as_template·save_production_as_template·list_templates·rename_template·delete_template·import_template·refresh_template·attach_filestore -
create_service·update_service·delete_service·restart_service·list_services·get_service_info·get_service_logs·run_service_command -
create_service_database·list_service_databases·get_service_database·rotate_service_database_password·delete_service_database -
create_volume·list_volumes·inspect_volume·delete_volume·read_file_in_volume·write_file_in_volume·search_in_volume·delete_file_in_volume -
list_service_presets·restore_service·delete_service_preset -
-
start_image_build·get_image_build·publish_image_build·cancel_image_build -
-
add_extra_repo·list_extra_repos·update_extra_repo·delete_extra_repo -
create_production·list_productions·get_production_info·production_logs·start_production·stop_production·restart_production·reconfigure_production·set_production_odoo_conf·delete_production -
update_production·rollback_production·set_production_auto_update·production_deploys -
snapshot_production·list_production_snapshots·restore_production·set_production_backup_schedule·prune_production_backups·production_backup_status·production_wal_status·control_production_wal·restore_cluster_pitr -
sync_production_mcp·production_odoo_info·production_odoo_read·production_odoo_preview_change·production_odoo_change_status·production_odoo_execute_change -
get_agent_instructions·get_odoo_development_guide·report_issue
Environment Management¶
Ephemeral, isolated Odoo environments — one per git branch. See Environment Management for the concepts behind them.
create_environment¶
Provision a new ephemeral Odoo environment: clone the repository, copy the template database, mount the filestore, start the container and route it.
Safe to call first, without listing environments: if one already exists under
this name it is returned as is — with its URL, and started when it was
stopped — and nothing is recreated. The single refusal is a branch mismatch: an
environment tracking another branch is left alone, since its database and URL
are in use. Move it with switch_branch, pass a different
env_name, or delete it first.
Parameters
branch- str · required — The git branch to clone (e.g.
19.0,feature/my-feature). env_name- str · default empty — Environment name. Empty defaults to the branch name. Use it to create several environments from the same branch (e.g.
env_name="client-a"withbranch="19.0"). template_name- str · default empty — Template profile to use as the database template. Pass
"none"to skip the template and initialise Odoo from scratch with-i base. When a template is given,repo_urlandodoo_imageare loaded from its metadata (and can still be overridden), and installed modules whose manifestversionin the checkout is higher than in the template database are upgraded before the environment is reported ready. repo_url- str · default empty — Git repository URL. Optional when
template_namesupplies it. odoo_image- str · default empty — Full Docker image with tag (e.g.
odoo:19.0). Optional whentemplate_namesupplies it. extra_addons- str · default empty — Comma-separated extra addon repos with branches, e.g.
"enterprise:19.0,custom-themes:main". The branch after the colon is mandatory. sanitize- bool · default
True— Run Odoo's native neutralization (deactivates outgoing mail servers and crons, disables payment providers, scrubs third-party API credentials, setsdatabase.is_neutralized) plus any custom scripts in the repository's.oduflow/odoo_sanitize/. Only applies to environments created from a template. auto_install_modules- str · default empty — Comma-separated modules to install right after provisioning (e.g.
"sale,purchase,stock"). Loaded from template metadata when a template is used and this is empty. env_vars- str · default empty — Comma- or newline-separated
KEY=VALUEpairs injected into the container. Commas inside values are preserved unless what follows looks like anotherKEY=; put one pair per line when in doubt. Merged per key over the template's own values, with these winning. A valuesecret:<name>references a team secret. hostname- str · default empty — Short Traefik hostname (e.g.
"qa"→qa.example.com). Replaces the team prefix in either hostname mode. from_production- str · default empty — Build this environment from a production's real data (database + filestore + repo/image/extra addons). Mutually exclusive with
template_nameandlocal_path. The copy goes through one managedprod-<name>template, published on first use and reused afterwards. local_path- str · default empty — Local fast path. Absolute path to a checkout on this host: Oduflow skips the clone and bind-mounts the directory live, so file edits are visible instantly with no git round-trip.
repo_urlis not required. Gated byallow_local_path.
Use it when
- A new feature branch needs its own running Odoo with realistic data.
- You want a throwaway copy of production data to reproduce a customer bug (
from_production). - You are iterating on code on this machine and want edits live in the container (
local_path). - An agent needs a safe target: calling it repeatedly is idempotent, not destructive.
oduflow call create_environment '{
"branch": "feature/invoice-report",
"template_name": "acme-19",
"extra_addons": "enterprise:19.0",
"auto_install_modules": "sale,account"
}'
delete_environment¶
Stop and remove every resource associated with an environment — container, database, filestore, ports and routing.
Parameters
env_name- str · required — The environment to tear down.
Use it when
- A branch is merged and its environment is no longer needed.
- You need to free an environment slot and no existing environment is worth keeping (otherwise prefer
switch_branch).
list_environments¶
List all managed environments with status, URL, current git branch, creation / last-activity / stopped timestamps, stop source, protection, Stack ownership and operator note.
Parameters
None.
Use it when
- Taking stock before creating another environment (slot pressure).
- Finding which environments are idle and can be reused or reclaimed.
get_environment_info¶
Full details for one environment: lifecycle and reuse metadata, database name, URL, repository, image, template, extra addons, workspace path, container status, and CPU/RAM stats. Fails with "does not exist" when the environment has neither an Odoo container nor a workspace.
Parameters
env_name- str · required — The environment to inspect.
Use it when
- You need the URL or database name to hand to someone or to another tool.
- Diagnosing "is it actually running, and what is it running?" before digging into logs.
- Checking which template and extra addons an environment was built from.
start_environment¶
Start all containers for a stopped environment.
Parameters
env_name- str · required — The environment to start.
wait- bool · default
True— Wait for Odoo to become ready, polling/web/healthevery 2 seconds for up to 120 seconds.
Use it when
- Resuming work on an environment the idle reaper stopped.
- A scripted flow must not continue until Odoo answers (
wait=True).
stop_environment¶
Stop the Odoo container, keeping the database, filestore and configuration.
Parameters
env_name- str · required — The environment to stop.
Use it when
- Freeing RAM and CPU on a busy host without losing the environment.
- Parking an environment you will come back to.
restart_environment¶
Restart the Odoo container. Python code is reloaded; the database is untouched.
Parameters
env_name- str · required — The environment to restart.
wait- bool · default
True— Wait for Odoo to become ready, polling/web/healthevery 2 seconds for up to 120 seconds.
Use it when
- Only Python logic changed and no database-backed definition moved (otherwise upgrade the module — see
pull_and_apply). - Odoo is wedged and you want a clean process before investigating further.
update_environment¶
Re-create the Odoo container without losing the database or filestore. Pulls the target image and rebuilds the container.
With no arguments it simply rebuilds from the current image and configuration — the fix for a broken container (packages accidentally removed, system files corrupted) reconnected to the existing data.
Parameters
env_name- str · required — The environment to update.
env_vars- str · default empty — Comma- or newline-separated
KEY=VALUEpairs that fully replace the current user-supplied variables. Empty keeps them. Database connection variables (HOST/USER/PASSWORD) are always preserved.secret:<name>references are supported. odoo_image- str · default empty — New Docker image with tag to pull and run (e.g.
odoo:19.0). Empty keeps the current image. hostname- str · default empty — New short Traefik hostname (e.g.
"qa"→qa.example.com). Changes the public URL. new_name- str · default empty — Rename the environment. The database, filestore, ports and credentials move with it. A pooled or explicit hostname is kept, so the URL stays; a name-derived hostname follows the new name. The scoped MCP endpoint moves from
/mcp/<old>to/mcp/<new>, so MCP clients must be re-pointed. Productions and stack members cannot be renamed here.
Use it when
- Bumping the Odoo image (e.g.
odoo:18.0→odoo:19.0) while keeping the data. - Changing container environment variables or wiring in a new secret.
- The container is damaged and you want a fresh one on the same data.
- The environment's name no longer describes what it holds. (If it should also move onto another branch, use
switch_branch— it renames along the way.)
switch_branch¶
Move an existing environment onto another git branch. Everything except the code stays: the database, filestore, URL / hostname, ports, database credentials and the scoped MCP token.
Reach for this when the team has no free environment slots and a previous
branch is finished (merged), or when that database and URL are worth keeping —
it replaces "delete the old environment, create a fresh one", which re-clones
the repository and re-copies the template database. With slots still free,
create_environment is simpler.
The branch must already exist on origin, so push it first. Oduflow diffs the old
and new tips and applies exactly the logic of pull_and_apply.
Errors and tracebacks come back in the response — do not chase them in the logs.
Parameters
env_name- str · required — The environment to move.
branch- str · required — Target git branch; it must already exist on origin.
install- str · default empty — Comma-separated modules to install (
-i). Empty leaves classification to Oduflow. upgrade- str · default empty — Comma-separated modules to upgrade (
-u). Empty leaves classification to Oduflow. restart- bool · default
False— Restart the container (for Python-only differences). strict- bool · default
False— Refuse instead of warning when the requested action looks incomplete for the diff. extra_addons- str · default empty — Extra addon repos with branches (e.g.
"enterprise:19.0") to switch along with the main repo. Empty keeps the current ones. new_name- str · default empty — Rename the environment in the same operation. The URL is kept, but the scoped MCP endpoint moves to
/mcp/<new name>.
Use it when
- Out of environment slots and an old branch is merged.
- A long-lived QA database and URL should follow a new branch.
- Keeping stakeholders on a stable link while the code underneath changes.
Database compatibility is not checked
Switching does not inspect which modules are installed in the retained
database. If the target code is incompatible, the apply command returns the
real failure or Odoo reports it at runtime. Live-mounted environments are
rejected — there the checkout is yours, so switch the branch in it and call
pull_and_apply.
Code Sync, Modules & Tests¶
pull_and_apply¶
Sync the latest code into an environment and apply the right Odoo action. This is the main development loop tool.
It works for both code-delivery modes, chosen automatically per environment:
- git — pulls the branch and resolves extra addons to shared immutable SHA checkouts before applying changes.
- live-mount (from
create_environment(local_path=...)) — your edits are already on disk; this just applies them, no git needed.
There are two ways to drive it:
- Explicit (recommended — you know what you changed): pass
install/upgradeand/orrestart=True. A guardrail compares your request against the detected changes and appends non-blocking warnings if something looks missing.strict=Truerefuses instead of warning. - Auto (leave everything empty): Oduflow classifies the changed files and decides install / upgrade / restart / refresh itself. Best when pulling commits you did not author.
Parameters
env_name- str · required — The environment to apply changes to.
install- str · default empty — Comma-separated modules to install (
-i). upgrade- str · default empty — Comma-separated modules to upgrade (
-u). restart- bool · default
False— Restart the Odoo container (for Python-only changes). strict- bool · default
False— Refuse to apply when the guardrail finds a likely missing action, instead of warning and applying anyway. summary_only- bool · default
False— Return a compact one-line action/status summary plus anoutput_idinstead of command logs and changed-file names. The raw output stays available throughread_output.
What to pass for which change
| You changed | Pass |
|---|---|
| View/QWeb XML, JS, CSS only | nothing — refresh the browser |
| Python logic / methods (no new fields or models) | restart=True |
A field, model, security rule, data record, ir.cron, mail template, or manifest data/depends |
upgrade="module" |
| A brand-new module | install="module" |
requirements.txt, .oduflow/requirements.txt, .oduflow/apt_packages.txt |
nothing — dependencies are reinstalled and the container restarted automatically |
Removed dependencies
Packages deleted from a requirements file are not uninstalled until the
container is rebuilt with update_environment.
Use it when
- Every time you push code and want it live in the environment.
- Pulling someone else's commits and you are not sure what they touched (auto mode).
- A CI-style flow needs a single call that both syncs and applies.
Errors come back inline
Errors and tracebacks are returned directly in the response — do not
call get_environment_logs to look for them. With
summary_only=True they are not inlined: read the full log with
read_output.
install_odoo_modules¶
Install Odoo modules (odoo -i) in an environment.
Parameters
env_name- str · required — The environment.
modules- str · required — Comma-separated modules to install (e.g.
"sale,crm,web").
Use it when
- Adding a module to an existing environment without pulling new code.
- Setting up prerequisites before
run_odoo_tests— testing an uninstalled module yields "0 of 0 tests".
upgrade_odoo_modules¶
Upgrade already-installed Odoo modules (odoo -u).
Unknown or uninstalled modules are rejected with a suggestion to use
install_odoo_modules or
pull_and_apply(install=...) instead.
Parameters
env_name- str · required — The environment.
modules- str · required — Comma-separated modules to upgrade (e.g.
"sale,crm,web"), or"all"on its own to upgrade every installed module (odoo -u all).
Use it when
- A model, field, view, security rule or data record changed and must be reloaded into the database.
- Re-applying a module's data files after editing them by hand.
run_odoo_tests¶
Run Odoo tests for specific modules. The modules must already be installed —
by default the run happens through an upgrade (-u).
Parameters
env_name- str · required — The environment.
modules- str · required — Comma-separated already-installed modules to test.
test_tags- str · default empty — Odoo
--test-tagsexpression narrowing the run:"/my_module:TestInvoice"(one class),"/my_module:TestInvoice.test_total"(one method),"-slow"(exclude a tag). Comma-separated, no spaces. Empty runs every test of the listed modules. Withupgrade=False, positive selectors must include one of the requested modules (e.g."slow/my_module"); exclusion-only selectors are scoped automatically. upgrade- bool · default
True— Upgrade the modules before testing. SetFalsefor a much faster re-run when the code is already loaded — but note Odoo then collects onlypost_installtests, so plainTransactionCaseclasses at the defaultat_installposition report "0 tests". If a class you expect does not run, re-run withupgrade=True. summary_only- bool · default
False— Return only Odoo's aggregateN failed, M error(s) of K testsline and anoutput_id; the full output stays available throughread_output.
Use it when
- Verifying a change before opening a pull request.
- Iterating on one failing test — narrow with
test_tagsrather than spending minutes on a full module upgrade. - Driving CI from an agent:
summary_only=Truekeeps the response small and the log reachable.
oduflow call run_odoo_tests '{
"env_name": "main",
"modules": "sale_custom",
"test_tags": "/sale_custom:TestInvoice.test_total",
"upgrade": false,
"summary_only": true
}'
list_installed_modules¶
List Odoo modules and their states as a table of name, state and installed version. By default only installed modules are shown.
Parameters
env_name- str · required — The environment.
name_filter- str · default empty — Substring match on the module name (e.g.
"sale"matchessale,sale_management,pos_sale). state_filter- str · default
"installed"— Module state:installed,uninstalled,to upgrade,to install. Pass an empty string for all states.
Use it when
- Checking whether a dependency is present before installing or testing.
- Auditing what a template-provisioned database actually has enabled.
- Finding modules stuck in
to upgradeafter a failed run.
get_environment_logs¶
Retrieve the last N lines from the environment's Odoo container log.
Parameters
env_name- str · required — The environment.
n_lines- int · default
100— Number of recent log lines to retrieve. grep- str · default empty — Case-insensitive substring filter — useful for finding a specific error, module or message.
level- str · default empty — Odoo log level filter:
ERROR,WARNINGorCRITICAL. Combines withgrep.
Use it when
- Odoo is running but misbehaving at runtime (a cron, a request, a worker).
- Tracking a warning that does not surface in a tool response.
Not for apply failures
pull_and_apply, switch_branch and
the module tools already return their errors and tracebacks inline. Reach
for the container log for runtime problems, not for those.
read_output¶
Read from a cached tool output by ID. Tools that can produce large output
(installs, upgrades, tests, pull_and_apply) cache it server-side and return
an output_id; this tool explores it without re-running anything.
Parameters
output_id- str · required — The cached output ID (e.g.
"a3f7c012") returned by the original tool. mode- str · default
"lines"—lines(a range, paginated withstart/end, default first 200),errors(only ERROR/WARNING/CRITICAL with ±5 lines of context),grep(case-insensitive substring search with line numbers),info(metadata only — line count, char count, error count, source tool),tail(last 100 lines). start- int · default
1— First line to return, 1-indexed. Used withlinesandgrep. end- int · default
0— Last line to return.0meansstart+200forlines, all results forgrep. grep- str · default empty — Search pattern for
mode="grep"; case-insensitive substring.
Use it when
- A
summary_only=Truecall reported a failure and you need the traceback. - A test run produced thousands of lines and you want only the errors (
mode="errors"). - Paging through a long install log without flooding the conversation.
Odoo Data Access¶
The odoo_* tools talk to the live Odoo HTTP server, exactly like an external
RPC client. Two consequences worth internalising:
- Edited Python code stays invisible until the environment is restarted (
pull_and_apply/restart_environment); XML views do reload. - Every call is its own committed transaction. Use
run_odoo_shellwhen you need a fresh registry,sudo(), private methods, a rollback, or several steps in one transaction.
odoo_schema¶
Inspect the Odoo schema: list models, or describe one model's fields
(XML-RPC fields_get).
Call this before writing a domain or a values dict — guessing field names is the most common cause of an empty result set or a confusing error.
Parameters
env_name- str · required — The environment.
model- str · default empty — Technical model name (e.g.
sale.order). Empty lists models instead. name_filter- str · default empty — Substring filter — on model names when listing models, on field names when describing a model.
attributes- str · default
"string,type,relation,required,readonly,selection"— Comma-separated field attributes to return. Odoo prunes them server-side, so a short list keeps the response small. Empty string returns every attribute. as_user- str · default empty — Login or numeric id to inspect as (empty = admin). Field visibility can differ per user.
limit- int · default
200— Maximum models when listing (0= no limit). Ignored when describing one model. offset- int · default
0— Models to skip when listing, for paging.
Use it when
- You need the exact technical name of a field before querying or writing.
- Finding which models a custom addon added.
- Checking whether a field is required, readonly, or a relation — and to what.
odoo_search_read¶
Search and read records — the ORM equivalent of XML-RPC search_read, with
access rights and record rules applied.
Prefer this over run_odoo_shell for reading data: it is far
faster and returns JSON you can parse.
Parameters
env_name- str · required — The environment.
model- str · required — Technical model name (e.g.
res.partner). domain- str · default
"[]"— Odoo search domain as JSON (e.g.'[["state","=","sale"]]'). A single bare leaf is accepted and wrapped for you. fields- str · default empty — Comma-separated field names, or a JSON array. Always pass this — reading every field pulls binary columns and blows up the response.
limit- int · default
80— Maximum rows, applied server-side. offset- int · default
0— Rows to skip, for paging. order- str · default empty — SQL-style ordering (e.g.
"date_order desc, id"). count_only- bool · default
False— Return only the number of matching records (search_count);fieldsandlimitare ignored. as_user- str · default empty — Login or numeric user id to run as. Empty = the environment's admin.
context- str · default empty — JSON object added to the call context (e.g.
'{"lang": "fr_FR", "active_test": false}').
Use it when
- Reading business data to verify a change took effect.
- Checking what a particular user can see (
as_user="portal@example.com") — permissions bugs show up here and nowhere else. - Counting records cheaply (
count_only=True). - Including archived records (
context='{"active_test": false}').
oduflow call odoo_search_read '{
"env_name": "main",
"model": "sale.order",
"domain": "[[\"state\",\"=\",\"sale\"]]",
"fields": "name,partner_id,amount_total",
"limit": 10
}'
odoo_create¶
Create one or many records — the ORM equivalent of XML-RPC create. Returns
the new ids.
Committed on success — no dry run
For a deliberate rollback, or several steps that must succeed or fail
together, use run_odoo_shell. If the call times out,
verify with a read before retrying — a repeat can create duplicates.
Parameters
env_name- str · required — The environment.
model- str · required — Technical model name (e.g.
res.partner). values- str · required — JSON object of field values, or a JSON array of such objects to create several records in one call.
as_user- str · default empty — Login or numeric user id to run as. Empty = admin.
context- str · default empty — JSON object added to the call context.
Use it when
- Seeding test data for a scenario.
- Reproducing a customer record that triggers a bug.
odoo_write¶
Update records — the ORM equivalent of XML-RPC write.
Committed on success — no dry run
Use run_odoo_shell when you need a rollback or one
transaction across several steps.
Parameters
env_name- str · required — The environment.
model- str · required — Technical model name.
ids- str · required — Record ids:
"42","1,2,3"or"[1,2,3]". values- str · required — JSON object of field values to set.
as_user- str · default empty — Login or numeric user id to run as. Empty = admin.
context- str · default empty — JSON object added to the call context.
Use it when
- Flipping a record into the state a test needs.
- Archiving instead of deleting (
values='{"active": false}') — usually what is actually wanted.
odoo_unlink¶
Delete records — the ORM equivalent of XML-RPC unlink.
Destructive and immediate
The records are gone when this returns, and there is no rollback. Confirm
the target set with odoo_search_read first.
Archiving (active = false via odoo_write) is usually
what is actually wanted.
Parameters
env_name- str · required — The environment.
model- str · required — Technical model name.
ids- str · required — Record ids to delete:
"42","1,2,3"or"[1,2,3]". as_user- str · default empty — Login or numeric user id to run as. Empty = admin.
context- str · default empty — JSON object added to the call context.
Use it when
- Cleaning up records you created for a test, in a throwaway environment.
odoo_call¶
Call a public Odoo model method — the XML-RPC execute_kw escape hatch for
everything the dedicated tools do not cover: read_group, name_search,
default_get, copy, message_post, action_confirm, and any method a
custom addon exposes.
ids is prepended as the first positional argument, so model="sale.order",
method="action_confirm", ids="42" sends args=[[42]]. Leave ids empty for
model-level (@api.model) methods.
Parameters
env_name- str · required — The environment.
model- str · required — Technical model name (e.g.
sale.order). method- str · required — Public method name. The CRUD mutations
create,writeandunlinkare rejected here — use their dedicated tools. ids- str · default empty — Record ids prepended as the first positional argument. Empty for model-level methods.
args- str · default
"[]"— JSON array of the remaining positional arguments. kwargs- str · default
"{}"— JSON object of keyword arguments. as_user- str · default empty — Login or numeric user id to run as. Empty = admin.
context- str · default empty — JSON object added to the call context.
Use it when
- Grouping and aggregating:
method="read_group",args='[[], ["amount_total:sum"], ["partner_id"]]'. - Autocomplete lookups:
method="name_search",kwargs='{"name": "Acme"}'. - Triggering business logic:
method="action_confirm",ids="42".
Private methods are rejected
Methods with a leading underscore are refused here (Odoo 19 refuses them
server-side too). Use run_odoo_shell for those.
run_db_query¶
Execute SQL directly against the environment's PostgreSQL database.
Parameters
env_name- str · required — The environment.
query- str · required — SQL to execute (e.g.
"SELECT id, name FROM res_partner LIMIT 10"). output_format- str · default
"csv"—csv(compact, good for agents) orhuman(pretty table — use when relaying results to a person). max_rows- int · default
100— Maximum rows returned. The query itself is not modified — truncation happens on the output, and a note suggests addingLIMIT.
Use it when
- Inspecting data the ORM hides or makes awkward (
ir_model_data, raw join tables, orphan rows). - Diagnosing a migration or a broken
ir.module.modulestate. - Fast aggregate checks that would be slow through the ORM.
The ORM is usually the right layer
SQL bypasses computed fields, record rules and constraints. Prefer
odoo_search_read unless you specifically need the
raw tables.
Inside the Odoo Container¶
read_file_in_odoo¶
Read a text file, or list a directory, inside the Odoo container. A directory
path returns a listing (like ls -la); a text file returns its contents (first
100 KB by default). Binary files are not supported — use
run_odoo_command for those.
Prefer this over run_odoo_command with cat or ls.
Parameters
env_name- str · required — The environment.
path- str · required — Absolute path inside the container (e.g.
/mnt/extra-addons/my_module/__manifest__.py). read_range- str · default empty — Line range
"START:END"(e.g."1:50","100:200"). Omitted returns the whole file, up to 100 KB.
Use it when
- Reading Odoo core source to understand a method you are overriding.
- Inspecting the addon layout actually mounted at
/mnt/extra-addons/. - Checking
/etc/odoo/odoo.conf. - Verifying a file landed after
pull_and_apply.
write_file_in_odoo¶
Write a text file inside the Odoo container. Parent directories are created, existing files are overwritten, and content is transferred via container stdin so shell escaping is never an issue.
Parameters
env_name- str · required — The environment.
path- str · required — Absolute path inside the container (e.g.
/tmp/import_data.csv). content- str · required — Text content to write.
user- str · default
"odoo"— OS user to own the file. Use"root"for system paths.
Use it when
- Writing a CSV for a data import.
- Creating or amending
odoo.confsettings. - Dropping a one-off Python script for
odoo shellto execute. - Placing test fixture files (demo data, config).
Not for source code
Do not edit repository source this way. All code changes must go
through git commit → push → pull_and_apply.
search_in_odoo¶
Recursive fixed-string grep inside the Odoo container, returning matching lines with file paths and line numbers.
Parameters
env_name- str · required — The environment.
pattern- str · required — Search pattern (fixed string, case-sensitive). Regex is deliberately unsupported to avoid escaping problems.
path- str · default
"/mnt/extra-addons"— Directory to search. Use/usr/lib/python3/dist-packages/odoo/addonsto search Odoo core. glob- str · default
"*.py"— File glob. Use"*.xml"for views and data,"*.js"for frontend,"*"for everything. max_results- int · default
50— Maximum matching lines to return.
Use it when
- Finding where a field is defined across all addons.
- Locating a model class in Odoo core (
pattern="class SaleOrder"). - Finding every import of a module, or an XML record id.
run_odoo_command¶
Execute an arbitrary shell command inside the Odoo container. The command runs
through sh -c, so pipes, redirections, &&, cd x && y, $VAR and quoting
all behave as written — one call, one shell line.
Parameters
env_name- str · required — The environment.
command- str · required — The shell command (e.g.
"ls /mnt/extra-addons | head"). user- str · default
"odoo"— OS user to run as. Use"root"for privileged operations. shell- bool · default
True— Run viash -c. PassFalsefor exact argv semantics: the string is split on whitespace and executed directly, so|,>,&&,*and$VARreach the program as literal arguments.
Use it when
- Installing a Python package ad hoc to test a hypothesis.
- Inspecting processes, disk usage or file permissions inside the container.
- Running a binary tool the dedicated file tools cannot cover.
run_odoo_shell¶
Execute Python inside odoo shell with full ORM access — self.env, all
models, and the environment's database. Use print() to produce output.
Transaction handling. odoo shell rolls back its cursor when the piped
script finishes, so ORM writes would otherwise be discarded. With
auto_commit=True (the default) the transaction is committed after your code
runs, so a successful run persists; if the code raises, the commit is never
reached and the transaction is rolled back with the traceback returned.
Parameters
env_name- str · required — The environment.
python_code- str · required — Python to execute. Use
print()for output. auto_commit- bool · default
True— Commit after a successful run. SetFalsefor a read-only or dry-run inspection where nothing should persist.
Use it when
- You need a fresh registry,
sudo(), a private method, a rollback, or several steps in one transaction — none of which theodoo_*RPC tools can give you. - Testing computed fields, or debugging workflow transitions and access rights.
- Running a data-fix script.
- Inspecting without persisting (
auto_commit=False).
oduflow call run_odoo_shell '{
"env_name": "main",
"python_code": "print(self.env[\"sale.order\"].search_count([]))",
"auto_commit": false
}'
http_request_to_odoo¶
Make an HTTP request to the running Odoo instance, from the host to the container's mapped port.
Parameters
env_name- str · required — The environment.
path- str · required — URL path (e.g.
/web/health,/jsonrpc,/my/invoices). method- str · default
"GET"— One ofGET,POST,PUT,DELETE. body- str · default empty — Request body, typically JSON. Empty for GET.
headers- str · default empty — Comma-separated
KEY:VALUEpairs (e.g."Content-Type:application/json,Accept:text/html"). session_id- str · default empty — Odoo session ID for authenticated requests. Obtain one by POSTing to
/web/session/authenticate, or mint one withconnect_as_user.
Use it when
- Testing a custom web controller or REST endpoint.
- Making a JSON-RPC call.
- Verifying access rights by checking 200 vs 403.
- A quick health check (
GET /web/health).
reset_admin_password¶
Reset the admin user's password in the environment's Odoo database. The
password is hashed with passlib (pbkdf2_sha512) inside the container and
written to the res_users record where login = 'admin'.
Parameters
env_name- str · required — The environment.
new_password- str · default
"test"— The new admin password.
Use it when
- A template or production copy carries an admin password nobody knows.
- Handing a demo environment to someone who needs to log in normally.
connect_as_user¶
Mint a passwordless Odoo login session for a user and return its session_id
cookie plus a URL — the same authenticated state a password login produces,
without setting or transmitting any password.
Hand the cookie to a browser automation tool (e.g. Playwright
context.add_cookies([...]) then page.goto(url)) to land directly in an
authenticated session, skipping the login form.
Parameters
env_name- str · required — The environment.
user- str · required — The target user's login (e.g.
"jane@acme.com") or numeric id.
Use it when
- Driving end-to-end browser tests without scripting the login form.
- Exercising a feature across roles in one run — admin, sales manager, portal. Portal users are supported: they land on
/weband Odoo redirects them to their portal. - Reproducing a "works for me, not for them" permissions report.
The session id is a live credential
It is shown in the tool's output (and therefore in the transcript) — treat
it like a password. The tool grants no new privilege: whoever can call it
can already run_odoo_shell.
Translations¶
export_module_translations¶
Export a module's translation catalogue using Odoo's own exporter.
Without lang this produces the .pot template: every translatable term with
an empty translation, including the _() / _lt() messages from the module's
Python sources. With lang it produces a .po whose translations are filled
from what the database currently holds — useful for seeing what actually got
applied.
The file is written into the module's own i18n/ directory inside the
container, which is a read-write mount of the environment's checkout — so in
live-mount mode it lands directly in your working tree. The response carries a
summary plus a one-time download URL, never the file body.
Parameters
env_name- str · required — The environment.
module- str · required — A single installed module's technical name (e.g.
sale_custom). lang- str · default empty — Locale to fill translations from (e.g.
pl_PL). Omit for a.pottemplate.
Use it when
- Getting the authoritative term list before writing translations.
- Checking that
_()messages are being picked up — look at thecodecount. - Snapshotting what the database holds for one language.
translation_status¶
Report whether a module's translations actually landed, and what to do next.
It compares the term template Odoo derives from the module, the translations
stored in the database, and the committed i18n/<lang>.po files, returning a
verdict per language rather than three catalogues to reconcile. Use it
after loading translations: Odoo's importer is silent about the two ways a
.po fails, and this is what makes them visible.
- Entries with no
#:reference line import as zero translations, with no warning at all, unless a sibling<module>.potsupplies the metadata. - Entries with no
#. module:comment abort the import outright unless that sibling template supplies it.
Verdicts: OK, PARTIAL, NOT LOADED, NOT TRANSLATED,
IMPORT SILENTLY DROPPED, IMPORT ABORTS, NO FILE, NOT ACTIVATED — each
with the coverage behind it and the call that fixes it.
Parameters
env_name- str · required — The environment.
module- str · required — A single installed module's technical name.
langs- str · default empty — Comma-separated locales to check (e.g.
"pl_PL,ru_RU"). Omit to check every language activated in the database excepten_US.
Use it when
- A translation "was loaded" but the UI is still in English.
- Reviewing translation coverage before a release.
- Diagnosing a
.poimport that reported success and did nothing.
Template Management¶
Templates are reusable database + filestore snapshots that make environment creation fast. See Template Management.
save_as_template¶
Save an environment's database and filestore as a template.
By default this creates a new template and refuses to overwrite an existing
one — pick a fresh template_name. overwrite=True deliberately re-baselines
an existing template: its database and filestore are replaced, and other
environments using it with overlay-mounted filestores are remounted against the
new baseline. On re-baseline their filestore changes (the overlay upper layer)
are preserved by default; reset_env_changes=True discards them. The source
environment itself is always reset — its data just became the new template.
Parameters
env_name- str · required — The environment whose database and filestore become the template.
template_name- str · required — Template profile to publish into.
reset_env_changes- bool · default
False— Discard other environments' filestore deltas (destructive). Default preserves them. overwrite- bool · default
False— Allow re-baselining an existing template. Default refuses if it already exists.
Use it when
- A configured environment (modules installed, data set up) should become the starting point for future branches.
- Re-baselining a team template after a round of configuration work.
Requires explicit user permission
If the user has not clearly and unambiguously asked to save a specific
environment as a template, do not call this. Both overwrite=True and
reset_env_changes=True require an explicit request of their own.
save_production_as_template¶
Save a production's database and filestore as a dev template. The production keeps serving throughout — the dump is a consistent snapshot and nothing is stopped or modified on the production side.
Overwrite and reset semantics are identical to
save_as_template.
Parameters
prod_name- str · required — The production whose database and filestore are copied.
template_name- str · required — Template profile to publish into.
reset_env_changes- bool · default
False— Discard other environments' filestore deltas (destructive). overwrite- bool · default
False— Allow re-baselining an existing template.
Use it when
- Developers need to work against realistic production data.
- Refreshing the managed
prod-<name>template that backscreate_environment(from_production=...).
The template holds unsanitized production data
Real customer records, real email addresses, real API credentials.
Sanitization happens later, when an environment is created from it
(create_environment runs Odoo's neutralization
plus the repository's custom sanitize scripts by default). Treat the
template itself as production-confidential. Requires explicit user
permission. Refused when the production has MCP copy-to-dev disabled.
list_templates¶
List available template profiles (database + filestore snapshots), including the branch and commit each database snapshot was taken from.
Parameters
None.
Use it when
- Choosing a
template_nameforcreate_environment. - Checking how stale a template is before building on it.
rename_template¶
Rename a template profile — its directory and its PostgreSQL template database.
Refused if any environment was created from this template: the template reference is fixed at creation time and cannot be updated on a running environment. Delete those environments first, or leave the template as is.
Parameters
template_name- str · required — Current name.
new_name- str · required — New name.
Use it when
- A template's name no longer reflects the Odoo version or customer it holds.
delete_template¶
Permanently remove a template profile — its template database and its files on disk.
Parameters
template_name- str · required — Template profile to delete.
Use it when
- A template is genuinely obsolete and disk space must be reclaimed.
Never on your own initiative
Every environment depending on this template loses its baseline and cannot be recreated until a new template is set up. Requires explicit user permission and confirmation.
import_template¶
Import or refresh a template from an Odoo database manager, an S3 prefix,
a local directory, or a local dump file. See Templates
for the raw dump plus filestore/ layout and migration examples.
Parameters
source- str · default empty — An http(s) Odoo URL,
s3://bucket/prefix, or an absolute local path. Omit withrefresh=True. master_pwd- str · default empty — Required only for the Odoo database-manager source.
db_name- str · default empty — Odoo database to back up. Empty auto-detects, and fails if several databases exist.
template_name- str · default
"default"— Template profile to create or update. without_filestore- bool · default
False— Import only the dump. Existing attachments are preserved on overwrite; a single local dump file also preserves them. overwrite- bool · default
False— S3/local only: incrementally replace template data. Unchanged dumps skip restore; deleted source attachments are removed, including when the source tree becomes empty. Requires explicit permission. refresh- bool · default
False— With no source, restore from the template's own files and refresh metadata and overlays. Requires explicit permission. s3_endpoint,s3_access_key,s3_secret_key,s3_region- str · default empty — S3 source connection settings. Credentials fall back to matching
[backup]settings, then anonymous access. Supply access and secret keys together.
Use it when
- Onboarding a customer whose Odoo runs elsewhere.
- Importing a raw backup without building an archive.
- Periodically synchronizing a backup into a development template.
refresh_template¶
Re-apply a template's current filestore to live overlay environments: unmount and remount every overlay-mounted environment using this template against the template's current on-disk filestore.
By default each environment's filestore changes (the overlay upper layer) are preserved — non-destructive.
Parameters
template_name- str · required — Template profile to re-apply.
reset_env_changes- bool · default
False— Discard environments' filestore deltas and reset every affected environment to the template baseline (destructive).
Use it when
- The template filestore was changed on disk and live environments should see it.
- Re-syncing an environment that was busy and got skipped during an import or save.
Requires explicit user permission
Especially with reset_env_changes=True.
attach_filestore¶
Attach or replace a template's filestore from a directory, an archive, or a remote rsync source.
Archive and directory sources are normalized to the Odoo filestore layout
(XX/<sha1>). Live environments' changes are preserved by default.
Parameters
template_name- str · required — Template profile to attach the filestore to.
source- str · required — A local directory, a local
.zip/.tar/.tar.gzarchive, anrsync://URL, or an SSH-style rsync source such asuser@host:/path. reset_env_changes- bool · default
False— Discard environments' filestore deltas (destructive). strip_prefix- str · default
"auto"— Wrapper directory to strip."auto"detects one such as the database name; pass an explicit prefix when auto-detection is ambiguous.
Use it when
- A database-only import (
import_templatewithwithout_filestore=True) needs its attachments. - The filestore arrives separately, e.g. rsynced from the customer's server.
Auxiliary Services¶
Managed side-car containers — Redis, Meilisearch, MinIO, anything your stack needs. See Auxiliary Services.
create_service¶
Create a managed auxiliary service container.
A service has exactly one exposure model: a catch-all port, or a
restricted Traefik routes allowlist. The two are mutually exclusive, and
port remains required outside Traefik mode.
Parameters
name- str · required — Short service name (e.g.
redis,meilisearch). image- str · required — Docker image with tag (e.g.
redis:7,getmeili/meilisearch:v1.6). A staging tag fromstart_image_build(oduflow-build/team-<id>:<build-id>) is taken from the local Docker daemon without a pull — see Container Image Builds. port- int · default
0— Catch-all exposure: forward every path to this one container port. Required outside Traefik. Mutually exclusive withroutes. routes- list · default none — Traefik exposure allowlist. Each object has
path, a backendport, and optionalstrip_prefix. Unlisted paths return Traefik 404. Mutually exclusive withport. hostname- str · default empty — Custom hostname for Traefik routing (Traefik mode only).
env_vars- str · default empty — Comma- or newline-separated
KEY=VALUEpairs. Commas inside values are preserved unless what follows looks like anotherKEY=— so"CONNECT_MCP_TOOL_GROUPS=write,collaboration,documents"is one variable; put one pair per line when in doubt. A valuesecret:<name>references a team secret. host_mode- bool · default
False— Run in host network mode instead of the shared Docker network, for services needing direct host network access. Traefik routing still works. volumes- str · default empty — Comma-separated mounts, each
volume_name:/container/path[:ro|rw]. Volumes must exist first (create_volume). privileged- bool · default
False— Full host access; implies all Linux capabilities. Mutually exclusive withnet_admin. net_admin- bool · default
False— Add theNET_ADMINcapability — required for VPN/WireGuard, tun/tap devices and iptables inside the container. command- str · default empty — Start command overriding the image
CMD, as a shell-quoted string (e.g."server /data --console-address :9001"). The imageENTRYPOINTis not affected. runtime- dict · default none — Explicit Docker
tmpfs, private cgroupns,stop_signalandstop_timeoutsettings.
Use it when
- Odoo needs a cache, search engine, object store or message broker alongside it.
- You want a scratch container on the team network for an experiment.
Reserved mount in Traefik TLS mode
The system ACME volume is mounted automatically at /etc/traefik:ro. Do
not include it in volumes — /etc/traefik is reserved.
oduflow call create_service '{
"name": "redis",
"image": "redis:7",
"port": 6379,
"volumes": "redis-data:/data"
}'
update_service¶
Preflight the configuration, pull the latest image and optionally change any setting. The container is recreated when the image or a setting changes; settings that are not overridden are preserved. This is the preferred way to change a service — no manual delete-and-recreate.
Three parameters are tri-state: omitted keeps the current value, a value fully replaces it, and an empty value clears it.
Parameters
name- str · required — The service to update.
env_vars- str · default empty —
KEY=VALUEpairs that fully replace existing variables. Empty keeps them. image- str · default empty — New image with tag (e.g.
redis:8). Empty keeps the current image. A staging tag fromstart_image_build(oduflow-build/team-<id>:<build-id>) is taken from the local Docker daemon without a pull — see Container Image Builds. port- int · default
0— New container port.0keeps the current one. hostname- str · default empty — New Traefik hostname. Empty keeps the current one.
host_mode- bool · default none — Host network mode. Unset keeps the current mode.
volumes- str · default none — Mounts that fully replace existing user volumes. Unset keeps them; an empty string unmounts every volume (the volumes keep their data). The implicit Traefik TLS mount at
/etc/traefik:rois preserved separately. privileged- bool · default none — Privileged mode. Unset keeps the current setting. Mutually exclusive with
net_admin. net_admin- bool · default none — Add (
true) or remove (false) theNET_ADMINcapability. Unset keeps current capabilities. routes- list · default none — Full replacement route list. Unset preserves it. Pass
[]together withportto return to a single catch-all port. command- str · default none — New start command as a shell-quoted string. Unset keeps the current command; an empty string drops the override and falls back to the image
CMD. Note this differs fromenv_vars/image, where empty means "keep". runtime- dict · default none — Replace lifecycle settings; omit to preserve, pass
{}to clear.
Use it when
- Pulling a new image tag for a running service.
- Rotating a service's credentials or pointing it at a new database.
- Recreating a legacy service so it picks up newly implicit system mounts.
Read before you write
Call get_service_info first. volumes and
env_vars are full replacements, so a partial argument silently drops
what you left out. Protected services refuse updates until an
administrator unprotects them in the dashboard.
delete_service¶
Stop and remove a service container, keeping its preset so
restore_service can bring it back.
Parameters
name- str · required — The service to delete.
save_preset- bool · default
True— Keep the saved configuration. Passfalseto delete the preset along with the container.
Use it when
- Freeing resources while keeping the ability to restore the exact configuration.
- Retiring a service for good (
save_preset=false).
Protected services
A protected service refuses to be deleted until an administrator unprotects it in the dashboard.
restart_service¶
Restart a managed service container.
Parameters
name- str · required — The service to restart (e.g.
redis,meilisearch).
Use it when
- The service is wedged, or picked up a configuration file you rewrote in its volume.
list_services¶
List all managed service containers.
Parameters
None.
Use it when
- Taking stock of what is running alongside your environments.
get_service_info¶
Full live state of one service: image with digest, runtime status, port and
routes, hostname, URL, host_mode, start command, volumes, environment
variables, capabilities, privileged flag, restart count, started_at, and
whether a saved preset exists.
In Traefik TLS mode this also reports the implicit /etc/traefik:ro ACME mount,
which is not stored in the preset.
Parameters
name- str · required — The service to inspect (e.g.
redis,fs).
Use it when
- Before
update_service— so full-replacement arguments preserve what you are not changing. - Confirming which image digest is actually running.
- Debugging routing: catch-all port vs. route allowlist.
get_service_logs¶
Retrieve recent logs from a managed service container.
Parameters
name- str · required — The service.
n_lines- int · default
100— Number of recent log lines.
Use it when
- A service starts and immediately exits.
- Checking whether a service accepted its configuration.
run_service_command¶
Execute a shell command inside a service container. The command runs through
sh -c, so pipes, redirections and && work as written.
Parameters
name- str · required — The service (e.g.
redis,meilisearch). command- str · required — The shell command (e.g.
"redis-cli ping","ls /data | wc -l"). user- str · default
"root"— OS user to run as. shell- bool · default
True— Run viash -c. PassFalsefor exact argv semantics, or when the image ships no shell at all (scratch/distroless).
Use it when
- Probing the service with its own CLI (
redis-cli,mc,psql). - Verifying a mounted volume actually contains what you expect.
Service PostgreSQL Databases¶
Persistent, team-scoped databases for auxiliary services — separate from Odoo's own databases and from the environment lifecycle.
create_service_database¶
Create a persistent PostgreSQL database with a dedicated non-superuser
owner. It belongs to the current team, survives service updates and deletion,
and is reachable from bridge-mode team services at the returned host and port.
Returns DATABASE_URL and the individual PG* credentials.
Parameters
name- str · required — Stable lowercase resource name using letters, digits,
-or_. cluster- str · default
"dev"—dev(the shared development cluster) orprod(the dedicated production cluster; requires production hosting). Databases onprodare covered by the cluster-wide WAL-G backups and are not counted against the development disk quota.
Use it when
- A service (n8n, Keycloak, a custom app) needs durable storage that outlives its container.
- You want backup coverage for a non-Odoo database (
cluster="prod").
list_service_databases¶
List managed database names, live status, size and connection count — without passwords.
Parameters
None.
Use it when
- Auditing what the team has provisioned and how much space it uses.
- Checking whether anything is still connected before a deletion.
get_service_database¶
Explicitly reveal the connection credentials for one managed database.
Parameters
name- str · required — The database.
Use it when
- Wiring the credentials into a service's
env_vars. - Recovering a
DATABASE_URLnobody wrote down.
The response contains a plaintext password
Treat it as a secret, and pass only the variables the target service actually needs. Consider storing it as a team secret instead of inlining it.
rotate_service_database_password¶
Rotate the owner password and return replacement credentials.
Parameters
name- str · required — The database.
Use it when
- A credential leaked, or appeared somewhere it should not have.
- Routine rotation before handing a project over.
Containers keep the old value
Existing containers keep the old password until their environment
variables are updated and the containers are recreated or restarted —
see update_service.
delete_service_database¶
Permanently drop the database and its login role, terminating active PostgreSQL connections first. Service containers are not modified and will fail to reconnect until reconfigured.
Parameters
name- str · required — The database to drop.
Use it when
- The owning service is gone for good and the data is genuinely disposable.
Protected databases
A protected database cannot be deleted until an administrator unprotects it in the dashboard.
Volumes¶
Named Docker volumes for use with services. See Auxiliary Services.
create_volume¶
Create a named Docker volume.
Parameters
name- str · required — Short volume name (e.g.
redis-data,meilisearch-data). description- str · default empty — What this volume is for.
Use it when
- A service needs durable storage. Volumes must exist before they can be mounted by
create_service.
list_volumes¶
List all managed Docker volumes and which services use them.
Parameters
None.
Use it when
- Finding orphaned volumes to reclaim.
- Checking what a volume is attached to before deleting it.
inspect_volume¶
Detailed information about one volume, including which services use it.
Parameters
name- str · required — The volume to inspect.
Use it when
- Confirming a volume is unused before
delete_volume.
delete_volume¶
Delete a managed Docker volume. Fails if any service still uses it.
Parameters
name- str · required — The volume to delete.
Use it when
- A service was retired and its data is no longer needed.
read_file_in_volume¶
Read a text file, or list a directory, inside a Docker volume. A temporary
helper container is spun up to access the contents. Directories return an
ls -la-style listing; text files return contents up to 100 KB. Binary files
are detected and rejected.
Parameters
name- str · required — The volume (e.g.
redis-data). path- str · required — Path inside the volume (e.g.
data/dump.rdb,config/redis.conf). A leading/is optional — paths are relative to the volume root. read_range- str · default empty — Line range
"START:END"(e.g."1:50"). Omitted returns the full file, up to 100 KB.
Use it when
- Checking a service's configuration file without starting the service.
- Confirming data landed in the volume after an import.
write_file_in_volume¶
Write a text file inside a Docker volume, creating parent directories and overwriting an existing file.
Parameters
name- str · required — The volume.
path- str · required — Path inside the volume (e.g.
config/my.conf). Leading/optional. content- str · required — Text content to write.
Use it when
- Seeding a service's configuration before its first start.
- Fixing a config that keeps the service from booting (then
restart_service).
search_in_volume¶
Recursive fixed-string grep inside a Docker volume, returning matching lines with paths and line numbers.
Parameters
name- str · required — The volume.
pattern- str · required — Search pattern (fixed string, case-sensitive).
path- str · default empty — Directory relative to the volume root. Default searches the entire volume.
glob- str · default
"*"— File glob (e.g."*.conf","*.xml"). max_results- int · default
50— Maximum matching lines.
Use it when
- Locating which config file in a volume carries a setting.
- Finding a stale hostname or credential across a service's data.
delete_file_in_volume¶
Delete a file or directory inside a Docker volume. Cannot delete the volume
root — use delete_volume for that.
Parameters
name- str · required — The volume.
path- str · required — Path inside the volume to delete (e.g.
data/old-dump.rdb). Leading/optional.
Use it when
- Clearing a corrupt cache or an outdated dump so the service rebuilds it.
Service Presets¶
A preset is a service's saved configuration. delete_service
keeps one by default, so a service can be brought back exactly as it was.
list_service_presets¶
List saved service presets.
Parameters
None.
Use it when
- Checking what can be restored after a cleanup.
restore_service¶
Recreate a service container from its saved preset, with the same configuration.
Parameters
name- str · required — The saved preset to restore.
Use it when
- Bringing back a service deleted to free resources.
- Rebuilding a service stack on a fresh host.
delete_service_preset¶
Remove a saved service preset.
Parameters
name- str · required — The preset to delete.
Use it when
- A service is retired permanently and its configuration should not linger.
Secrets¶
list_secrets¶
List the names of the team's named secrets. Values are write-only: a human sets them in the Oduflow dashboard, and they can never be read back through MCP.
Reference a secret in any env_vars argument —
create_environment,
update_environment,
create_service,
update_service — as KEY=secret:<name>. The real value is
substituted only inside the container, while every stored or displayed
configuration keeps the reference.
Parameters
None.
Use it when
- Finding out which secret names exist before wiring one into a container.
- Keeping an API key out of tool arguments, transcripts and stored configuration.
Container Image Builds¶
Requires a [team.X.image_registry] section in oduflow.toml.
A succeeded build is kept in the host's Docker daemon under a staging tag,
oduflow-build/team-<id>:<build-id> (reported by
get_image_build). That tag can be passed directly as the
image of create_service or
update_service: it is resolved from the local daemon, not
pulled from a registry, so a build can be run and checked as an auxiliary
service before publish_image_build pushes it
anywhere. These service operations accept only the team's own staging images.
Automatic build retention preserves tags referenced by running or stopped
containers. Unused staging tags remain temporary and can be pruned; use a
published tag to restore a service after pruning or move it to a new host.
start_image_build¶
Build a container image from the environment checkout's current HEAD commit
— sealed with git archive under the environment lock, so the source cannot
shift mid-build. The build runs asynchronously server-side and this call
returns a build_id immediately. Hard timeouts, log-size caps and per-team
concurrency limits apply.
Parameters
env_name- str · required — The environment whose checkout to build from.
dockerfile- str · default
"Dockerfile"— Dockerfile path relative to the context. context- str · default
"."— Build context directory relative to the repository root. target- str · default empty — Multi-stage build target.
build_args- str · default empty — Comma-separated
KEY=VALUEDocker build arguments.
Use it when
- Producing a deployable image from the exact code you just tested.
- Building a release candidate from a tagged commit.
Build arguments are not secret
Their values reach the Dockerfile and the image history. Never pass
credentials. Push your commits and pull_and_apply
first — the build uses the checkout's HEAD at call time.
get_image_build¶
Status, source commit, publication history and a build log tail for one build.
Parameters
env_name- str · required — The environment the build belongs to.
build_id- str · required — The build to inspect.
tail_lines- int · default
100— Trailing build log lines to include.
Use it when
- Polling an asynchronous build to completion.
- Reading the failing Dockerfile step.
publish_image_build¶
Push a succeeded build's exact image — never a rebuild — to one or more tags under the team's configured registry namespace.
Any syntactically valid tag is accepted, including latest and semver.
Overwriting an existing tag is intentional and last-writer-wins. Tags are
pushed one by one, so partial success is possible and each tag reports its own
outcome.
Parameters
env_name- str · required — The environment the build belongs to.
build_id- str · required — A build in status
succeeded. repository- str · required — Destination repository below the configured prefix (e.g.
"app"). tags- str · required — Comma-separated tags to publish, e.g.
"1.4.0,latest".
Use it when
- Promoting a verified build to
latestand a version tag in one call. - Publishing the identical bits you tested, with no risk of a rebuild drifting.
cancel_image_build¶
Terminate a running build and its Docker connection — even when the current
Dockerfile step produces no output — and move the job to cancelled.
Parameters
env_name- str · required — The environment the build belongs to.
build_id- str · required — The build to cancel.
Use it when
- A build is hung on a silent step and is holding team build concurrency.
- You started a build from the wrong commit.
Repository Auth¶
setup_repo_auth¶
Cache git credentials for a private git host. The token is stored in the team's
git credential store and verified. Git matches credentials by host (and
username), so one entry covers every repository on that host; afterwards
create_environment and
add_extra_repo can clone with a plain https:// URL.
Access is verified with git ls-remote against repo_url when one is given,
otherwise against the provider's API (GitHub, GitLab, Bitbucket).
Parameters
repo_url- str · default empty — Repository HTTPS URL, used to derive the host and to verify access.
token- str · default empty — Personal access token / app password. Preferred form — pass the token here rather than inline in the URL.
username- str · default empty — Account name stored with the token. Optional for GitHub, GitLab and Azure DevOps (defaults to
x-access-token); required for Bitbucket app passwords. Use distinct usernames to keep several tokens for the same host. host- str · default empty — Git host such as
github.comorgit.example.com:8443. Only needed whenrepo_urlis omitted.
Use it when
- Onboarding a private repository for the first time.
- Replacing an expired token.
Legacy form
A repo_url with inline credentials
(https://user:PAT@github.com/owner/repo.git) and no token is still
accepted, but the explicit token form is preferred.
oduflow call setup_repo_auth '{
"repo_url": "https://github.com/owner/repo.git",
"token": "ghp_..."
}'
get_ssh_public_key¶
Return the team's SSH public key. Oduflow maintains one SSH deploy key per team,
generated automatically at server start. Register it with your git hosting — as
a repository deploy key (read access is enough) or on a machine-user account —
and SSH repository URLs (git@github.com:owner/repo.git) work in
create_environment,
add_extra_repo and productions without a token.
Parameters
None.
Use it when
- You prefer deploy keys over tokens, or the host mandates them.
- Setting up access to a self-hosted git server.
One repository per GitHub deploy key
GitHub allows a given deploy key on only one repository. To reach several repositories with the same key, attach it to a machine-user account instead.
Extra Addons¶
Shared addon repositories — Odoo Enterprise, OCA, your own theme repo — cloned once and mounted into environments. See Extra Addons Repositories.
add_extra_repo¶
Register an extra addons repository. Registration checks access and reads the remote branch list; no code is downloaded. The first environment that uses a branch downloads only that branch's latest commit (no history), so a large multi-version repository costs only the versions in use.
Parameters
name- str · required — Short name for the repo (e.g.
enterprise,custom-themes). repo_url- str · required — HTTPS (
https://github.com/owner/repo.git) or SSH (git@github.com:owner/repo.git, needs the team deploy key — seeget_ssh_public_key). branches- str · default empty — Comma-separated branch names to download now instead of on first use. Empty downloads nothing yet. The dashboard provides a remote branch picker; REST accepts a list.
Use it when
- Making Odoo Enterprise available to environments.
- Sharing an OCA collection or an internal theme repo across the team.
list_extra_repos¶
List extra addons repositories with their downloaded branches and the branch list last read from the remote.
Parameters
None.
Use it when
- Finding the exact name and branch to use in an
extra_addonsargument.
update_extra_repo¶
Refresh the remote branch list and fetch the latest changes of every downloaded branch, pruning branches deleted on the remote. Branches never used stay undownloaded (repositories added by older Oduflow versions still fetch all branches).
Parameters
name- str · required — The extra repo to update (e.g.
enterprise). add_branch- str or list of str · default empty — A branch, or a list of branches, to download now and keep updated (e.g.
17.0or["17.0", "18.0"]), instead of waiting for their first use. A branch missing on the remote fails the call before anything is downloaded; a failed fetch leaves the tracked set unchanged.
Use it when
- Warming up a branch before the first environment needs it.
- An environment needs a fix that landed in the shared addons repo.
delete_extra_repo¶
Delete an extra addons repository.
Parameters
name- str · required — The extra repo to delete.
Use it when
- A shared repo is no longer used by any environment.
Production Hosting¶
Long-lived Odoo instances with their own domain, on a dedicated production
PostgreSQL cluster. Every tool in this section and the two that follow requires
[production].enabled = true. Read Production Hosting for the
workflow and the disaster-recovery consequences.
create_production¶
Provision a production Odoo environment: long-lived, its own domain, the
dedicated production PostgreSQL cluster, auto-tuned workers, and no
sanitization. Requires routing_mode = "traefik".
Productions are rarely created and rarely deleted — they live on and get
updated with update_production.
Parameters
name- str · required — Production name, e.g.
erp(lowercase letters, digits, dashes). repo_url- str · default empty — HTTPS git repository URL. Required unless
from_environmentsupplies it. branch- str · default empty — Git branch to deploy (full history is kept). Required unless
from_environmentsupplies it. domain- str · default empty — The public domain; DNS must point at this server, TLS via Let's Encrypt. In a team with
base_domainconfigured it must be the zone apex or a subdomain of it (e.g.erp.demo.example.com). Empty defaults to the apex for the team's first production and<name>.<base_domain>afterwards. Client-owned domains go inextra_domains. extra_domains- list · default none — Additional public FQDNs routed to the same production (e.g. the client's own
erp.customer.com). Each gets its own Let's Encrypt certificate; DNS must point here. odoo_image- str · default empty — Docker image, e.g.
odoo:18.0. Required unlessfrom_environmentsupplies it. git_user- str · default empty — Git username for credential matching.
extra_addons- dict · default none — Extra addon repos as
{repo_name: branch}. auto_update- bool · default
False— Deploy automatically on GitHub push webhooks. allow_copy_to_dev_mcp- bool · default
True— Allow MCP/agent-initiated copies of this production's data into dev (save_production_as_templateand the firstcreate_environment(from_production=...)). WhenFalse, those tools refuse to publish a new copy; an already published template stays usable, but only withsanitize=True. The dashboard UI is never gated, and no MCP tool can change this flag afterwards — an administrator toggles it in the dashboard. template_name- str · default empty — Template to seed the database and filestore from (e.g. an import of the customer's existing production). Empty starts a fresh database (
odoo -i base). Mutually exclusive withfrom_environment. from_environment- str · default empty — Dev environment to promote: its database and filestore are copied (Odoo briefly stopped for a consistent copy, then restarted — the environment is not reset), and empty
repo_url/branch/odoo_image/git_user/extra_addonsdefault to the environment's own. No sanitization — the data goes into production. env_vars- dict · default none — User environment variables; values may be
secret:<name>references. Omit to inherit the source environment's variables; pass{}to inherit none. ManagedHOST/PORT/USER/PASSWORDcannot be overridden. References survive reconfiguration. server_mode- str · default
workers— How Odoo serves HTTP.workers(sync): worker processes on port 8069 serve the pages and Traefik sends only the live bus (/websocket,/longpolling) to the gevent port 8072.gevent(async): Traefik sends all traffic to the single gevent process on 8072 — suits many long-lived or I/O-bound requests, but one CPU-heavy request slows everyone. Crons run in both modes. See Server mode.
Use it when
- Going live with a customer after development settles.
- Migrating a customer's existing Odoo onto Oduflow (
template_namefrom an import). - Promoting a validated dev environment straight into production (
from_environment).
list_productions¶
List the team's productions with status, domain, deployed commit, auto-update state and last deploy result.
Parameters
None.
Use it when
- A quick overview of what is live and whether anything is behind.
get_production_info¶
Detailed information about one production: status, health, deployed commit,
recent branch commits, deploy history, current odoo.conf overrides, and
backup state.
Parameters
name- str · required — The production name.
Use it when
- Checking what is deployed versus what is on the branch.
- Confirming backup coverage and health before a risky change.
- Reviewing which
odoo.confoverrides are in force.
production_logs¶
Read a production's Odoo container logs.
Parameters
name- str · required — The production name.
n_lines- int · default
100— Number of log lines to return. grep- str · default empty — Case-insensitive substring filter.
level- str · default empty — Log level filter (e.g.
ERROR,WARNING).
Use it when
- Investigating a customer-reported error at a known time.
- Watching for errors after a deploy.
start_production¶
Start a stopped production.
Parameters
name- str · required — The production name.
Use it when
- Bringing a production back online after maintenance.
- Restarting applications after a WAL disk-protection recovery — see
control_production_wal.
stop_production¶
Stop a production.
Parameters
name- str · required — The production name.
Use it when
- A planned maintenance window requires the application down.
- Something is actively causing damage and must be halted.
restart_production¶
Restart a production's Odoo container — brief downtime. A container whose Traefik routing is outdated is recreated instead (same downtime).
Parameters
name- str · required — The production name.
Use it when
- Odoo is wedged or leaking, and a clean process is the fastest remedy.
- A configuration change needs to be picked up.
reconfigure_production¶
Change a production's infrastructure settings and recreate its container to match. Omitted or empty arguments are left unchanged. The database and filestore are preserved; expect brief downtime while the container is replaced.
Changeable: the public domain (Traefik host rule + Let's Encrypt), the extra domains, the Odoo image, the deployed branch or repository URL, the git credential user, the extra addon repos, the user environment variables, and the server mode. A call that changes nothing still recreates a container whose state drifted from the record (missing container or checkout, outdated Traefik routing, or a team secret whose value changed since the container was created).
Parameters
name- str · required — The production name.
domain- str · default empty — New public domain. DNS must point at this server. With
base_domainconfigured it must be the zone apex or a subdomain of it; client-owned domains go inextra_domains. extra_domains- list · default none — New full set of additional FQDNs. Pass
[]to remove all; omit to leave unchanged. odoo_image- str · default empty — New Docker image, e.g.
odoo:19.0. branch- str · default empty — New git branch to deploy.
repo_url- str · default empty — New git repository URL (HTTPS or SSH).
git_user- str · default none — New git username for credential matching. Pass
""to clear it; omit to leave unchanged. extra_addons- dict · default none — New full set of extra addon repos
{repo_name: branch}. Pass{}to remove all; omit to leave unchanged. env_vars- dict · default none — Full replacement user environment variables, including
secret:<name>references. Omit to preserve;{}clears them. server_mode- str · default empty —
workers(sync: pages on 8069, bus on 8072) orgevent(async: everything on 8072). Re-tunes theodoo.confworkers and re-points Traefik. Omit to leave unchanged. recreate- bool · default false — Recreate the container even when no setting, secret value or runtime state differs from the record.
Use it when
- A team secret used by the production got a new value: call it with just the
name. Secret values reach the container only when it is created, so
restart_productionkeeps the old value; this call detects the changed value, recreates the container and lists the affected variables (names only). - A customer's domain changes, or they bring their own.
- Moving production onto a release branch.
- Adding an addons repository production now depends on.
Changing the image does not migrate the database
A major Odoo version bump additionally needs an explicit module upgrade
plan. After a branch or repository change, run
update_production with install= / upgrade= if
the new code needs module changes.
set_production_odoo_conf¶
Set or remove odoo.conf [options] overrides for a production and re-apply
the configuration. Overrides are stored per production, win over the
auto-tuned worker settings, and survive deploys and retunes. Current
overrides are shown by get_production_info.
Parameters
name- str · required — The production name.
options- dict · default none — Options to set, e.g.
{"limit_time_real": "300"}. unset- str · default empty — Comma-separated option names to remove, reverting them to the managed or base value.
restart- bool · default
True— Restart the container so Odoo picks the change up (brief downtime).
Use it when
- A long-running report needs a higher
limit_time_real. - The auto-tuned worker count does not suit this workload.
Managed keys are refused
addons_path, data_dir and the db_* keys are managed by Oduflow and
cannot be overridden.
delete_production¶
Delete a production. The container and registry record are removed; the
database and workspace (filestore, repository, deploy history) are kept
unless drop_database=true.
Kept leftovers are tombstoned: the reaper purges them [lifecycle]
prod_purge_hours after deletion (0 = keep forever, the default), and
oduflow cleanup --purge-deleted-productions --force purges them immediately.
Re-creating a production with the same name revives the leftovers'
tombstone-free state — the kept database itself must still be dealt with
explicitly.
Parameters
name- str · required — The production name.
confirm- str · required in practice — Must equal the production name (safety check).
drop_database- bool · default
False— Also drop the database and delete the workspace.
Use it when
- A customer engagement ended and the hosting is being wound down.
- A production was created by mistake and nothing depends on it.
Production Deployment¶
update_production¶
Deploy the latest commits of a production's branch — with automatic code rollback on failure.
It pulls the branch (and extra-addon worktrees), decides or applies the Odoo action, then verifies the deploy (module exit codes plus a health check). If the deploy fails, the checkout is reset to the previous commit, the config is re-applied and the container restarted.
Drive it like pull_and_apply: explicit (pass
install / upgrade / restart=True) or auto (all empty — changed files
are classified automatically). Note that in production a "refresh"-class change
(XML/JS) still restarts the container, because there is no --dev=xml in
production.
Parameters
name- str · required — The production name.
install- str · default empty — Comma-separated modules to install (
-i). upgrade- str · default empty — Comma-separated modules to upgrade (
-u). restart- bool · default
False— Restart the container (for Python-only changes).
Use it when
- Shipping a release to a customer.
- Applying a hotfix you have already validated in a dev environment.
The database is never rolled back automatically
Code rollback is automatic; data is not. If module upgrades left the
database inconsistent, restore a snapshot manually — take
snapshot_production before a risky deploy.
rollback_production¶
Manually roll a production's code back to a previous commit and restart.
Parameters
name- str · required — The production name.
to_commit- str · default empty — Target commit sha, or any git ref present in the checkout. Empty rolls back to the previous deploy's starting commit.
Use it when
- A deploy succeeded technically but the change is wrong in production.
- Reverting to a known-good commit while you investigate.
Code only
The database is not touched. For a data rollback, restore a snapshot with
restore_production.
set_production_auto_update¶
Enable or disable automatic deployment from GitHub push webhooks. When enabled,
a push to the production's branch triggers
update_production in the background, with automatic
code rollback on failure.
Parameters
name- str · required — The production name.
enabled- bool · required —
Trueto deploy automatically on push.
Use it when
- A mature project should ship continuously from a protected branch.
- Freezing deploys during a change window (
enabled=false).
production_deploys¶
Deploy history, newest last: commits, actions, modules, status
(success / rolled_back / rollback_failed / skipped) and errors.
Parameters
name- str · required — The production name.
limit- int · default
20— Maximum number of records.
Use it when
- Correlating "it broke on Tuesday" with what was deployed.
- Finding the commit to pass to
rollback_production. - Auditing whether an auto-update deploy silently rolled back.
Production Backup & Recovery¶
Snapshots are the per-production restore unit; WAL-G covers the whole cluster.
Both require a [backup] section in oduflow.toml.
snapshot_production¶
Take a snapshot of a production to S3: a database dump, a deduplicated filestore revision, and a manifest recording the deployed commit sha.
Parameters
name- str · required — The production name.
note- str · default empty — Free-form note stored in the manifest.
Use it when
- Before any risky deploy, module upgrade or data migration.
- Capturing a known-good state you may want to return to.
list_production_snapshots¶
List a production's snapshots, oldest first: id, created_at, sizes and commit
sha.
Parameters
name- str · required — The production name.
refresh- bool · default
False— Re-list S3 (the source of truth) instead of using the local cache.
Use it when
- Picking a
snapshot_idforrestore_production. - Verifying that scheduled snapshots are actually landing (
refresh=True).
restore_production¶
Restore a production's database and filestore from a snapshot, or replace them with a dev environment's data (promotion into an existing production).
The restore is swap-based, so a failed restore leaves the previous state in place. The code checkout is not touched — a warning is returned if it does not match the source's commit.
Parameters
name- str · required — The production name.
snapshot_id- str · default empty — Snapshot to restore (see
list_production_snapshots). Mutually exclusive withfrom_environment. from_environment- str · default empty — Dev environment whose database and filestore replace this production's. The environment's Odoo is briefly stopped for a consistent copy, then restarted — the environment itself is not reset. No sanitization — the data goes into production.
confirm- str · required in practice — Must equal the production name (safety check).
Use it when
- A bad migration or data loss needs the last good snapshot back.
- Promoting a rebuilt dataset from dev into an existing production.
Take a snapshot first
This replaces the production's current data. If that data may still be
needed, call snapshot_production before
restoring.
set_production_backup_schedule¶
Override a production's daily snapshot time.
Parameters
name- str · required — The production name.
schedule- str · required —
"HH:MM"in server-local time, or"off"to disable scheduled snapshots for this production. Unset (the default) follows[backup] snapshot_time.
Use it when
- A customer's quiet hours differ from the team default.
- Staggering snapshots so several productions do not back up at once.
prune_production_backups¶
Apply the retention policy ([backup] keep) to the team's snapshots and
filestore chunk store immediately. This also runs weekly on schedule.
Pruning uses safe two-step fossil collection: chunks are only permanently deleted on a later prune, after every production has produced a newer revision.
Parameters
None.
Use it when
- S3 costs need reining in before the weekly run.
- You just lowered
keepand want it applied now.
production_backup_status¶
Backup posture for the team: per-production snapshot state (schedule, last snapshot, last error) and cluster WAL-G state (base backups, WAL archiver health, S3 reachability).
Parameters
None.
Use it when
- The weekly "are we actually backed up?" check.
- Diagnosing why a scheduled snapshot did not appear.
production_wal_status¶
Cached shared-cluster WAL queue, upload progress, disk reserve, stale-data and protection state.
Parameters
None.
Use it when
- WAL archiving is falling behind and the PostgreSQL volume is filling up.
- Confirming the cluster has left disk-protection mode.
control_production_wal¶
Control the shared production cluster's WAL handling. Affects all teams on this server. Unarchived WAL is never discarded.
Parameters
action- str · required — One of
pause(retain WAL),resume,retry(interrupt onlywal-push),recover(start PostgreSQL only, under disk protection),release(clear protection after checks; applications remain stopped). confirm- str · required in practice — Must equal
ALL-PRODUCTIONS.
Use it when
- S3 is unreachable and WAL uploads must be paused deliberately.
- Recovering a cluster that hit the disk reserve and stopped.
Recovery is deliberately partial
recover starts PostgreSQL only; release clears protection but leaves
applications stopped. Bring each production back with
start_production once you are satisfied the cluster
is healthy.
restore_cluster_pitr¶
Disaster recovery. Restore the whole production PostgreSQL cluster from
WAL-G — base backup plus WAL replay. This affects every production database
at once; to restore a single production use
restore_production.
This is also the "resurrect production elsewhere" path: a fresh Oduflow server
with the same [backup] section can rebuild the cluster from S3.
The current data directory is displaced inside the volume, not destroyed. Production Odoo containers are stopped and restarted.
Parameters
target_time- str · default empty — PITR target, e.g.
"2026-07-10 12:00:00+00". Empty replays the whole archive to the latest state. confirm- str · required in practice — Must equal
RESTORE-CLUSTER.
Use it when
- The cluster is lost or corrupted at the storage layer.
- Rebuilding production on new hardware from S3 alone.
- Rewinding every database to a point in time before a catastrophic change.
Production Odoo API¶
Read and change production Odoo records through OduMCP, the connector addon
Oduflow installs into the production itself. Reads are policy-bounded and
changes go through an approval plan that a human approves in Odoo, so no
arbitrary ORM call ever reaches a live database. Every tool here requires
[production].enabled = true and — over HTTP — the /production endpoint with
the team's production_token; see
Production access and rotation.
sync_production_mcp¶
Install or upgrade the odumcp addon on a production and synchronize the
team's configured key with Odoo. An empty name processes every production of
the team and reports each one separately, so a single failure does not hide the
rest.
New productions are provisioned automatically; this tool is for existing ones,
for retrying a failed setup, and for rotating the key after production_token
changes in oduflow.toml (change the value, restart Oduflow, then run this).
No secret is accepted or returned. Stopped productions must be started first,
and adding the managed addon mount recreates the container.
Parameters
name- str · default empty — One production, or empty for every production of the team.
Use it when
- Adopting a production that predates automatic provisioning.
- The connector reports itself unavailable after a failed setup.
- Rotating
production_token.
production_odoo_info¶
Odoo identity, profile and the capabilities the deployed policy actually enables — the cheapest way to confirm the connector is reachable and what it will allow.
Parameters
name- str · required — Production name.
Use it when
- Verifying a fresh install or a rotated key.
- Discovering which operations the production's policy permits before planning work.
production_odoo_read¶
Policy-governed reads: models.list, models.describe, records.search,
records.read, records.count, records.aggregate, attachments.read and
reports.render. Parameters follow the OduMCP API (model, domain,
fields, ids, limit, …). There is no arbitrary ORM call.
Start from models.describe: it reports the fields this production is willing
to expose, which is not the full Odoo schema.
Parameters
name- str · required — Production name.
operation- str · required — One of the read operations listed above.
params- dict · default none — Operation parameters as defined by the OduMCP API.
Use it when
- Answering a question about live data without copying the database into dev.
- Rendering a production report for a customer.
production_odoo_preview_change¶
Store a change plan in Odoo and return its approval_id. This does not
execute the business change. Actions include record.create / update /
delete, method.call, message.post, activity.schedule / update /
done and attachment.create.
Approval is a human act in Odoo, unless that production's own policy explicitly
permits auto-approval. Retrying the same intent means reusing the same
idempotency_key, never composing a second plan.
Parameters
name- str · required — Production name.
action- str · required — The planned action, e.g.
record.update. payload- dict · required — Action payload as defined by the OduMCP API.
idempotency_key- str · required — Stable key for this intent; reuse it when retrying.
batch_key- str · default empty — Groups plans that must be approved and executed together.
Use it when
- A production record genuinely has to change and the change needs an audit trail.
production_odoo_change_status¶
Read a plan's approval state and, once executed, its stored result.
This is also the correct response to an uncertain execute: the change tools never retry writes on their own, so the status is what tells you whether the earlier call landed.
Parameters
name- str · required — Production name.
approval_id- str · required — The ID returned by
production_odoo_preview_change.
Use it when
- Waiting on a human approval.
- A previous execute failed in transport and the outcome is unknown.
production_odoo_execute_change¶
Execute the stored, approved plan by ID. It never grants approval and never substitutes a payload — the plan that runs is the plan that was approved.
Check the returned state: pending, expired, rejected and failed all
mean the change did not happen. After a transport failure, check the status
before creating any new plan.
Parameters
name- str · required — Production name.
approval_id- str · required — The approved plan to execute.
Use it when
- A human has approved the plan in Odoo and the change should now be applied.
Agent Guidance & Feedback¶
get_agent_instructions¶
Load the compact Oduflow agent workflow and the active code-delivery mode.
Parameters
None.
Use it when
- Once at the start of an agent session, before other Oduflow tools. Not before every call — the guide holds for the session.
get_odoo_development_guide¶
Get the Odoo development standards and constraints guide for a specific Odoo version (15–19).
Parameters
version- str · required — Odoo version number. Both
"19"and"19.0"are accepted.
Use it when
- Before writing or refactoring Odoo module code. Determine the version from the request, from
get_environment_info, or from theodoo_imagevalue —odoo:18.0meansversion="18". - Immediately after
create_environmenttells you to.
report_issue¶
Build a prefilled link the user can follow to file a bug, feature request or feedback about Oduflow itself on GitHub.
The tool does not create the issue: it returns a prefilled link to the
oduflow/oduflow issue form. Show the link to the user and let them submit it
from their own GitHub account, so the report is attributable to them and they
can edit it first. Oduflow version, Python version, platform, transport and
routing mode are attached automatically.
Parameters
details- str · required — The report body: what happened, what was expected, or the feedback.
kind- str · default
"feedback"— One ofbug,feature,feedback. Selects the issue form and its labels. title- str · default empty — One-line summary used as the issue title.
Use it when
- The user hits a bug in Oduflow, wants a feature, or wants to send feedback — not for problems in their own Odoo code.
Never include identifying or customer data
No hostnames, repository URLs, branch or database names, credentials, or customer data in the text.
The exact current signature and defaults for every tool are also available from
oduflow list (oduflow list --verbose adds descriptions). The production
workflow and disaster-recovery consequences are covered in
Production Hosting; the CLI equivalents are in the
CLI Reference.
