Skip to content

Automations

An automation (Maitento’s API calls it an automated action) says “when this happens, start that”. The trigger can be:

  • a schedule, such as every weekday at 07:00;
  • a run changing, such as when an interaction finishes with a certain answer.

What it starts can be an interaction, an app, a capsule or a code pipeline. It can also post a message into a running interaction.

See it in tutorial 17, On a schedule, which runs tutorial 16’s taglines app every morning, triggers it by hand, and reads its history.

An automation has one or more actions (what to start) plus its triggers. This one starts the taglines app every morning:

const app = await mt.apps.getByName("taglines");
const daily = await mt.automations.create({
name: "daily-taglines",
actions: [{ name: "write-taglines", config: { $type: "app", version: { id: app.id, version: 1 },
inputs: [{ name: "product", value: "a bamboo coffee cup" }] } }],
});
await mt.automations.addSchedule(daily.id, { name: "every-morning", minute: "0", hour: "7" });

Run it once now, to test it, with trigger:

const { processId } = await mt.automations.trigger(daily.id);

Every run it starts is listed in its history, newest first: what started it (Schedule, Message or Manual), the run’s id, the outcome and, when it failed, why. Read it with automations.history, mt action-history, or the automation’s History in the portal. The history keeps the newest 50 entries.

When nothing could be started, trigger fails with api:automations:start-failed and says why, followed by the cause’s own code (api:apps:input-missing for an app started without one of its inputs, for example). It never answers with an empty process id.

An action pins a version. An app, interaction or capsule action names the version it starts (version: { id, version }), and keeps starting that version after you deploy a new one. Update the automation to move it on: tutorial 17’s script looks up the app’s latest version each time it runs. A codepipeline action names the pipeline instead, and an interaction-message action names the run it posts to.

A schedule is a cron expression split into fields: minute, hour, dayOfMonth, month, dayOfWeek, and an optional second. Any field you leave out means “every”. Times are UTC.

Each schedule’s nextOccurrence says when it fires next, and the automation’s nextScheduledRunAt is the soonest of them. Both are up to date in the response to the call that adds, changes, removes or switches a schedule, and move on after every scheduled run.

You wantFields
Every day at 07:00 UTCminute: "0", hour: "7"
Weekdays at 09:30 UTCminute: "30", hour: "9", dayOfWeek: "1-5"
Every 15 minutesminute: "*/15"

A message trigger starts the automation when a run changes and matches a filter. The filter is a JSONPath over the change, for example “an interaction finished with priority P1”:

$..[?(@.item.interaction.id == '<interaction id>' && @.item.status == 5 && @.item.output =~ /"priority":"P1"/)]
  • An app action gives every input. All of an app’s inputs are required, so saving an action that leaves one out is refused with api:automations:app-input-missing, naming the input.
  • The $type must come first in an action’s config: app, interaction, interaction-message, capsule or codepipeline.
  • Runs start as the person who created the automation. They pay for models like any other run: on the credential stack their definition, namespace or tenant names, or else on your model keys.
  • An action can choose the credential stack its runs use: credentialStack (the stack’s id or name) in an app or interaction action’s config, or in a codepipeline action’s request. Saving an action that names a stack you haven’t got is refused with api:credential-stacks:unknown.
  • Filters see statuses as numbers. For example, 5 is Finished.
  • A trigger with no filter fires on every change, which includes the runs it starts itself. Always filter.