Skip to content

Automations

Automations is the perfect tool when you want something to happen automatically. Automations requires no coding and are created in a visual point-and-click tool.

Examples of Automations:

  • Create a "status change" when a deal is closed.
  • Send notifications upon work order assignment.
  • Enroll a lead into an automated flow upon creation.
  • Record a timestamp when a ticket is closed.

These can be conceptualized as "WHEN an event occurs, THEN execute the following actions." Automations break down these processes into triggers and steps:

WHEN: [Trigger occurs]
THEN: [Execute Step1], [Execute Step2], [Execute Step3], ...

The steps are picked from a list of available steps, which we call The Step Library. This library covers the most common needs such as creating and updating objects. For more complex Automations, multiple steps may be necessary.

To refine execution, steps can include prerequisite conditions, akin to if-statements, ensuring that only relevant actions are taken:

WHEN: [Trigger occurs]
THEN: IF [condition1] { Execute Step1 }, IF [condition2] { Execute Step2 }, IF [condition3] { Execute Step3 }, ...

Getting started:

Go to Lime Admin > System > Automations.

There you will find:

  • A visual automation builder
  • Logs from all previously run Automations

Triggers

Triggers define the WHEN part of an Automation. Triggers fire when a lime object is being created or updated — applicable to various scenarios such as winning a deal, closing a ticket, or creating a lead.

when created or updated

Automations with this trigger happen when saving changes. If an automation fails it will prevent the entire save from going through.

This trigger will only run automations for those lime objects that were in the original save. This means lime objects created or updated in an automation will not trigger automations for those other objects!

For example, let's say we have two automations:

  • WHEN a deal is closed and the associated company isn't a customer THEN update associated company to be a customer
  • WHEN a company becomes a customer THEN send an email to the billing department

Then if a user closes a deal the company will become a customer but there will be no email sent.

after created or updated

This trigger is enabled by turning on the Run in background toggle in the automation editor. The trigger label in the automations list then changes from when ... to after ... (e.g. Sale/Project: after updated).

Background automations are primarily used for AI agent steps, where running them inline would delay the user's save.

How it works:

  • The automation's pre-condition is evaluated as part of the save, inside the unit of work. If it doesn't match, the automation is not dispatched.
  • If the pre-condition matches, the automation is dispatched to run in a background task after the save has committed.
  • The automation's steps are evaluated later, against the current database state.

Things to keep in mind:

  • A failure in a step will not prevent the save from going through, since the save has already committed by the time the steps run.
  • Step-level conditions that rely on the save-time state — such as has changed — will not behave the same as in a synchronous automation. By the time the steps run, that transient information is no longer available.
  • Background automations appear twice in the automation runs log: once when they are dispatched during the save, and once when they actually run in the background.

Step Library

The THEN part of an Automation consists of various steps available in the Step Library. These include creating new lime objects, calculating formulas, and updating fields.

The steps described below are the built-in ones. Optional packages can add additional steps — for example Start Email Conversation (from the Email Integration package) or Send a transactional email (from the Transactional Message Library) — so the exact list of steps available in your application depends on which packages are installed.

Create new

This step creates new lime objects, for example status change, history or participant. This is used for cases such as "When a Deal changes status, create a Status Change Note about this" or "When a Lead is created, add this Lead as a Participant to a specific Automated Flow"

Update fields

This step updates one or more fields on a lime object. Typical use cases are "When a Deal is won or lost, set the Deal's Closed/Won Date to Today's date" or "When a Deal is updated, calculate the Weighted Value and save it to the field Weighted value."

Get lime object

This step loads a lime object for a given lime type and record ID and provides it as output from the step. This object can then be used later on in the automation. For example load the object "Invoice question" and then use its output to Set the ticket type on the ticket to "Invoice Question"

Get sequence number

This step fetches the next number from a sequence defined in Lime Admin > System > Sequences. It is typically used to assign a running number to things like tickets, quotes or projects — optionally combined with a Formula step to add a prefix or padding before the value is saved to a field.

See Sequences for details on defining sequences and combining them with prefixes.

Run AI Agent

This step runs a configured AI agent, passing in the triggering lime object (or another object) as input. The agent is picked from a dropdown of agents defined in Lime Admin > AI Agents > Agent, and the required inputs depend on the selected agent.

Each agent also produces its own set of outputs, which can be referenced in subsequent steps — for example to write an agent's result into a field via an Update fields step, or to use it inside a Formula.

This step is only available in background automations, since AI agents typically take too long to run inline without delaying the user's save.

Formula

