{"section":"tutorials","requestedLocale":"en","requestedSlug":"create-cx-automations","locale":"en","slug":"create-cx-automations","path":"docs/en/tutorials/storefront/agentic-cx/create-cx-automations.md","branch":"main","content":"## Overview\n\nAutomations are designed to act proactively based on predefined rules and conditions. Unlike passive agents, which only react to user interactions, automations can initiate actions or communications when certain criteria are met, often triggered by changes in data or system events. The command to deploy an automation is: `weni project push agent_definition.yaml`.\n\n## Basic concepts and YAML structure\n\nAn automation is defined in an `agent_definition.yaml` file. The main fields are:\n\n- **agents.<agent_id>**: Identifies the agent.\n- **name**: The agent's display name, with a 55-character limit.\n- **description**: A description of the agent's purpose and capabilities.\n- **rules**: A dictionary of rules that trigger the agent's actions.\n- Inside **rules.<rule_id>**:\n  - **display_name**: The readable name of the rule.\n  - **template**: The Highly Structured Message (HSM) template to use.\n  - **start_condition**: A description of the condition that must be met to trigger the rule.\n  - **source**: Defines the code to run when the rule is triggered, with `entrypoint` pointing to the class/method and `path` to the directory where the code is located.\n- **pre_processing**: Defines a preprocessing step to prepare data before evaluating the rules, with `source` specifying the code and `result_examples_file` pointing to a JSON file with output examples.\n\nThe `result_example.json` file must be an array of objects. Each object contains:\n\n- `urn`: The contact's unique identifier (for example, a phone number or user ID).\n- `data`: A dictionary with the data relevant to the rule. The structure of this dictionary depends on the information your agent needs to process.\n\n## Project structure\n\nAn automation follows a clear folder structure.\n\n```\nyour-project-name/\n├── rules/\n│   ├── status_aprovado/\n│   │   ├── main.py\n│   │   └── requirements.txt\n│   └── status_invoiced/\n│       ├── main.py\n│       └── requirements.txt\n├── pre_processors/\n│   └── processor/\n│       ├── processing.py\n│       └── requirements.txt\n├── agent_definition.yaml\n└── result_example.json\n```\n\nThis structure helps organize the different parts of the agent. The `rules/` folder contains the rules separated by status, each with its own `main.py` and `requirements.txt`. The `pre_processors/processor` folder contains the preprocessing code and its `requirements.txt`, while the `agent_definition.yaml` and `result_example.json` files are stored in the root directory.\n\n## YAML definition example\n\nBelow is an example of an `agent_definition.yaml` file with an agent called `active_order_status` that manages order statuses:\n\n```yaml\nagents:\n  active_order_status:\n    name: \"Active Order Status\"\n    description: \"Agent that triggers status templates of orders, based on the status received from VTEX - Order Status\"\n    language: \"pt_BR\"\n    rules:\n      PaymentApproved:\n        display_name: \"Payment Approved\"\n        template: \"payment_confirmation_2\"\n        start_condition: \"When the status is Payment Approved\"\n        source:\n          entrypoint: \"main.PaymentApproved\"\n          path: \"rules/status_payment_approved\"\n      OrderInvoiced:\n        display_name: \"Order Invoiced\"\n        template: \"order_update_no_cta_1\"\n        start_condition: \"When the status is Invoiced\"\n        source:\n          entrypoint: \"main.StatusInvoiced\"\n          path: \"rules/status_invoiced\"\n      OrderCanceled:\n        display_name: \"Order Canceled\"\n        template: \"order_canceled_3\"\n        start_condition: \"When the status is Canceled\"\n        source:\n          entrypoint: \"main.Canceled\"\n          path: \"rules/status_canceled\"\n      OrderCreated:\n        display_name: \"Order Created\"\n        template: \"order_management_no_cta_5\"\n        start_condition: \"When the status is Order Created\"\n        source:\n          entrypoint: \"main.OrderCreated\"\n          path: \"rules/status_order_created\"\n    pre_processing:\n      source:\n        entrypoint: \"processing.PreProcessor\"\n        path: \"pre_processors/processor\"\n      result_examples_file: \"result_example.json\"\n```\n\nThis file defines four rules linked to different order statuses. For each rule, the display name, associated HSM template, start condition, and path to the Python code to be executed are configured. The `pre_processing` block specifies the class and directory to use for preparing the data before evaluating the rules.\n\n## Preprocessing\n\nThe preprocessing step gathers all the data needed by the rules. Only at this stage can HTTP requests or other external calls be made; for this reason, there's a single `requirements.txt` file in `pre_processors`. The `PreProcessorContext` object contains the webhook payload and project information. Webhook data is accessed with `context.payload.get(\"field\")`. For example, to get the `orderId` in a payload like the one below, use `context.payload.get(\"orderId\")`.\n\n```json\n{\n    \"recorder\": {\n        \"_record\": {\n            \"x-vtex-meta\": {},\n            \"x-vtex-meta-bucket\": {}\n        }\n    },\n    \"domain\": \"Marketplace\",\n    \"orderId\": \"1544102600592-01\",\n    \"currentState\": \"payment-approved\",\n    \"lastState\": \"canceled\",\n    \"currentChangeDate\": \"2025-02-07T13:54:54.7438532Z\",\n    \"lastChangeDate\": \"2025-02-07T13:54:54.6657558Z\",\n    \"vtexAccount\": \"leoamaral\"\n}\n```\n\nIn addition to accessing payload fields, you can get project information such as the identifier (uuid) and the VTEX account through `context.project.get(\"uuid\")` and `context.project.get(\"vtex_account\")`. The preprocessor's process method must return a `ProcessedData` object, consisting of a `urn` (contact identifier) and a dictionary containing the data to be passed to the rules. The `urn` must follow the `whatsapp:5582900000000` pattern.\n\nBelow is a simplified example of a preprocessor:\n\n```python\nfrom weni.context.preprocessor_context import PreProcessorContext\nfrom weni.preprocessor import PreProcessor as BasePreProcessor, ProcessedData\n\nclass PreProcessor(BasePreProcessor):\n    def process(self, context: PreProcessorContext) -> ProcessedData:\n        # Obter dados do webhook\n        order_id = context.payload.get(\"orderId\", \"\")\n        phone_number = context.payload.get(\"phone_number\", \"\")\n        state = context.payload.get(\"currentState\", \"\")\n\n        # Obter dados do projeto\n        project_id = context.project.get(\"uuid\")\n        vtex_account = context.project.get(\"vtex_account\")\n\n        # Lógica de negócio (chamadas externas podem ser feitas aqui)\n        # ...\n\n        # Retornar o contato e dados para as regras\n        urn = f\"whatsapp:{phone_number}\"\n        return ProcessedData(urn, {\"orderId\": order_id, \"status\": state})\n```\n\n## Rule implementation: PaymentApproved\n\nEach agent rule is implemented as a class that inherits from `Rule`. The `execute` function checks whether the condition is met and returns `True` if the message should be sent. The `get_template_variables` function builds a dictionary with the template variables. Below is the implementation of the `PaymentApproved` rule:\n\n```python\nfrom weni.preprocessor import ProcessedData\nfrom weni.rules import Rule\n\nclass PaymentApproved(Rule):\n    def execute(self, data: ProcessedData) -> bool:\n        status = data.data.get(\"status\")\n        # Verifica se o status recebido no pré-processamento é 'payment-approved'\n        return status == \"payment-approved\"\n\n    def get_template_variables(self, data: ProcessedData) -> dict:\n        name = data.data.get(\"name\")\n        price = int(data.data.get(\"price\", 0))\n        order_id = data.data.get(\"orderId\")\n        # Retorna variáveis na ordem do template HSM\n        return {\"1\": f\"R$ {price / 100}\", \"2\": order_id}\n```\n\n## Using templates (HSM)\n\nMessage templates (HSM) registered in WhatsApp Business can contain placeholders such as `{{1}}`, `{{2}}`, and so on. When `execute` returns `True`, the VTEX CX Platform (Weni) CLI calls `get_template_variables` to complete these variables. For example, considering a template such as `Hello {{1}}, your order {{2}} is now in {{3}} stage`, the function must return:\n\n```json\n{\"1\": \"Leonard\", \"2\": \"12345\", \"3\": \"Delivery\"}\n```\n\n## Rule execution logic and use cases\n\nAfter preprocessing, the agent follows the rules defined in the YAML file in order. The first rule whose `execute` method returns `True` will be executed, and the others will be ignored. Therefore, it's important to organize the rules hierarchically and make sure that preprocessing returns sufficient data for the conditions of each rule. Common use cases include order notifications (approved, invoiced, canceled, created), but you can create rules for any relevant event within VTEX or your business flow.\n\n## Conclusion\n\nAutomations allow you to automate notifications and interactions with your customers based on VTEX events. By structuring your project following this guide — clearly defining the YAML, pre-processing, and rules — you ensure a secure, scalable integration that informs your customers at the right time.\n\n> [Here](https://github.com/weni-ai/weni-example-agents) you can find an example of automation code."}