Agent
Odoo Agent Backup Validation
Validate your Odoo backup strategy and rehearse restore procedures via the AI agent.
odoocli -q "Check if my backups are current"odoo-agent-backup-validateSKILL LIBRARY
Skills are self-contained Odoo operations. Add them to the CLI, your MCP server, or any agent framework — each one works standalone without the full toolkit.
23
Skills available
3
Categories
1
File per skill
WORKS WITH
>_ OdooCLIMCP Claude Desktop, Cursor, WindsurfSDK LangChain, CrewAI, custom agentsAgent
Validate your Odoo backup strategy and rehearse restore procedures via the AI agent.
odoocli -q "Check if my backups are current"odoo-agent-backup-validateAgent
Install or upgrade an Odoo module with preflight checks, backup reminder, and rollback safety via the AI agent.
odoocli -q "Install the sale_management module"odoo-agent-deploy-moduleAgent
Run a full instance diagnostic via the AI agent — server version, modules, users, cron status, and recent errors in one command.
odoocli -q "Is my Odoo instance healthy?"odoo-agent-health-checkAgent
Detect negative stock, overdue transfers, and valuation discrepancies across your Odoo warehouse via the AI agent.
odoocli -q "Are there any products with negative stock?"odoo-agent-inventory-auditAgent
Batch review and post draft invoices with confirmation via the AI agent.
odoocli -q "Post all draft invoices from this month"odoo-agent-invoice-postingReliability
Detect attachment growth and database-backed blobs so filestore misconfiguration or restore drift is caught before PostgreSQL disk pressure incidents.
bash -lc "psql \"$ODOO_DB_URI\" -c \"select count(*) as attachments, pg_size_pretty(pg_total_relation_size(''ir_attachment'')) as table_total_size, count(*) filter (where store_fname is null and db_datas is not null) as db_backed_rows from ir_attachment;\" -c \"select coalesce(res_model, ''(none)'') as model, count(*) as rows, pg_size_pretty(sum(coalesce(file_size, 0))::bigint) as logical_file_size from ir_attachment group by coalesce(res_model, ''(none)'') order by sum(coalesce(file_size, 0)) desc nulls last limit 15;\""odoo-attachment-storage-drift-checkReliability
Validate your latest PostgreSQL backup and fail fast if the file is stale.
ls -1t /var/backups/odoo/*.dump | head -n 1odoo-db-backup-checkReliability
Surface tables accumulating dead tuples so slow reads/writes are caught early when autovacuum falls behind.
psql "$ODOO_DB_URI" -c "select relname as table_name, n_live_tup, n_dead_tup, round(100.0 * n_dead_tup / nullif(n_live_tup + n_dead_tup, 0), 2) as dead_pct, coalesce(to_char(last_autovacuum, 'YYYY-MM-DD HH24:MI:SS'), 'never') as last_autovacuum from pg_stat_user_tables where schemaname = 'public' and relname in ('sale_order','account_move','stock_move','mail_mail','queue_job') order by n_dead_tup desc;"odoo-dead-tuple-bloat-checkReliability
Detect ir_attachment records whose backing files are missing from filestore after restores, rsync drift, or partial volume loss.
bash -lc "psql \"$ODOO_DB_URI\" -Atc \"select id, store_fname from ir_attachment where type = 'binary' and store_fname is not null order by id desc limit 2500\" | while IFS=\"|\" read -r id fname; do primary=\"$ODOO_FILESTORE/$fname\"; fallback=\"$ODOO_FILESTORE/${fname:0:2}/${fname:2:2}/$fname\"; [ -f \"$primary\" ] || [ -f \"$fallback\" ] || echo \"$id|$fname|missing_blob\"; done"odoo-filestore-missing-blob-checkReliability
Detect PostgreSQL sessions left idle inside open transactions, a common hidden source of lock waits and stalled Odoo writes.
psql "$ODOO_DB_URI" -c "select pid, usename, application_name, client_addr, now() - xact_start as txn_age, now() - state_change as idle_for, wait_event_type, left(query, 140) as last_query from pg_stat_activity where datname = current_database() and state = 'idle in transaction' order by xact_start asc;"odoo-idle-in-transaction-checkReliability
Map blocked PostgreSQL sessions to their blockers so you can cancel the right statement first instead of killing workers blindly.
psql "$ODOO_DB_URI" -c "select blocked.pid as blocked_pid, blocked.application_name as blocked_app, now() - blocked.query_start as blocked_for, blocking.pid as blocking_pid, blocking.application_name as blocking_app, now() - blocking.query_start as blocking_for, left(blocking.query, 140) as blocking_query from pg_stat_activity blocked join pg_locks blocked_locks on blocked.pid = blocked_locks.pid and not blocked_locks.granted join pg_locks blocking_locks on blocked_locks.locktype = blocking_locks.locktype and blocked_locks.database is not distinct from blocking_locks.database and blocked_locks.relation is not distinct from blocking_locks.relation and blocked_locks.page is not distinct from blocking_locks.page and blocked_locks.tuple is not distinct from blocking_locks.tuple and blocked_locks.virtualxid is not distinct from blocking_locks.virtualxid and blocked_locks.transactionid is not distinct from blocking_locks.transactionid and blocked_locks.classid is not distinct from blocking_locks.classid and blocked_locks.objid is not distinct from blocking_locks.objid and blocked_locks.objsubid is not distinct from blocking_locks.objsubid and blocking_locks.granted join pg_stat_activity blocking on blocking_locks.pid = blocking.pid where blocked.datname = current_database() order by blocking_for desc;"odoo-lock-blocker-graphReliability
Surface active PostgreSQL queries running longer than 60 seconds so you can isolate slow endpoints, blocked ORM calls, and runaway report jobs before they cascade.
psql "$ODOO_DB_URI" -c "select pid, usename, application_name, state, wait_event_type, wait_event, now() - query_start as query_age, left(query, 180) as query_excerpt from pg_stat_activity where datname = current_database() and state = 'active' and query_start is not null and now() - query_start > interval '60 seconds' and query not ilike '%pg_stat_activity%' order by query_age desc;"odoo-long-running-query-checkDeployment
Pull custom modules and restart Odoo in one safe shell sequence.
git pull && ./scripts/restart-odoo.shodoo-module-syncDeployment
Surface modules left in to-install/to-upgrade/to-remove states so you catch incomplete release work before users do.
psql "$ODOO_DB_URI" -c "select name, state, latest_version from ir_module_module where state in ('to install','to upgrade','to remove') order by state, name;"odoo-module-upgrade-preflightReliability
Surface long-lived PostgreSQL transactions that often sit behind lock waits, stalled writes, and upgrade friction.
psql "$ODOO_DB_URI" -c "select pid, usename, application_name, state, wait_event_type, now() - xact_start as txn_age, left(query, 140) as query from pg_stat_activity where datname = current_database() and xact_start is not null order by xact_start asc limit 20;"odoo-oldest-transaction-checkReliability
Detect stuck outgoing emails and repeated send failures so customer notifications do not silently pile up.
psql "$ODOO_DB_URI" -c "select state, count(*) as jobs, min(create_date) as oldest_created, max(create_date) as newest_created from mail_mail where state in ('outgoing','exception') group by state order by jobs desc;"odoo-outbound-mail-queue-checkReliability
Detect scheduled actions that missed their nextcall window so silent automation drift is caught before finance, sync, or notification jobs are skipped.
psql "$ODOO_DB_URI" -c "select name, user_id, interval_number, interval_type, nextcall, now() - nextcall as overdue_for from ir_cron where active = true and nextcall < now() - interval '5 minutes' order by overdue_for desc;"odoo-overdue-cron-checkReliability
Surface high-dead-tuple tables with stale autovacuum timestamps and show currently running vacuum progress before bloat and freeze pressure become write incidents.
bash -lc "psql \"$ODOO_DB_URI\" -c \"select schemaname, relname, n_live_tup, n_dead_tup, round(100 * n_dead_tup::numeric / nullif(n_live_tup + n_dead_tup, 0), 2) as dead_pct, last_autovacuum, now() - coalesce(last_autovacuum, last_vacuum) as since_last_vacuum from pg_stat_user_tables where n_live_tup > 0 and ((n_dead_tup > 50000 and n_dead_tup::numeric / nullif(n_live_tup + n_dead_tup, 0) > 0.10) or coalesce(last_autovacuum, last_vacuum) is null or coalesce(last_autovacuum, last_vacuum) < now() - interval ''1 day'') order by n_dead_tup desc limit 25;\" -c \"select p.pid, p.relid::regclass as relation, p.phase, p.heap_blks_scanned, p.heap_blks_total, now() - a.query_start as running_for from pg_stat_progress_vacuum p join pg_stat_activity a on a.pid = p.pid order by running_for desc;\""odoo-postgres-autovacuum-stall-checkReliability
Measure active PostgreSQL connections against max_connections so you can catch pool exhaustion before Odoo starts throwing connection errors.
psql "$ODOO_DB_URI" -c "with limits as (select setting::int as max_connections from pg_settings where name = 'max_connections'), usage as (select count(*) as current_connections, count(*) filter (where state = 'active') as active_connections, count(*) filter (where state = 'idle in transaction') as idle_in_txn_connections from pg_stat_activity where datname = current_database()) select usage.current_connections, limits.max_connections, round(100.0 * usage.current_connections / nullif(limits.max_connections, 0), 1) as pct_used, usage.active_connections, usage.idle_in_txn_connections from usage cross join limits;"odoo-postgres-connection-saturation-checkReliability
Measure streaming replica lag in bytes and time so you can catch stale read replicas and failover risk before incidents.
psql "$ODOO_DB_URI" -c "select application_name, client_addr, state, sync_state, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn)) as lsn_lag, write_lag, flush_lag, replay_lag from pg_stat_replication order by pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) desc nulls last;"odoo-postgres-replication-lag-checkReliability
Surface stalled physical/logical replication slots retaining WAL so you catch disk-growth risk before PostgreSQL fills volume and stalls writes.
bash -lc "psql \"$ODOO_DB_URI\" -c \"select slot_name, slot_type, active, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)) as retained_wal, pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)::bigint as retained_wal_bytes, restart_lsn, confirmed_flush_lsn from pg_replication_slots order by retained_wal_bytes desc nulls last;\" -c \"select count(*) as slots, count(*) filter (where not active) as inactive_slots, pg_size_pretty(coalesce(sum(pg_wal_lsn_diff(pg_current_wal_lsn(), restart_lsn)), 0)::bigint) as total_retained_wal from pg_replication_slots;\""odoo-postgres-replication-slot-lag-checkReliability
Measure transaction ID age at database and table level so you catch autovacuum freeze risk before PostgreSQL forces write-blocking emergency vacuum.
bash -lc "psql \"$ODOO_DB_URI\" -c \"select datname, age(datfrozenxid) as xid_age, round(100 * age(datfrozenxid)::numeric / current_setting(''autovacuum_freeze_max_age'')::numeric, 2) as pct_of_freeze_max_age from pg_database where datallowconn order by age(datfrozenxid) desc;\" -c \"select n.nspname as schema, c.relname, coalesce(s.n_dead_tup, 0) as dead_tuples, age(c.relfrozenxid) as rel_xid_age from pg_class c join pg_namespace n on n.oid = c.relnamespace left join pg_stat_user_tables s on s.relid = c.oid where c.relkind = ''r'' and n.nspname not in (''pg_catalog'', ''information_schema'') order by age(c.relfrozenxid) desc limit 20;\""odoo-postgres-xid-wraparound-risk-checkReliability
Surface stuck, failed, and long-running queue jobs before they become customer-facing incidents.
odoocli queue inspect --status failed,pending,started --older-than 15m --limit 50odoo-queue-health-checkUse skills directly from your MCP client — no terminal required.
Set up MCP