Odoo Manager Skill
🔐 URL, Database & Credential Resolution
URL Resolution
Odoo server URL precedence (highest to lowest):
- 1.
temporary_url — one-time URL for a specific operation - INLINECODE1 — user-defined URL for the current session
- INLINECODE2 — environment default URL
This allows you to:
- - Switch between multiple Odoo instances (production, staging, client-specific)
- Test against demo databases
- Work with different client environments without changing global config
Examples (conceptual):
CODEBLOCK0
Database Resolution
Database name (db) precedence:
- 1. INLINECODE4
- INLINECODE5
- INLINECODE6
Use this to:
- - Work with multiple databases on the same Odoo server
- Switch between test and production databases
Username & Secret Resolution
Username precedence:
- 1. INLINECODE7
- INLINECODE8
- INLINECODE9
Secret (password or API key) precedence:
- 1.
temporary_api_key or INLINECODE11 - INLINECODE12 or INLINECODE13
- INLINECODE14 (if set) or INLINECODE15
Important:
- - Odoo API keys are used in place of the password, with the usual login.
- Store passwords / API keys like real passwords; never log or expose them.
Environment variables are handled via standard OpenClaw metadata: requires.env declares required variables (ODOO_URL, ODOO_DB, ODOO_USERNAME, ODOO_PASSWORD). ODOO_API_KEY is an optional environment variable used instead of the password when present; it is not listed in metadata and should simply be set in the environment when needed.
Resolved Values
At runtime the skill always works with:
- -
{{resolved_url}} — final URL - INLINECODE23 — final database name
- INLINECODE24 — final login
- INLINECODE25 — password or API key actually used to authenticate
These are computed using the precedence rules above.
🔄 Context Management
The temporary_* and user_* names are runtime context variables used by the skill logic, not OpenClaw metadata fields. OpenClaw does not have an optional.context metadata key; context is resolved dynamically at runtime as described below.
Temporary Context (One-Time Use)
User examples:
- - "Pour cette requête, utilise l’instance staging Odoo"
- "Utilise la base
odoo_demo juste pour cette opération" - "Connecte-toi avec cet utilisateur uniquement pour cette action"
Behavior:
- - Set
temporary_* (url, db, username, api_key/password) - Use them for a single logical operation
- Automatically clear after use
This is ideal for:
- - Comparing data between two environments
- Running a single check on a different database
Session Context (Current Session)
User examples:
- - "Travaille sur l’instance Odoo du client XYZ"
- "Utilise la base
clientx_prod pour cette session" - "Connecte-toi avec mon compte administrateur pour les prochaines opérations"
Behavior:
- - Set
user_* (url, db, username, api_key/password) - Persist for the whole current session
- Overridden only by
temporary_* or by clearing INLINECODE34
Resetting Context
User examples:
- - "Reviens à la configuration Odoo par défaut"
- "Efface mon contexte utilisateur Odoo"
Action:
- - Clear
user_url, user_db, user_username, user_password, INLINECODE39 - Skill falls back to environment variables (
ODOO_URL, ODOO_DB, ODOO_USERNAME, ODOO_PASSWORD / ODOO_API_KEY)
Viewing Current Context
User examples:
- - "Sur quelle instance Odoo es-tu connecté ?"
- "Montre la configuration Odoo actuelle"
Response should show (never full secrets):
CODEBLOCK1
⚙️ Odoo XML-RPC Basics
Odoo exposes part of its server framework over XML-RPC (not REST).
The External API is documented here: https://www.odoo.com/documentation/18.0/fr/developer/reference/external_api.html
Two main endpoints:
- -
{{resolved_url}}/xmlrpc/2/common — authentication and meta calls - INLINECODE46 — model methods via INLINECODE47
1. Checking Server Version
Call version() on the common endpoint to verify URL and connectivity:
CODEBLOCK2
Example result:
CODEBLOCK3
2. Authenticating
Use authenticate(db, username, password_or_api_key, {}) on the common endpoint:
CODEBLOCK4
INLINECODE52 is an integer user ID and will be used in all subsequent calls.
If authentication fails, uid is False / 0 — the skill should:
- - Inform the user that credentials or database are invalid
- Suggest checking
ODOO_URL, ODOO_DB, username, and secret
3. Calling Model Methods with execute_kw
Build an XML-RPC client for the object endpoint:
CODEBLOCK5
Then use execute_kw with the following signature:
CODEBLOCK6
All ORM operations in this skill are expressed in terms of execute_kw.
🔍 Domains & Data Types (Odoo ORM)
Domain Filters
Domains are lists of conditions:
CODEBLOCK7
Examples:
- - All companies: INLINECODE61
- Partners in France: INLINECODE62
- Leads with probability > 50%: INLINECODE63
Common operators:
- -
"=", "!=", ">", ">=", "<", INLINECODE69 - INLINECODE70 ,
"ilike" (case-insensitive) - INLINECODE72 , INLINECODE73
- INLINECODE74 (hierarchical relations)
Field Value Conventions
- - Integer / Float / Char / Text: use native types.
- Date / Datetime: strings in
YYYY-MM-DD or ISO 8601 format. - Many2one: usually send the record ID (
int) when writing; reads often return [id, display_name]. - One2many / Many2many: use the Odoo command list protocol for writes (not fully detailed here; see Odoo docs if needed).
🧩 Generic ORM Operations (execute_kw)
Each subsection below shows typical user queries and the corresponding
execute_kw usage. They are applicable to any model (not only res.partner).
List / Search Records (search)
User queries:
- - "Liste tous les partenaires société"
- "Cherche les commandes de vente confirmées"
Action (generic):
CODEBLOCK8
Notes:
- -
domain is a list (can be empty [] to match all records). - Use
offset and limit for pagination.
Count Records (search_count)
User queries:
- - "Combien de partenaires sont des sociétés ?"
- "Compte les tâches en cours"
Action:
CODEBLOCK9
Read Records by ID (read)
User queries:
- - "Affiche les détails du partenaire 7"
- "Donne-moi les champs name et country_id pour ces IDs"
Action:
CODEBLOCK10
If fields is omitted, Odoo returns all readable fields (often a lot).
Search and Read in One Step (search_read)
Shortcut for search() + read() in a single call.
User queries:
- - "Liste les sociétés (nom, pays, commentaire)"
- "Montre les 5 premiers partenaires avec leurs pays"
Action:
CODEBLOCK11
Create Records (create)
User queries:
- - "Crée un nouveau partenaire 'New Partner'"
- "Crée une nouvelle tâche dans le projet X"
Action:
CODEBLOCK12
Returns the newly created record ID.
Update Records (write)
User queries:
- - "Met à jour le partenaire 7, change son nom"
- "Baisse la probabilité de ces leads"
Action:
CODEBLOCK13
Notes:
- -
ids is a list of record IDs. - All records in
ids receive the same values.
Delete Records (unlink)
User queries:
- - "Supprime ce partenaire de test"
- "Efface ces tâches temporaires"
Action:
CODEBLOCK14
Name-Based Search (name_search)
Useful for quick lookup on models with a display name (e.g. partners, products).
User queries:
- - "Trouve le partenaire dont le nom contient 'Agrolait'"
Action:
CODEBLOCK15
Result is a list of [id, display_name].
👥 Contacts / Partners (res.partner)
INLINECODE90 is the core model for contacts, companies, and many business relations in Odoo.
List Company Partners
User queries:
- - "Liste toutes les sociétés"
- "Montre les sociétés avec leur pays"
Action:
CODEBLOCK16
Get a Single Partner
User queries:
- - "Affiche le partenaire 7"
- "Donne-moi le pays et le commentaire du partenaire 7"
Action:
CODEBLOCK17
Create a New Partner
User queries:
- - "Crée un partenaire 'Agrolait 2' en tant que société"
- "Crée un contact personne rattaché à la société X"
Minimal body:
CODEBLOCK18
Additional fields examples:
- -
street, zip, city, INLINECODE94 - INLINECODE95 ,
phone, INLINECODE97 - INLINECODE98 (
"person" or "company")
Update a Partner
User queries:
- - "Change l’adresse du partenaire 7"
- "Met à jour le pays et le téléphone"
Action:
CODEBLOCK19
Delete a Partner
User queries:
- - "Supprime le partenaire 999 de test"
Action:
CODEBLOCK20
🧱 Model Introspection (ir.model, ir.model.fields, fields_get)
Discover Fields of a Model (fields_get)
User queries:
- - "Quels sont les champs de res.partner ?"
- "Montre les types et labels des champs pour ce modèle"
Action:
CODEBLOCK21
The result is a mapping from field name to metadata:
CODEBLOCK22
List All Models (ir.model)
User queries:
- - "Quels modèles sont disponibles dans ma base Odoo ?"
Action:
CODEBLOCK23
INLINECODE101 indicates whether a model is defined in code ("base") or created dynamically ("manual").
List Fields of a Specific Model (ir.model.fields)
User queries:
- - "Donne-moi la liste des champs du modèle res.partner via ir.model.fields"
Action (simplified):
CODEBLOCK24
⚠️ Error Handling & Best Practices
Typical Errors
- - Authentication failure: wrong URL, DB, username, or secret →
authenticate returns False or later calls fail. - Access rights / ACLs: user does not have permission on a model or record.
- Validation errors: required fields missing, constraints violated.
- Connectivity issues: network errors reaching
xmlrpc/2/common or xmlrpc/2/object.
The skill should:
- - Clearly indicate if the issue is with connection, credentials, or business validation.
- Propose next steps (check env vars, context overrides, user rights).
Pagination
- - Use
limit / offset on search and search_read to handle large datasets. - For interactive use, default
limit to a reasonable value (e.g. 80).
Field Selection
- - Always send an explicit
fields list for read / search_read when possible. - This reduces payload and speeds up responses.
Domains & Performance
- - Prefer indexed fields and simple operators (
=, in) for large datasets. - Avoid unbounded searches without domain on very big tables when possible.
🚀 Quick End-to-End Examples
Example 1: Check Connection & List Company Partners
- 1. Resolve context:
{{resolved_url}}, {{resolved_db}}, {{resolved_username}}, INLINECODE121 - Call
version() on INLINECODE123 - Authenticate to get INLINECODE124
- Call
execute_kw on res.partner with search_read and domain INLINECODE128
Example 2: Create a Partner, Then Read It Back
- 1. Authenticate via INLINECODE129
- INLINECODE130 a new
res.partner with INLINECODE132 - INLINECODE133 that ID with fields INLINECODE134
Example 3: Work on Another Database for One Operation
- 1. Set
temporary_url and/or temporary_db to point to another Odoo environment. - Authenticate and perform the requested operation using resolved context.
- Temporary context is cleared automatically.
📚 References & Capabilities Summary
- - Official Odoo External API documentation (XML-RPC): https://www.odoo.com/documentation/18.0/fr/developer/reference/external_api.html
- Requires an Odoo plan with External API access (Custom plans; not available on One App Free / Standard).
This skill can:
- - Connect to Odoo via XML-RPC using password or API key.
- Switch dynamically between multiple instances and databases using context.
- Perform generic CRUD (
search, search_count, read, search_read, create, write, unlink) on any Odoo model via execute_kw. - Provide ready-made flows for
res.partner (contacts / companies). - Inspect model structures using
fields_get, ir.model, and ir.model.fields. - Apply best practices regarding pagination, field selection, and error handling.
Odoo Manager 技能
🔐 URL、数据库与凭证解析
URL 解析
Odoo 服务器 URL 优先级(从高到低):
- 1. temporaryurl — 特定操作的一次性 URL
- userurl — 当前会话的用户自定义 URL
- ODOO_URL — 环境默认 URL
这允许您:
- - 在多个 Odoo 实例之间切换(生产、预发布、特定客户端)
- 针对演示数据库进行测试
- 在不同客户端环境中工作,无需更改全局配置
示例(概念性):
text
// 默认:使用环境中的 ODOO_URL
{{resolved_url}}/xmlrpc/2/common
// 为一次操作覆盖:
temporary_url = https://staging.mycompany.odoo.com
{{resolved_url}}/xmlrpc/2/common
// 为会话覆盖:
user_url = https://client-xyz.odoo.com
{{resolved_url}}/xmlrpc/2/common
数据库解析
数据库名称(db)优先级:
- 1. temporarydb
- userdb
- ODOO_DB
使用此功能:
- - 在同一 Odoo 服务器上处理多个数据库
- 在测试数据库和生产数据库之间切换
用户名与密钥解析
用户名优先级:
- 1. temporaryusername
- userusername
- ODOO_USERNAME
密钥(密码或 API 密钥)优先级:
- 1. temporaryapikey 或 temporarypassword
- userapikey 或 userpassword
- ODOOAPIKEY(如果设置)或 ODOO_PASSWORD
重要提示:
- - Odoo API 密钥替代密码使用,使用常规登录方式。
- 像存储真实密码一样存储密码/API 密钥;切勿记录或暴露它们。
环境变量通过标准 OpenClaw 元数据处理:requires.env 声明必需变量(ODOOURL、ODOODB、ODOOUSERNAME、ODOOPASSWORD)。ODOOAPIKEY 是一个可选环境变量,存在时替代密码使用;它不在元数据中列出,只需在需要时在环境中设置即可。
解析后的值
在运行时,技能始终使用:
- - {{resolvedurl}} — 最终 URL
- {{resolveddb}} — 最终数据库名称
- {{resolvedusername}} — 最终登录名
- {{resolvedsecret}} — 实际用于认证的密码或 API 密钥
这些值使用上述优先级规则计算得出。
🔄 上下文管理
temporary 和 user 名称是技能逻辑使用的运行时上下文变量,而非 OpenClaw 元数据字段。OpenClaw 没有 optional.context 元数据键;上下文按如下所述在运行时动态解析。
临时上下文(一次性使用)
用户示例:
- - 对于此请求,使用 Odoo 预发布实例
- 仅为此操作使用 odoo_demo 数据库
- 仅为此操作使用此用户连接
行为:
- - 设置 temporary*(url、db、username、apikey/password)
- 用于单个逻辑操作
- 使用后自动清除
适用于:
- - 比较两个环境之间的数据
- 在不同数据库上运行单个检查
会话上下文(当前会话)
用户示例:
- - 在客户端 XYZ 的 Odoo 实例上工作
- 为此会话使用 clientx_prod 数据库
- 使用我的管理员账户进行后续操作
行为:
- - 设置 user(url、db、username、apikey/password)
- 在整个当前会话中持续存在
- 仅被 temporary 覆盖或通过清除 user* 覆盖
重置上下文
用户示例:
- - 恢复为默认 Odoo 配置
- 清除我的 Odoo 用户上下文
操作:
- - 清除 userurl、userdb、userusername、userpassword、userapikey
- 技能回退到环境变量(ODOOURL、ODOODB、ODOOUSERNAME、ODOOPASSWORD / ODOOAPIKEY)
查看当前上下文
用户示例:
- - 你连接到了哪个 Odoo 实例?
- 显示当前 Odoo 配置
响应应显示(绝不显示完整密钥):
text
当前 Odoo 上下文:
- - URL:https://client-xyz.odoo.com (userurl)
- 数据库:clientxyzprod (userdb)
- 用户名:apiintegration (userusername)
- 密钥:使用 API 密钥 (userapikey)
- 回退 URL:https://default.odoo.com (ODOOURL)
- 回退数据库:defaultdb (ODOODB)
⚙️ Odoo XML-RPC 基础
Odoo 通过 XML-RPC(而非 REST)暴露其服务器框架的一部分。
外部 API 文档在此:https://www.odoo.com/documentation/18.0/zhCN/developer/reference/externalapi.html
两个主要端点:
- - {{resolvedurl}}/xmlrpc/2/common — 认证和元数据调用
- {{resolvedurl}}/xmlrpc/2/object — 通过 execute_kw 调用模型方法
1. 检查服务器版本
调用 common 端点的 version() 以验证 URL 和连接:
python
common = xmlrpc.client.ServerProxy(f{resolved_url}/xmlrpc/2/common)
version_info = common.version()
示例结果:
json
{
server_version: 18.0,
serverversioninfo: [18, 0, 0, final, 0],
server_serie: 18.0,
protocol_version: 1
}
2. 认证
在 common 端点上使用 authenticate(db, username, passwordorapi_key, {}):
python
uid = common.authenticate(resolveddb, resolvedusername, resolved_secret, {})
uid 是一个整数用户 ID,将在所有后续调用中使用。
如果认证失败,uid 为 False / 0 — 技能应:
- - 告知用户凭据或数据库无效
- 建议检查 ODOOURL、ODOODB、用户名和密钥
3. 使用 execute_kw 调用模型方法
为 object 端点构建 XML-RPC 客户端:
python
models = xmlrpc.client.ServerProxy(f{resolved_url}/xmlrpc/2/object)
然后使用以下签名的 execute_kw:
python
models.execute_kw(
resolved_db,
uid,
resolved_secret,
model.name, # 例如 res.partner
methodname, # 例如 searchread
[positional_args],
{keyword_args}
)
本技能中的所有 ORM 操作均以 execute_kw 表示。
🔍 域与数据类型(Odoo ORM)
域过滤器
域是条件列表:
python
domain = [[field_name, operator, value], ...]
示例:
- - 所有公司:[[iscompany, =, True]]
- 法国的合作伙伴:[[countryid, =, france_id]]
- 概率 > 50% 的线索:[[probability, >, 50]]
常用运算符:
- - =、!=、>、>=、<、<=
- like、ilike(不区分大小写)
- in、not in
- child_of(层级关系)
字段值约定
- - 整数 / 浮点数 / 字符 / 文本:使用原生类型。
- 日期 / 日期时间:YYYY-MM-DD 或 ISO 8601 格式的字符串。
- 多对一:写入时通常发送记录 ID(int);读取时通常返回 [id, display_name]。
- 一对多 / 多对多:写入时使用 Odoo 命令列表协议(此处不详述;如有需要请参阅 Odoo 文档)。
🧩 通用 ORM 操作(execute_kw)
以下每个小节显示典型的用户查询和相应的 execute_kw 用法。它们适用于任何模型(不仅仅是 res.partner)。
列出/搜索记录(search)
用户查询: