Odoo Manager技能使用说明
Odoo 管理员技能
🔐 URL、数据库与凭据解析
URL 解析
Odoo 服务器 URL 优先级(从高到低):
temporary_url— 用于特定操作的一次性 URLuser_url— 为当前会话用户定义的 URLODOO_URL— 环境默认 URL
这使您可以:

- 在多个 Odoo 实例之间切换(生产、预发布、特定客户)
- 针对演示数据库进行测试
- 无需更改全局配置即可处理不同的客户环境
示例(概念性):
// Default: uses ODOO_URL from environment
{{resolved_url}}/xmlrpc/2/common
// Override for one operation:
temporary_url = "https://staging.mycompany.odoo.com"
{{resolved_url}}/xmlrpc/2/common
// Override for session:
user_url = "https://client-xyz.odoo.com"
{{resolved_url}}/xmlrpc/2/common
数据库解析
数据库名称 (db) 优先级:
temporary_dbuser_dbODOO_DB
用于:
- 在同一Odoo服务器上处理多个数据库
- 在测试和生产数据库之间切换
用户名与密钥解析
用户名优先级:
temporary_usernameuser_usernameODOO_USERNAME
密钥(密码或API密钥)优先级:
temporary_api_key或temporary_passworduser_api_key或user_passwordODOO_API_KEY(若已设置)或ODOO_PASSWORD
重要提示:
- Odoo API密钥被用于替代密码,配合常规登录使用。
- 请像对待真实密码一样存储密码/API密钥;切勿记录或暴露它们。
环境变量通过标准的OpenClaw元数据处理:requires.env声明必需变量 (ODOO_URL、ODOO_DB、ODOO_USERNAME、ODOO_PASSWORD)。ODOO_API_KEY是一个可选的环境变量,当存在时,它将替代密码使用;它未列在元数据中,应在需要时直接在环境中设置。
解析后的值
在运行时,该技能始终使用:
{{resolved_url}}— 最终 URL{{resolved_db}}— 最终数据库名称{{resolved_username}}— 最终登录凭证{{已解析的密钥}}— 密码或实际用于身份验证的API密钥
这些值通过上述优先级规则计算得出。
🔄 上下文管理
这些
temporary_*和user_*名称是技能逻辑使用的运行时上下文变量,而非OpenClaw的元数据字段。OpenClaw并不拥有optional.context元数据键;上下文会在运行时根据下述规则动态解析。
临时上下文(一次性使用)
用户示例:
- "对于此请求,请使用Odoo的预发布实例"
- "使用
odoo_demo数据库""仅用于此操作" - "仅为此操作连接此用户"
行为:
- 设置
temporary_*(URL、数据库、用户名、API密钥/密码) - 将其用于单一逻辑操作
- 使用后自动清除
这非常适用于:
- 比较两个环境间的数据
- 在不同数据库上运行单次检查
会话上下文(当前会话)
用户示例:
- "处理客户XYZ的Odoo实例"
- "使用
clientx_prod数据库进行此会话" - "为后续操作使用我的管理员账户连接"
行为:
- 设置
user_*(网址,数据库,用户名,API密钥/密码) - 在当前整个会话期间持续有效
- 仅可通过以下方式覆盖
temporary_*或通过清除操作user_*
重置上下文
用户示例:
- "恢复到默认的Odoo配置"
- "清除我的Odoo用户上下文"
操作:
- 清除
用户网址、用户数据库、用户用户名、用户密码、用户API密钥 - 技能回退至环境变量(
ODOO_URL、ODOO_DB,ODOO_USERNAME,ODOO_PASSWORD/ODOO_API_KEY)
查看当前上下文
用户示例:
- "你连接的是哪个 Odoo 实例?"
- "显示当前的 Odoo 配置"
响应应显示(绝不显示完整密钥):
Current Odoo Context:
- URL: https://client-xyz.odoo.com (user_url)
- DB: clientxyz_prod (user_db)
- Username: api_integration (user_username)
- Secret: using API key (user_api_key)
- Fallback URL: https://default.odoo.com (ODOO_URL)
- Fallback DB: default_db (ODOO_DB)
⚙️ Odoo XML-RPC 基础
Odoo 通过XML-RPC(非 REST)公开其部分服务器框架。 外部 API 文档在此:https://www.odoo.com/documentation/18.0/fr/developer/reference/external_api.html
两个主要端点:
{{resolved_url}}/xmlrpc/2/common— 用于身份验证和元调用{{resolved_url}}/xmlrpc/2/object— 用于通过模型方法execute_kw
1. 检查服务器版本
调用version()在common端点以验证URL和连接性:
common = xmlrpc.client.ServerProxy(f"{resolved_url}/xmlrpc/2/common")
version_info = common.version()
示例结果:
{
"server_version": "18.0",
"server_version_info": [18, 0, 0, "final", 0],
"server_serie": "18.0",
"protocol_version": 1
}
2. 身份验证
使用authenticate(db, username, password_or_api_key, {})在通用端点:
uid = common.authenticate(resolved_db, resolved_username, resolved_secret, {})
uid是一个整数用户ID,将在所有后续调用中使用。
如果认证失败,uid为False/0——此时技能应:
- 告知用户凭据或数据库无效
- 建议检查
ODOO_URL,ODOO_DB、用户名和密钥
3. 使用 execute_kw 调用模型方法
为对象端点构建一个 XML-RPC 客户端:
models = xmlrpc.client.ServerProxy(f"{resolved_url}/xmlrpc/2/object")
然后使用execute_kw,其签名如下:
models.execute_kw(
resolved_db,
uid,
resolved_secret,
"model.name", # e.g. "res.partner"
"method_name", # e.g. "search_read"
[positional_args],
{keyword_args}
)
本技能中的所有 ORM 操作均以execute_kw的方式表达。
🔍 域与数据类型(Odoo ORM)
域过滤器
域是条件列表:
domain = [["field_name", "operator", value], ...]
示例:
- 所有公司:
[['is_company', '=', True]] - 法国的合作伙伴:
[['country_id', '=', france_id]] - 概率大于50%的线索:
[['probability', '>', 50]]
常用运算符
"=","!=",">",">=","<","<=""like","ilike"(不区分大小写)"in","not in""child_of"(层级关系)
字段值约定
- 整型 / 浮点型 / 字符型 / 文本型:使用原生类型。
- 日期型 / 日期时间型:采用
YYYY-MM-DD或ISO 8601格式。 - 多对一:写入时通常发送记录ID(
整数);读取时通常返回[id, display_name]。 - 一对多 / 多对多:写入时使用Odoo的命令列表协议(此处未完全详述;如有需要请参阅Odoo文档)。
🧩 通用ORM操作(execute_kw)
以下每个小节展示了典型的用户查询及其对应的execute_kw用法。这些操作适用于任何模型(不仅仅是res.partner)。
列出 / 搜索记录(search)
用户查询:
- "列出所有公司合作伙伴"
- "搜索已确认的销售订单"
通用操作:
ids = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "search",
[domain],
{"offset": 0, "limit": 80}
)
备注:
域是一个列表(可以为空[]以匹配所有记录)。- 使用
偏移量和限制进行分页。
记录计数(search_count)
用户查询:
- "有多少合作伙伴是公司?"
- "统计进行中的任务"
操作:
count = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "search_count",
[domain]
)
按ID读取记录(read)
用户查询:
- "显示合作伙伴7的详细信息"
- "给我这些ID的name和country_id字段"
操作:
records = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "read",
[ids],
{"fields": ["name", "country_id", "comment"]}
)
如果字段如果省略,Odoo 将返回所有可读字段(通常数量很多)。
一步完成搜索与读取(search_read)
这是search()与read()在一个调用中的快捷方式。
用户查询:
- "列出公司(名称、国家、备注)"
- "显示前5个合作伙伴及其国家"
操作:
records = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "search_read",
[domain],
{
"fields": ["name", "country_id", "comment"],
"limit": 5,
"offset": 0,
# Optional: "order": "name asc"
}
)
创建记录(create)
用户查询:
- "创建一个新的合作伙伴 'New Partner'"
- "在项目X中创建一个新任务"
操作:
new_id = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "create",
[{
"name": "New Partner"
# other fields...
}]
)
返回新创建记录的ID。
更新记录(write)
用户查询:
- "更新合作伙伴7,更改其名称"
- "降低这些线索的概率"
动作:
success = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "write",
[ids, {"field": "new value", "other_field": 123}]
)
说明:
ids是一个记录ID列表。- 所有在
ids中的记录都会接收到相同的值。
删除记录(解除关联)
用户查询:
- "删除这个测试合作伙伴"
- "清除这些临时任务"
动作:
success = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "unlink",
[ids]
)
基于名称的搜索(name_search)
适用于对具有显示名称的模型进行快速查找(例如合作伙伴、产品)。
用户查询:
- "查找名称包含'Agrolait'的合作伙伴"
动作:
results = models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "name_search",
["Agrolait"],
{"limit": 10}
)
结果是一个[id, display_name]的列表。
👥 联系人 / 合作伙伴 (res.partner)
res.partner是Odoo中联系人、公司以及许多业务关系的核心模型。
列出公司合作伙伴
用户查询:
- "列出所有公司"
- "显示公司及其所在国家"
操作:
companies = models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "search_read",
[[["is_company", "=", True]]],
{"fields": ["name", "country_id", "comment"], "limit": 80}
)
获取单个合作伙伴
用户查询:
- "显示合作伙伴7"
- "给我合作伙伴7的国家和备注"
操作:
[partner] = models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "read",
[[7]],
{"fields": ["name", "country_id", "comment"]}
)
创建新合作伙伴
用户查询:
- "创建一个名为'Agrolait 2'的公司合作伙伴"
- "创建一个隶属于公司X的个人联系人"
最小请求体:
partner_id = models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "create",
[{
"name": "New Partner",
"is_company": True
}]
)
额外字段示例:
street,zip,city,国家ID电子邮件,电话,手机公司类型("个人"或"公司")
更新合作伙伴
用户查询:
- "更改合作伙伴7的地址"
- "更新国家和电话"
操作:
models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "write",
[[7], {
"street": "New street 1",
"phone": "+33 1 23 45 67 89"
}]
)
删除合作伙伴
用户查询:
- "删除测试合作伙伴999"
操作:
models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "unlink",
[[999]]
)
🧱 模型内省 (ir.model, ir.model.fields, fields_get)
发现模型的字段 (fields_get)
用户查询:
- "res.partner 有哪些字段?"
- "显示此模型的字段类型和标签"
操作:
fields = models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "fields_get",
[],
{"attributes": ["string", "help", "type"]}
)
结果是字段名到元数据的映射:
{
"name": {"type": "char", "string": "Name", "help": ""},
"country_id": {"type": "many2one", "string": "Country", "help": ""},
"is_company": {"type": "boolean", "string": "Is a Company", "help": ""}
}
列出所有模型 (ir.model)
用户查询:
- "我的Odoo数据库中有哪些可用模型?"
操作:
models_list = models.execute_kw(
resolved_db, uid, resolved_secret,
"ir.model", "search_read",
[[]],
{"fields": ["model", "name", "state"], "limit": 200}
)
状态指示模型是在代码中定义的("base")还是动态创建的("manual")。
列出特定模型的字段 (ir.model.fields)
用户查询:
- "通过ir.model.fields给我res.partner模型的字段列表"
操作(简化版):
partner_model_ids = models.execute_kw(
resolved_db, uid, resolved_secret,
"ir.model", "search",
[[["model", "=", "res.partner"]]]
)
fields_meta = models.execute_kw(
resolved_db, uid, resolved_secret,
"ir.model.fields", "search_read",
[[["model_id", "in", partner_model_ids]]],
{"fields": ["name", "field_description", "ttype", "required", "readonly"], "limit": 500}
)
⚠️ 错误处理与最佳实践
典型错误
- 认证失败:错误的URL、数据库、用户名或密钥 →
进行身份验证返回False或后续调用失败。 - 访问权限/ACL:用户对模型或记录没有权限。
- 验证错误:必填字段缺失,违反约束条件。
- 连接问题:网络错误,无法访问
xmlrpc/2/common或xmlrpc/2/object。
该技能应:
- 明确指示问题是出在连接、凭证,还是业务验证。
- 提出后续步骤(检查环境变量、上下文覆盖、用户权限)。
分页
- 使用
限制/偏移量在搜索和搜索读取操作中处理大型数据集。 - 对于交互式使用,默认
限制为一个合理的值(例如80)。
字段选择
- 始终为
读取/搜索读取操作尽可能发送明确的字段列表。 - 这可以减少负载并加快响应速度。
域与性能
- 对于大型数据集,优先使用索引字段和简单运算符(
=、in)。 - 尽可能避免在非常大的表上进行无限制的无域搜索。
🚀 快速端到端示例
示例1:检查连接并列出公司合作伙伴
- 解析上下文:
{{resolved_url}},{{resolved_db}},{{resolved_username}},{{resolved_secret}} - 调用
version()在{{resolved_url}}/xmlrpc/2/common - 进行身份验证以获取
uid - 调用
execute_kw在res.partner使用search_read和域[['is_company', '=', True]]
示例2:创建合作伙伴,然后读取其信息
- 通过以下方式认证
common.authenticate 创建一个新的res.partner包含{"name": "新合作伙伴", "is_company": True}读取该ID的字段["name", "is_company", "country_id"]
示例3:为单次操作切换到另一个数据库
- 设置
temporary_url和/或temporary_db以指向另一个Odoo环境。 - 使用已解析的上下文进行认证并执行请求的操作。
- 临时上下文会自动清除。
📚 参考文档与功能概览
- 官方Odoo外部API文档(XML-RPC):https://www.odoo.com/documentation/18.0/fr/developer/reference/external_api.html
- 需要一个支持外部API访问的Odoo套餐(定制套餐;不适用于单应用免费版/标准版)。
此技能可以:
- 通过密码使用XML-RPC连接到Odoo或API密钥。
- 使用上下文在不同实例和数据库之间动态切换。
- 执行通用的CRUD操作(
搜索、计数搜索、读取、搜索并读取、创建、写入、删除)于任意Odoo模型,通过execute_kw方法。 - 为
res.partner(联系人/公司) - 提供现成的流程。
使用fields_get、ir.model和ir.model.fields - 来检查模型结构。


微信扫一扫,打赏作者吧~