This step offers a kind of script language called Jinja. It can be used to for example format phone numbers, capitalize strings or do arithmetics. At first glance Jinja can be daunting but most users will only need to learn a subset.

The lime object that triggers the automation is available as the variable event.limeobject and the formatting-filters found in Document Templates can also be used here.

Examples:

  • Concatenate firstname and lastname when updating a coworker:

    {{event.limeobject.firstname}} {{event.limeobject.lastname}}
    
  • Get tomorrow's date:

    {{context.today | add_days(1)}}
    
  • Compute the weighted value of a deal:

    {{event.limeobject.value * event.limeobject.probability}}
    
  • Format a phone number:

    {% for letter in event.limeobject.mobilephone %}{% if letter in '+0123456789' %}{{letter}}{% endif %}{% endfor %}
    
  • Create a good note (in markdown) to be used in a status change note when closing a Deal:

    {{context.active_user.name}} closed deal **{{event.limeobject.name}}**
    on company {{event.limeobject.company.name}} for 
    **{{event.limeobject.value | format_number(locale="sv_SE", decimal_places=2)}} SEK**.
    

Refer to the Document Templates' documentation and the official Jinja documentation for more filter examples.

Sample automations

To use one of the examples in your own application follow these steps:

  1. Copy the json from one of the examples below (there is a copy button).
  2. Go to Lime Admin > System > Automations.
  3. Click the "+ automation" button.
  4. Switch to "code editor".
  5. Paste in the json.
  6. Switch back from "code editor".

Use this to create a history note when a company becomes a customer.

Create history when company becomes customer
{
  "id": "fdf0b870-6df2-4241-842a-a80d5fbf5c47",
  "title": "Company: New Customer",
  "active": true,
  "steps": [
    {
      "id": "step1",
      "title": "Create history for new customer",
      "action": "create_limeobject",
      "arguments": {
        "limetype": {
          "exp_type": "constant",
          "value": "history"
        },
        "properties": {
          "exp_type": "map",
          "items": [
            {
              "key": {
                "exp_type": "constant",
                "value": "note"
              },
              "value": {
                "exp_type": "constant",
                "value": "Became a customer!"
              }
            },
            {
              "key": {
                "exp_type": "constant",
                "value": "type"
              },
              "value": {
                "exp_type": "constant",
                "value": "comment"
              }
            },
            {
              "key": {
                "exp_type": "constant",
                "value": "company"
              },
              "value": {
                "exp_type": "context",
                "key": "event.limeobject"
              }
            },
            {
              "key": {
                "exp_type": "constant",
                "value": "coworker"
              },
              "value": {
                "exp_type": "context",
                "key": "context.active_user"
              }
            }
          ]
        }
      },
      "condition": {
        "exp_type": "and",
        "expressions": [
          {
            "exp_type": "or",
            "expressions": [
              {
                "exp_type": "has_changed",
                "limeobject": {
                  "exp_type": "context",
                  "key": "event.limeobject"
                },
                "property_name": {
                  "exp_type": "constant",
                  "value": "buyingstatus"
                }
              }
            ]
          },
          {
            "exp_type": "or",
            "expressions": [
              {
                "exp_type": "equals",
                "left": {
                  "exp_type": "context",
                  "key": "event.limeobject.buyingstatus.key"
                },
                "right": {
                  "exp_type": "constant",
                  "value": "active"
                }
              }
            ]
          }
        ]
      }
    }
  ],
  "trigger": {
    "limeType": "company",
    "triggerType": "limeobject",
    "onUpdate": true,
    "onCreate": true
  }
}

Use this automation to timestamp when a deal is won or lost.

Deal order/lost date
{
  "id": "eb844c9d-76f2-4c51-809a-3a8315faf550",
  "title": "Deal: Order/lost date",
  "active": true,
  "steps": [
    {
      "id": "step1",
      "title": "Set order/lost date",
      "action": "update_limeobject",
      "arguments": {
        "limeobject": {
          "exp_type": "context",
          "key": "event.limeobject"
        },
        "properties": {
          "exp_type": "map",
          "items": [
            {
              "key": {
                "exp_type": "constant",
                "value": "closeddate"
              },
              "value": {
                "exp_type": "context",
                "key": "context.now"
              }
            }
          ]
        }
      },
      "condition": {
        "exp_type": "and",
        "expressions": [
          {
            "exp_type": "or",
            "expressions": [
              {
                "exp_type": "is_empty",
                "expression": {
                  "exp_type": "context",
                  "key": "event.limeobject.closeddate"
                }
              }
            ]
          },
          {
            "exp_type": "or",
            "expressions": [
              {
                "exp_type": "equals",
                "left": {
                  "exp_type": "context",
                  "key": "event.limeobject.dealstatus.key"
                },
                "right": {
                  "exp_type": "constant",
                  "value": "agreement"
                }
              },
              {
                "exp_type": "equals",
                "left": {
                  "exp_type": "context",
                  "key": "event.limeobject.dealstatus.key"
                },
                "right": {
                  "exp_type": "constant",
                  "value": "rejection"
                }
              }
            ]
          }
        ]
      }
    }
  ],
  "trigger": {
    "limeType": "deal",
    "triggerType": "limeobject",
    "onUpdate": true,
    "onCreate": true
  }
}

