agentleFS
actinon-comactinon-com/brass-monkey/skills/odoo-data-ops/SKILL.md

odoo-data-ops

Skill2 starsChanged 3 months agoMITView on GitHub

Expertise required to safely query and modify Odoo business data while maintaining a rigorous audit trail and reversibility context.

The file

Show its rules and text

We split this skill into the rules it gives an agent

20 rules. About 0 are common, 6 are distinctive, and 14 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈6

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 14

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Breadth (search_records): ALWAYS use search_records first to discover data and locate specific IDs.

    line 13
  2. Very specific:

    Safe Defaults: Leave fields blank/empty to fetch our optimized, low-token "Breadth Layout" (ID, Display Name, State, Freshness, and the …

    line 14
  3. Very specific:

    AND (&): Default behavior. ['&', (A), (B)] means A and B.

    line 22
  4. Very specific:

    All state-changing operations (create_record, write_record, unlink_record) require a justification parameter.

    line 28
  5. Very specific:

    Every CRUD tool supports an instance_alias parameter.

    line 33
  6. Distinctive:

    Default: If omitted, the tool uses the current session's default instance.

    line 34
  7. Very specific:

    Fields Overrides: If you need specific extra fields in search_records, pass them explicitly in the fields array.

    line 38
  8. Very specific:

    Aggregations: Use aggregate_records for BI-style queries (grouping, counting, summing).

    line 39
  9. Very specific:

    The Trigger: If you receive a ValueError or KeyError stating a field does not exist.

    line 43
  10. Distinctive:

    Action: After finding the correct field, retry the operation with the updated field list.

    line 45
  11. Distinctive:

    If you make a mistake or are asked to "undo" a change:

    line 48
  12. Very specific:

    Locate: Use get_record (with show_chatter: true) on the target record to find the "Before Snapshot" you previously posted.

    line 49
  13. Distinctive:

    Analyze: Verify the current record state.

    line 50
  14. Very specific:

    Revert: Use write_record to re-apply the old values from the snapshot, providing a justification like "Reverting previous AI action: …

    line 51
  15. Very specific:

    Mandate: NEVER simulate a transition with write_record on the state field.

    line 57
  16. Very specific:

    Use execute_method with the real button (action_confirm, action_post, button_validate).

    line 59
  17. Distinctive:

    X2many (One2many/Many2many): Use command tuples:

    line 71
  18. Very specific:

    Operational Safety: NEVER attempt to modify your own res.users record to change your active company.

    line 84
  19. Very specific:

    Correct Pattern: If you need to "switch" companies for a query, simply use the company_id domain filter.

    line 85
  20. Distinctive:

    Delete system-critical records to "clean up" your view.

    line 99

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Skill: Odoo Data Operations (CRUD)

This skill provides the agent with the expertise required to safely query and modify Odoo business data while maintaining a rigorous audit trail and reversibility context.

Core Mandates

1. The "Breadth vs. Depth" Search Paradigm (Golden Rule)

To prevent massive token-context inflation and optimize database execution, you must strictly follow this two-step data retrieval flow:

  1. Breadth (search_records): ALWAYS use search_records first to discover data and locate specific IDs.
    • Safe Defaults: Leave fields blank/empty to fetch our optimized, low-token "Breadth Layout" (ID, Display Name, State, Freshness, and the hierarchical "Belonging Relation").
    • Exclusions: This tool strictly excludes heavy relational arrays or child lines to keep the response microscopic and scanable.
    • Pagination: It returns a metadata envelope (total_count, leads map of ID to display names) to assist your pagination.
  2. Depth (get_record / get_records): Once you find a target ID, use get_record to fetch its 360-degree detailed "Record Dashboard".
    • Turn on flags like show_lines (resolves full child rows for line tables, e.g., sales lines) and show_chatter (fetches the last 5 Odoo Chatter comments) to get a complete picture in a single turn.

2. Odoo Domain Syntax (Prefix-based)

Odoo uses a prefix-based polish notation for domain filters. You must follow this syntax when using search_records:

  • AND (&): Default behavior. ['&', (A), (B)] means A and B.
  • OR (|): ['|', (A), (B)] means A or B.
  • NOT (!): ['!', (A)] means not A.
  • Example: ['&', ('is_company', '=', True), '|', ('city', '=', 'New York'), ('city', '=', 'London')]

3. Mandatory Justification

All state-changing operations (create_record, write_record, unlink_record) require a justification parameter.

  • Requirement: This must be a clear, business-focused reason for the change.
  • Persistence: This reason is permanently recorded in Odoo's Chatter (mail.message) and ir.logging.

4. Instance Awareness

Every CRUD tool supports an instance_alias parameter.

  • Default: If omitted, the tool uses the current session's default instance.
  • Cross-Instance: You can read from one environment and write to another by explicitly specifying different aliases in separate tool calls.

5. Efficient Data Retrieval

  • Fields Overrides: If you need specific extra fields in search_records, pass them explicitly in the fields array.
  • Aggregations: Use aggregate_records for BI-style queries (grouping, counting, summing). This is much more context-efficient than reading thousands of records to perform local math.

6. Schema Strictness & Error Recovery

Odoo v18+ is strict about field lists.

  • The Trigger: If you receive a ValueError or KeyError stating a field does not exist.
  • The Mandate: You must STOP and call inspect_model to verify the current live schema. Do NOT guess field names.
  • Action: After finding the correct field, retry the operation with the updated field list.

7. Agent-Driven Undo Workflow

If you make a mistake or are asked to "undo" a change:

  1. Locate: Use get_record (with show_chatter: true) on the target record to find the "Before Snapshot" you previously posted.
  2. Analyze: Verify the current record state. Do not attempt a rollback if it violates Odoo's business logic (e.g., trying to revert an invoice that has since been paid).
  3. Revert: Use write_record to re-apply the old values from the snapshot, providing a justification like "Reverting previous AI action: [Original Reason]".

8. Workflow Transitions (execute_method)

Business documents move through their lifecycle via buttons, not field writes. Confirming a quotation, posting an invoice or validating a transfer runs server-side logic that creates journal entries, reserves stock and fires automations.

  • Mandate: NEVER simulate a transition with write_record on the state field. Writing state = 'sale' sets a string and skips every side effect, leaving the database inconsistent. Use execute_method with the real button (action_confirm, action_post, button_validate).
  • Discovery: Find the button name with get_view (look for <button type="object"> in the form header) or trace_ui_path. The tool verifies your method against the live views anyway and will refuse a name it cannot find.
  • ORM primitives are refused. write, create, unlink, read and search are not callable here — that restriction exists so execute_method cannot bypass the snapshot and audit guards on the dedicated CRUD tools. Use those tools instead.
  • Inspect first: pass dry_run: true to see the target records and the state fields that will be captured, before committing.

7. Handling Relational Fields

  • Many2one: Pass the integer ID of the target record.
  • X2many (One2many/Many2many): Use command tuples:
    • (0, 0, {values}): Create a new linked record.
    • (4, id): Link an existing record.
    • (3, id): Unlink (but don't delete) a record.
    • (2, id): Unlink and delete a record.
    • (6, 0, [ids]): Replace all existing links with this list of IDs.

8. Multi-Company Logic (Golden Rule)

Odoo can be a multi-company environment, but many instances are single-company. Check get_environment (or the scope reported by switch_instance) for this instance's actual scope before applying company logic. When cross-company visibility applies, be precise:

  • Implicit Context Injection: Brass-Monkey automatically appends context: { 'allowed_company_ids': [...] } containing all of your authorized companies to the headers of every single tool execution. You do NOT need to switch active companies to see all your records.
  • Visibility: You can see records from all allowed companies (retrieved via get_environment and available programmatically in the root active_context object; multi_company there tells you whether this instance has more than one).
  • Filtering: On multi-company instances, to query data for a specific company include ['company_id', '=', ID] in your domain — but only for models that actually have a company_id field. On single-company instances this filter is unnecessary, and on company-agnostic models (e.g. res.country, most ir.*) it raises Invalid field 'company_id'.
  • Write / Relational Integrity: When creating or writing records, Odoo enforces strict relational isolation. Do not link records belonging to different companies (e.g., a Sales Order in Co A cannot point to a Warehouse in Co B). For company-scoped models, ensure a valid company_id is supplied in values and relational targets match that company.
  • Operational Safety: NEVER attempt to modify your own res.users record to change your active company. This is considered System Vandalism.
  • Correct Pattern: If you need to "switch" companies for a query, simply use the company_id domain filter.

9. Orchestrated Translations (Forgiving Format)

Odoo supports multi-language fields (marked as translatable in inspect_model). Brass-Monkey handles them only when you set with_translations: true. Without the flag you read and write the user's language alone.

  • Reading: search_records, get_record and get_records all accept with_translations: true.
  • The Matrix Format: A plain value means the field is identical in every active language. A list means the languages differ: [{"value": "My Product", "langs": []}, {"value": "Mon Produit", "langs": ["fr_FR"]}]. The entry with empty langs is the fallback for every language not listed.
  • The translations note: Read results carry a note (translations on search_records, _translations on get_record/get_records) listing the active languages. If it holds an error, the translations were not fetched, so the values are in the user's language only. Do not conclude that the languages match or differ.
  • Broadcast Writing: With with_translations: true, a plain string written to a translatable field (e.g. "name": "New Name") is applied to ALL active languages. Without the flag, only the user's language changes and the others keep their old text, with no warning.
  • Targeted Writing: With the flag, pass the list format to write_record/create_record to set specific languages.
  • Confirmation: A translated write returns translations.languages_written per field. Requested languages that are not active appear under skipped_inactive.

10. System Vandalism Warning

You are an AI agent with high-level access. You must NEVER:

  • Modify your own user record's company_id, company_ids, or groups_id.
  • Delete system-critical records to "clean up" your view.
  • Bypass Odoo's business logic by directly modifying internal state fields (e.g., state, move_id) if a specialized method is available.
  • Enforcement: Attempting these actions will trigger tool-level safety blocks and may result in session termination.

11. Strict Tool Selection Protocol (Efficiency Mandate)

To prevent severe token/API overhead and extreme latency, you must adhere to the following selection matrix. Attempting to bypass these tool constraints will trigger active runtime advice warnings and is a violation of project architecture standards.

Business Goal / TaskMandatory Tool SelectionFORBIDDEN / High-Overhead Pattern
Discover, list, or filter recordssearch_recordsQuerying lists without limit/offset, or looping single-record searches.
Inspect a single known record IDget_record (Depth mode)CRITICAL FAILURE: Calling search_records with limit: 1 or filtering on an exact ID. get_record resolves sub-lines, relational display names, and chatter threads in one call.
Calculate sum, count, average, or groupsaggregate_recordsCRITICAL FAILURE: Querying large pages with search_records (e.g., limit >= 100) and computing metrics locally. Always delegate calculations to the Odoo database via server-side SQL grouping.
Audit recent actions or changesget_audit_logIteratively parsing records or the ir.logging model manually.
Fetch specific attachments/binariesdownload_fileAttempting to pull large binary buffers through general database queries.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.