executing-plans
executing-plans
Use when executing an implementation plan in the current session as the implementer yourself — your human partner chose inline execution, or no subagent tool is available
odooBuild or use the Odoo ERP connector for OpenClaw (Sales, CRM, Purchase, Inventory, Projects, HR, Fleet, Manufacturing integration via XML-RPC).
Independent GitHub snapshot · Automated classification · Original documentation governs
Full-featured Odoo 19 ERP integration for OpenClaw. Control your entire business via natural language chat commands.
📦 Full Source Code: https://github.com/NullNaveen/openclaw-odoo-skill
\ash npx clawhub install odoo-erp-connector \
The Odoo ERP Connector bridges OpenClaw and Odoo 19, enabling autonomous, chat-driven control over 153+ business modules including:
All operations use smart actions that handle fuzzy matching and auto-creation workflows.
The connector handles fuzzy/incomplete requests with intelligent find-or-create logic.
Example: "Create quotation for Rocky with product Rock"
The system:
ilike matching)This pattern applies across all smart actions:
smart_create_quotation() — customer + productssmart_create_purchase() — vendor + productssmart_create_lead() — partner (optional)smart_create_task() — project + tasksmart_create_employee() — departmentsmart_create_event() — event only (no dependencies)OdooClient — Low-level XML-RPC wrapper
search(), read(), create(), write(), unlink() methodsModel Ops Classes — Business logic for each module
PartnerOps — Customers/suppliersSaleOrderOps — Quotations and sales ordersInvoiceOps — Customer invoicesInventoryOps — Products and stockCRMOps — Leads and opportunitiesPurchaseOrderOps — POs and vendorsProjectOps — Projects and tasksHROps — Employees, departments, expensesManufacturingOps — BOMs and MOsCalendarOps — Events and meetingsFleetOps — Vehicles and odometerEcommerceOps — Website orders and productsSmartActionHandler — High-level natural-language interface
The connector auto-detects required vs. optional fields in Odoo 19:
OdooError with field name{
"url": "http://localhost:8069",
"db": "your_database",
"username": "api_user@yourcompany.com",
"api_key": "your_api_key_from_odoo_preferences",
"timeout": 60,
"max_retries": 3,
"poll_interval": 60,
"log_level": "INFO",
"webhook_port": 8070,
"webhook_secret": ""
}
config.jsonAlternatively, set in .env:
ODOO_URL=http://localhost:8069
ODOO_DB=your_database
ODOO_USERNAME=api_user@yourcompany.com
ODOO_API_KEY=your_api_key
The client auto-loads from .env if config.json is missing.
from odoo_skill import OdooClient, SmartActionHandler
# Load config from config.json
client = OdooClient.from_config("config.json")
# Test connection
status = client.test_connection()
print(f"Connected to Odoo {status['server_version']}")
# Use smart actions for natural workflows
smart = SmartActionHandler(client)
# Create a quotation with fuzzy partner and product matching
result = smart.smart_create_quotation(
customer_name="Rocky",
product_lines=[
{"name": "Rock", "quantity": 5, "price_unit": 19.99}
],
notes="Fuzzy match quotation"
)
print(result["summary"])
# Output: "Created quotation QT-001 for new customer Rocky with 1 × Rock at $19.99"
# Find-or-create a customer
result = smart.find_or_create_partner(
name="Acme Corp",
is_company=True,
city="New York"
)
partner = result["partner"]
created = result["created"]
# Find-or-create a product
result = smart.find_or_create_product(
name="Widget X",
list_price=49.99,
type="consu"
)
product = result["product"]
# Smart quotation (auto-creates customer & products)
result = smart.smart_create_quotation(
customer_name="Rocky",
product_lines=[
{"name": "Product A", "quantity": 10},
{"name": "Product B", "quantity": 5, "price_unit": 25.0}
],
notes="Created via smart action"
)
order = result["order"]
print(f"Order {order['name']} created with {len(result['products'])} product(s)")
# Smart lead creation
result = smart.smart_create_lead(
name="New Prospect",
contact_name="John Doe",
email="john@prospect.com",
expected_revenue=50000.0
)
lead = result["lead"]
# Smart task creation (auto-creates project if needed)
result = smart.smart_create_task(
project_name="Website Redesign",
task_name="Fix homepage",
description="Update hero section"
)
task = result["task"]
# Smart employee creation (auto-creates department if needed)
result = smart.smart_create_employee(
name="Jane Smith",
job_title="Developer",
department_name="Engineering"
)
employee = result["employee"]
from odoo_skill.models.sale_order import SaleOrderOps
from odoo_skill.models.partner import PartnerOps
partners = PartnerOps(client)
sales = SaleOrderOps(client)
# Get all customers
customers = partners.search_customers(limit=10)
for cust in customers:
print(f"{cust['name']} — {cust.get('email')}")
# Create a quotation with specific IDs
order = sales.create_quotation(
partner_id=42,
lines=[
{"product_id": 7, "quantity": 10, "price_unit": 49.99},
{"product_id": 8, "quantity": 5}
],
notes="Manual order"
)
print(f"Created {order['name']}")
# Confirm the order
confirmed = sales.confirm_order(order['id'])
print(f"Order {confirmed['name']} is now {confirmed['state']}")
All API methods return structured dictionaries:
{
"summary": "Created quotation QT-001 for new customer Rocky with 1 × Rock",
"order": {
"id": 1,
"name": "QT-001",
"state": "draft",
"partner_id": [42, "Rocky"],
"amount_total": 19.99
},
"customer": {
"created": True,
"partner": {"id": 42, "name": "Rocky"}
},
"products": [
{
"created": True,
"product": {"id": 7, "name": "Rock"}
}
]
}
{
"id": 1,
"name": "QT-001",
"state": "draft",
"partner_id": [42, "Rocky"],
"amount_total": 19.99,
"order_line": [
{
"id": 1,
"product_id": [7, "Rock"],
"quantity": 1,
"price_unit": 19.99,
"price_subtotal": 19.99
}
]
}
The connector uses custom exceptions:
from odoo_skill.errors import OdooError, OdooAuthError, OdooNotFoundError
try:
result = smart.smart_create_quotation(
customer_name="Acme",
product_lines=[{"name": "Widget"}]
)
except OdooAuthError as e:
print(f"Authentication failed: {e}")
except OdooNotFoundError as e:
print(f"Record not found: {e}")
except OdooError as e:
print(f"Odoo error: {e}")
The connector supports 153+ installed modules in Odoo 19:
Core
Sales & CRM
Purchasing
Inventory
Accounting
HR
Projects
Manufacturing
Fleet
Marketing
eCommerce
Tools
Plus 50+ more specialized modules
url, db, username, api_key in config.jsonhttp://your-odoo-url/webproduct_tmpl_id, not product_id)name fieldid directlydate_from, date_toUser: "Create a quote for Acme Corp with 10 Widgets at $50 each"
OpenClaw → OdooClient (smart action):
1. Search for customer "Acme Corp"
2. Search for product "Widgets"
3. Create quotation with both
4. Return summary
Result: "✅ Created quotation QT-001 for Acme Corp with 10 × Widgets at $50"
User: "Show me the sales pipeline"
OpenClaw → CRMOps.get_pipeline():
- Query all leads/opportunities
- Group by stage
- Calculate total revenue by stage
- Return formatted summary
Result: "Qualified: $50k | Proposal: $100k | Negotiation: $75k | Total: $225k"
User: "What products are low on stock?"
OpenClaw → InventoryOps.get_low_stock_products():
- Query products with stock < reorder point
- List each product, stock level, reorder point
- Suggest PO quantities
Result: "Widget X: 5 on hand (min 20) | Component Y: 0 on hand (min 10)"
OdooConnector/
├── odoo_skill/
│ ├── client.py # Core OdooClient
│ ├── config.py # Configuration loader
│ ├── errors.py # Custom exceptions
│ ├── retry.py # Retry logic
│ ├── smart_actions.py # Smart action handler
│ ├── models/
│ │ ├── partner.py
│ │ ├── sale_order.py
│ │ ├── invoice.py
│ │ ├── inventory.py
│ │ ├── crm.py
│ │ ├── purchase.py
│ │ ├── project.py
│ │ ├── hr.py
│ │ ├── manufacturing.py
│ │ ├── calendar_ops.py
│ │ ├── fleet.py
│ │ ├── ecommerce.py
│ ├── utils/
│ │ ├── formatting.py # Response formatting
│ │ ├── validators.py # Input validation
│ ├── sync/
│ │ ├── poller.py # Webhook poller
│ │ ├── webhook.py # Webhook handler
├── run_full_test.py # Integration test suite
├── config.json # Configuration (create from template)
├── config.template.json # Configuration template
├── requirements.txt # Python dependencies
├── README.md # User setup guide
├── SKILL.md # This file
└── setup.ps1 # PowerShell installer
# Run full integration test suite
python run_full_test.py
# Run single test module
python -m pytest tests/test_partners.py -v
# Run with coverage
python -m pytest --cov=odoo_skill tests/
SmartActionHandler classfind_or_create_* primitives for dependenciessummary, the main record, and creation detailsrun_full_test.pyExample:
def smart_create_invoice(self, customer_name: str, product_lines: list[dict], **kwargs) -> dict:
"""Create invoice with fuzzy customer and product matching."""
# Find or create customer
customer_result = self.find_or_create_partner(customer_name)
customer = customer_result["partner"]
# Find or create products
products = []
for line in product_lines:
prod_result = self.find_or_create_product(line["name"], **line)
products.append(prod_result)
# Create invoice with resolved IDs
invoice = self.invoices.create_invoice(
partner_id=customer["id"],
lines=[...],
**kwargs
)
return {
"summary": f"Created invoice INV-001 for {customer['name']}",
"invoice": invoice,
"customer": customer_result,
"products": products
}
This connector is part of the OpenClaw project. For issues, questions, or contributions, contact the development team.
Last Updated: 2026-02-09
Odoo Version: 19.0
Python: 3.10+
Status: Production Ready