Use this automation to calculate the weighted value on a deal.

The weighted value is the potential deal value multiplied with the probability of closing the deal.

Weighted value on deal
{
  "id": "ef8aa034-04bf-4d4c-aff3-247439695260",
  "title": "Deal: Weighted Value",
  "active": true,
  "steps": [
    {
      "id": "step1",
      "title": "If lost, probability is 0%",
      "action": "update_limeobject",
      "arguments": {
        "limeobject": {
          "exp_type": "context",
          "key": "event.limeobject"
        },
        "properties": {
          "exp_type": "map",
          "items": [
            {
              "key": {
                "exp_type": "constant",
                "value": "probability"
              },
              "value": {
                "exp_type": "constant",
                "value": 0
              }
            }
          ]
        }
      },
      "condition": {
        "expressions": [
          {
            "expressions": [
              {
                "left": {
                  "key": "event.limeobject.dealstatus.key",
                  "fallback": null,
                  "exp_type": "context"
                },
                "right": {
                  "value": "rejection",
                  "exp_type": "constant"
                },
                "exp_type": "equals"
              }
            ],
            "exp_type": "or"
          }
        ],
        "exp_type": "and"
      }
    },
    {
      "id": "step2",
      "title": "If won, probability is 100%",
      "action": "update_limeobject",
      "arguments": {
        "limeobject": {
          "exp_type": "context",
          "key": "event.limeobject"
        },
        "properties": {
          "exp_type": "map",
          "items": [
            {
              "key": {
                "exp_type": "constant",
                "value": "probability"
              },
              "value": {
                "exp_type": "constant",
                "value": 1
              }
            }
          ]
        }
      },
      "condition": {
        "expressions": [
          {
            "expressions": [
              {
                "left": {
                  "key": "event.limeobject.dealstatus.key",
                  "fallback": null,
                  "exp_type": "context"
                },
                "right": {
                  "value": "agreement",
                  "exp_type": "constant"
                },
                "exp_type": "equals"
              }
            ],
            "exp_type": "or"
          }
        ],
        "exp_type": "and"
      }
    },
    {
      "id": "step3",
      "title": "Calculate weighted value",
      "action": "formula",
      "arguments": {
        "template": {
          "value": "{{event.limeobject.value*event.limeobject.probability}}",
          "exp_type": "constant"
        }
      },
      "condition": null
    },
    {
      "id": "step4",
      "title": "Update deal with the new weighted value",
      "action": "update_limeobject",
      "arguments": {
        "limeobject": {
          "exp_type": "context",
          "key": "event.limeobject"
        },
        "properties": {
          "exp_type": "map",
          "items": [
            {
              "key": {
                "exp_type": "constant",
                "value": "weightedvalue"
              },
              "value": {
                "exp_type": "context",
                "key": "steps.step3.output.value"
              }
            }
          ]
        }
      },
      "condition": null
    }
  ],
  "trigger": {
    "limeType": "deal",
    "triggerType": "limeobject",
    "onUpdate": true,
    "onCreate": true
  }
}

Creates a history note of all protocol answers when a work order is closed.

This example requires the lime types from the Work Order addon.

Summarize work order protocols
{
  "id": "1e2c54c3-e848-490b-933f-4b6f5a6196cc",
  "title": "Work Order: Protocol Summary",
  "active": true,
  "steps": [
    {
      "id": "step1",
      "title": "Summarize protocols",
      "action": "formula",
      "arguments": {
        "template": {
          "value": "{% for form in event.limeobject.limepkg_form_protocol -%}\nšŸ“„ **{{form.title}}**:\n{% for answer in form.limepkg_form_answer -%}\n* {{answer.title}}: {{answer.answer}}{% if answer.comment != \"\"%} - *{{answer.comment}}*{%endif%}\n{% endfor %}\n\n{% endfor -%}",
          "exp_type": "constant"
        }
      },
      "condition": {
        "exp_type": "and",
        "expressions": [
          {
            "limeobject": {
              "key": "event.limeobject",
              "fallback": null,
              "exp_type": "context"
            },
            "property_name": {
              "value": "state",
              "exp_type": "constant"
            },
            "exp_type": "has_changed"
          },
          {
            "left": {
              "key": "event.limeobject.state.key",
              "fallback": null,
              "exp_type": "context"
            },
            "right": {
              "value": "Finished",
              "exp_type": "constant"
            },
            "exp_type": "equals"
          }
        ]
      }
    },
    {
      "id": "step2",
      "title": "Create protocol summary as history note",
      "action": "create_limeobject",
      "arguments": {
        "limetype": {
          "value": "history",
          "exp_type": "constant"
        },
        "properties": {
          "exp_type": "map",
          "items": [
            {
              "key": {
                "value": "note",
                "exp_type": "constant"
              },
              "value": {
                "key": "steps.step1.output.value",
                "fallback": null,
                "exp_type": "context"
              }
            },
            {
              "key": {
                "value": "workorder",
                "exp_type": "constant"
              },
              "value": {
                "key": "event.limeobject",
                "fallback": null,
                "exp_type": "context"
              }
            },
            {
              "key": {
                "value": "helpdesk",
                "exp_type": "constant"
              },
              "value": {
                "key": "event.limeobject.helpdesk",
                "fallback": null,
                "exp_type": "context"
              }
            },
            {
              "key": {
                "value": "type",
                "exp_type": "constant"
              },
              "value": {
                "value": "comment",
                "exp_type": "constant"
              }
            },
            {
              "key": {
                "exp_type": "constant",
                "value": "coworker"
              },
              "value": {
                "exp_type": "context",
                "key": "context.active_user"
              }
            }
          ]
        }
      },
      "condition": {
        "expressions": [
          {
            "limeobject": {
              "key": "event.limeobject",
              "fallback": null,
              "exp_type": "context"
            },
            "property_name": {
              "value": "state",
              "exp_type": "constant"
            },
            "exp_type": "has_changed"
          },
          {
            "left": {
              "key": "event.limeobject.state.key",
              "fallback": null,
              "exp_type": "context"
            },
            "right": {
              "value": "Finished",
              "exp_type": "constant"
            },
            "exp_type": "equals"
          },
          {
            "expression": {
              "key": "steps.step1.output.value",
              "fallback": null,
              "exp_type": "context"
            },
            "exp_type": "is_not_empty"
          }
        ],
        "exp_type": "and"
      }
    }
  ],
  "trigger": {
    "limeType": "workorder",
    "triggerType": "limeobject",
    "onUpdate": true,
    "onCreate": false
  }
}

FAQ

How fast are automations?

Automations have the same performance impact as you would expect from naive custom lime objects.

Can I create my own custom steps?

There is currently no support for custom steps.

Can I create my own custom triggers?

There is currently no support for custom triggers.

How do I move an automation from test to prod?

Automations can be copy-pasted with ease using the "code editor".

How long are automation runs stored?

The automation runs are stored for 7 days. The cleanup is done by lsp_cleanupdb on a nightly schedule.

Can I combine custom limeobjects with automations?

There are several ways to customize what happens when something is saved in the system. The following sequence describes how the automation trigger inside the unit of work interacts with those other customization capabilities during saves:

  • When uow.commit() is called:
    1. prepare_update() is called for all custom lime objects in the uow. Any lime objects added to the uow in this step can trigger automations in the next step.
    2. Automations are triggered for all lime objects in the uow. Any lime objects added to the uow in this step will not trigger automations, but may trigger before_update in the next step.
    3. before_update() is called for all custom lime objects in the uow. Any lime objects added to the uow in this step will not trigger any automations.
    4. SQL on UPDATE
    5. after_update() is called for all custom lime objects in the uow.

Troubleshooting

When automation runs it fails with a Failed to evaluate condition error message

This error means that the system couldn't evaluate a condition in the when part of the automation. It often occurs when the values involved are either missing or not compatible.

If the error includes a message like:
'<' not supported between instances of 'NoneType' and 'datetime.datetime'
it indicates that the values being compared are of different or incompatible types (e.g., trying to compare an empty value with a date).

Common causes:

  • Missing value: One of the values used in the condition is empty or not set. For example, a lime object property expected to have a value is blank.
  • Type mismatch: The values used in the comparison are of different types. For instance, a condition compares a number to a text value, or a date to a blank field.

To resolve the issue, double-check the values used in the condition:

  • Ensure all required values are populated by marking the relevant lime type properties as required.
  • Confirm that the types of the values being compared match (e.g., date with date, number with number).