Automations in your App
What an action is
An action is a piece of your own code that your App runs for you, separately from the page your visitors look at. The page asks for something and the action does it — check a coupon code, total up yesterday's orders, resize an uploaded photo, send a reminder.
The reason to move work into an action rather than write it into the page is trust. Anything written into the page is visible to anyone who opens your App, so it can never hold a password, an API key, or a rule you don't want copied. An action can, because your visitors never see it — they only see what it gives back.
Each action has a short name you choose and returns a result to whatever asked for it.
Where automations live
Open your App in the editor, choose the Equip tab, then Automations. The page has four parts:
- Actions — every action you've written, each with how it runs, its language, who can run it, how its latest run went, and icons to switch it on or off, test it, copy the call to it, edit it and delete it. The Code icon at the top opens ready-to-copy calls for every kind of action.
- Schedules — which actions run on a clock, and when.
- Included — what every action gets without setting anything up: Signing and a Cache, free, within a daily limit.
- History — every run of every action, and whether it was your Draft or your Live App that ran it.
Actions belong to your Draft, so you can add, test and edit them before you ever publish. Only schedules wait: they run on your Live App, so until your first publish their add button opens Publish first.
Messages on the same tab has its own Automatic rules, which are a different and simpler thing: each sends one of your saved emails when something happens, with no code involved. The actions on this page run code you wrote.
Choose what your code needs, not where it runs
When you write an action you pick how it Runs. The choice says what your code needs — MotherFluxer works out where to run it from that. You never choose a machine.
- Instant — the app waits for the answer. Use it for anything a visitor is waiting on: validating a form, checking a code, looking a record up. Written in JavaScript.
- Background — runs later, and the answer lands in History. Use it for work that takes real time: crunching data, machine learning, a report, anything on a schedule. Pick the Language: Python, Go, Rust, Java, C++, Bash or SQL.
- Background, self-contained — the same, with your App's saved data and keys deliberately out of reach.
- Webhook — an outside service calls it. Nothing in your App calls it; you give another service its address, and that service fires it when something happens over there — a payment cleared, a form was submitted, a parcel shipped. Same choice of languages as Background.
- Webhook, self-contained — an outside service calls it, and it uses nothing from your App.
- On device — runs on the visitor's own device: instant, free, and with nothing from your App. Written in Python or SQL.
The window's By mode line sums up the language rules: Instant · JavaScript only, Others · no JavaScript, and SQL · input only — an SQL action transforms the input it is given and nothing else.
Self-contained and on-device are the same promise, made for different reasons. Code in any of them can reach none of your App's saved information, none of your keys and none of your outside connections — so none of the keys your App declares is handed to one. A self-contained action in Python or SQL has only one home, the visitor's device, so it is offered as On device; the other self-contained modes are for the other languages.
The device mode is worth understanding properly: the work happens on your visitor's own machine, so it is immediate, costs you nothing however many people use it, and their data never leaves their device. If your code needs any of your App's own data or keys, pick Instant, Background or Webhook instead.
Write and save an action
In Equip › Automations, select New action (the + icon on Actions). The window asks for:
- Name — a short name like
checkout: letters, numbers and underscores, starting with a letter or an underscore. The editor refuses anything else with Name · letters and numbers, no spaces. - Runs — how it runs, and for the modes that offer a choice, its Language.
- Enabled — leave it on so it can run. Switch it off to keep the code but stop it running.
- Who can run it — who may run it from a page. A new action starts on Only this app.
- Acts as — whose rows it reads and changes when a person calls it.
- The code itself. Starter opens working examples to begin from — Call AI, Save to a list, Handle a webhook and more, matched to the mode and language you picked.
Select Save. The window only offers combinations of mode and language that have somewhere to run, so a saved action never fails later for that reason. If you switch mode or language while the code is still an untouched starter, the starter is swapped for the matching one; once you've written your own code, picking a starter Asks first before replacing it.
The same check runs on actions the building assistant writes for you. An action has to state three things — how it is called, what it is written in, and whether it may use your App's data and keys — and if one is missing or unrecognised, the refusal names that gap rather than something else.
An action goes live the same way the rest of your App does: when you publish. The window marks it Draft only, and saving says Saved to Draft · publish to go live. Your published App keeps running the version you last published, so you can rewrite a payment check or a nightly job and try it without your visitors running the half-finished version.
Choose who can run an action
Nobody can run an action from a page until you say so. Who can run it has three answers:
- Only this app — where every new action starts. Your App's own schedules, webhooks, background work and other actions can run it, and so can your own tests. A call from a page is refused as if the action were switched off.
- Signed-in people — anyone with an account on your App. This needs sign-in turned on in Manage › Users.
- Anyone — anyone on the internet, signed in or not. Nothing stops someone calling it from a script, so choose this only for an action that is safe in a stranger's hands.
An On device action runs in the visitor's own page, so there is nothing to close: it reads Anyone: the page runs it.
Opening an action wider asks first. Let a page run this action? says who you are letting in and, under It reaches, what the action can touch: for a connected service, which one and whether the action reads your private data, sends as you, spends your money, deletes or changes what is stored there. For an action that uses your App, Keys names every key and data link your App declares, since the action can read them all. Open it confirms it, and closing one again never asks.
Choose who an action acts as
Acts as decides whose rows an action reads and changes when a person calls it:
- The person calling — the default. The action has exactly the rights of whoever called it.
- The app — it Reads and changes every row of every list in your App. Use it for work that crosses people, such as a moderator removing someone else's post, and check inside the action that the caller is allowed. It asks first, and an action a stranger can run can't act as the app.
A schedule, a webhook and background work an action queued always act as the app, because no person is calling them. When one adds a record to a list whose records belong to someone, its code has to name that person.
Call an action from your App
Your App's page calls an action you have opened to it by name:
js
const result = await window.mfFn.invoke('checkout', { code: 'SPRING' });An Instant or On device action answers right there, so you can use the result on the next line. A Background action answers at once with the run's id, the work carries on after your page has moved on, and the outcome lands in History. A Webhook action isn't called from your App at all; the outside service you gave its address to fires it.
When an action hands back a page to go to — a Stripe checkout or billing page — send the visitor there with open instead:
js
window.mfFn.open('checkout', { code: 'SPRING' });It runs the action and goes to the page it returns. Call it straight from the button click. Pages like Stripe's checkout won't run inside another page, so when your App is shown inside one — the editor's preview, the community, or someone else's site — the page opens in its own window and your App stays put.
You don't have to type the call from memory. Each action's copy icon copies the exact call to it, and the Code icon on Actions shows the call for an instant action, a background action, and how an outside service calls a webhook.
Give a webhook's address to another service
A Webhook action has an Address, shown in its window once the action has been published, with a copy icon; its row in Actions has a link icon that copies it too. Paste it into the other service. Only you, the App's owner, see the address — a collaborator sees the action but not where it can be called from.
The address is yours to keep. MotherFluxer mints it once, the first time the action is published, and it stays the same through every later publish — so once you have pasted it elsewhere, you never have to change it. It is long and unguessable on purpose, because anyone holding it can fire that action: treat it like a password. To retire it, delete or rename the action.
While your App is unpublished the address still shows, marked Unpublished, but it answers nothing until you publish again.
Run an action on a schedule
In Equip › Automations, select New schedule on Schedules to have an action run on its own clock — a nightly digest, a weekly cleanup, an hourly sync.
Pick the Action, then how often it Repeats — Every minute, Hourly, Daily, Weekly, Monthly, or Custom for a schedule you type yourself — with the Time and Time zone. Once saved, the window shows when it runs Next.
- Schedules run on your Live App only, as Runs on says. A schedule belongs to your Draft like the action it runs, so the window says it Takes effect On publish: a schedule you add or change reaches Live when you next publish — saving says Saved to Draft · publish to go live — and until then Live keeps running the schedule it was last published with. The Next run is Live's own, so the window shows it only while what you see is the schedule Live is running.
- A schedule and its action reach Live together, in the same publish. While your App is unpublished every schedule reads Held until published again.
- Removing a schedule asks first: its Schedule Stops running, and while your Live App runs it, Live Keeps serving until publish — Live keeps firing it until you next publish.
- An action has One each: saving a schedule for an action that already has one replaces it.
- An On device action can't be scheduled — there is no visitor's device to run it on.
- A schedule's row says when it won't fire: Off, Paused when it stopped because it could not run as written, or Action off when its action is switched off.
The outcome of every scheduled run lands in History like any other.
Test an action before your visitors do
In Equip › Automations, select an action's test icon. Type the Input as JSON — for example { "code": "SPRING" } — and select Run.
An instant action shows its result right there. A background one is queued, and the window says so with a button to History, where its outcome lands.
A test runs your Draft's version of the action, against your Draft's own data — a real run rather than a simulation, on the copy you are allowed to break — and its result is marked Draft. An On device action Runs in the Draft preview: the editor asks your running Draft to run it, so you test exactly what a visitor gets. Your published App and its data are untouched until you publish.
See what ran, and what went wrong
History in Equip › Automations records every time an action ran, however it started — called by your App, fired by a schedule, called by an outside service, or started by you with a test.
Each row shows the Action, how the run went (Done, Failed, Denied, Timed out, Paused or Waiting), how long it Took, which App ran it — Draft or Live — and When. Choose All, Live or Draft to show one of them, and use Search to find a run by action name, something in its output, or the text of an error.
Open a run to read it in full: its Result, when it Started, how long it Took, the Processor time it used, how many Writes and outside Calls it made, and its Output and Errors kept apart, so a failure's reason isn't buried in the program's own lines.
This is the first place to look when an action isn't doing what you expect: it tells you whether the action ran at all, and if it did, exactly what it said.
Let an action use a key
An action often needs a credential — an API key for a service you call, a signing secret, a password. You never paste one into the code: a key's value typed into any of your App's files is refused at save.
Add it once as a variable under Variables in Equip › Connect — Add a key, a name such as MAPS_KEY, what it is For, and its Value. The value goes into your account's vault, and the action reads the variable by name:
js
module.exports = async (input, ctx) => {
const resp = await ctx.fetch('https://api.example.com/v1/places', {
method: 'POST',
headers: { Authorization: ctx.env.MAPS_KEY },
body: JSON.stringify({ query: input.place }),
});
return { status: resp.status };
};ctx.env.MAPS_KEY is a sealed handle, not the key: passed as a header to ctx.fetch, it is swapped for the real key on the server at the moment the call runs, so the value never appears in your code, your pages or a log. A plain variable your App declares — a region, a feature switch — reads as its value the same way.
Every action that uses your App can read every variable the App declares; there is no list of keys to keep per action. Reading a name the App doesn't declare stops the action with a message saying where to declare it. A self-contained or on-device action is given no keys at all, by design.
Read a list from another of your Apps
An action can read — and, if you allow it, write — a list that lives in another of your Apps, through a data link. The records stay in the other App, under that list's own rules; nothing is copied.
Set it up in Equip › Connect: Add a key on Variables, choose Data link as the Kind, name the variable (such as ORDERS), pick the list and its Access — Read, or Read and write — and select Link a list. Then pass the variable where a list name would go:
js
module.exports = async (input, ctx) => {
const { rows } = await ctx.data.query({ collection: ctx.env.ORDERS, limit: 20 });
return { orders: rows };
};- Only an action that acts as the App can follow a link — set Acts as to The app. The link reads the whole list as the other App itself does, never on a visitor's behalf.
- It reads the same side: your Draft reads the other App's Draft data, and your Live App reads its Live data.
- Writing needs a read-and-write link —
ctx.data.write(ctx.env.ORDERS, values)on a read-only link is refused. A list that holds people's details can only be linked for reading. - No live updates travel over a link. Only your actions read it; a page can't, and it does not refresh itself when the other App's list changes.
If the link is revoked, or nothing is linked yet, the action's call is refused with a message that the variable is not linked to a list and where to link one. If the other App has no data on that side yet, the call says that instead.
Rename or delete an action
An action's name is what everything calls it by. Rename one in its window and select Save:
- Its schedule moves to the new name in the same save, with nothing to confirm. Like any Draft change, Live keeps running the old name on its old schedule until you publish.
- A webhook action gets a new address under its new name.
- A name another action already has is refused with Name already used.
Deleting an action asks first and says what goes with it. The action, Its schedule (Deleted) and, for a webhook, Its address (Stops) all leave your Draft at once. Where your Live App has the action, Live Keeps serving until publish: it keeps answering the action, its address and its schedule until you next publish.
What actions cost
Every action runs In a sandbox and Within the app’s usage quota — both listed under Runs in the Code window on Actions — rather than being billed one by one, and every run is capped so a mistake — a loop that never ends, a runaway job — can't quietly run up a bill. When the day's allowance is used up, actions pause rather than keep spending; a paused run reads Paused in History, and your Live App's status on Publish says why.
An action that uses your App reaches it through ctx.data, ctx.env, ctx.fetch and ctx.ai, which the same window lists under Can use.
On device actions cost nothing at all, however many people use them, because the work happens on the visitor's machine.
Ask the building assistant to write one
You can describe what you want to the building assistant in plain language — "when someone submits the form, email me a summary" — and it writes the action and the code that calls it. It appears in Equip › Automations exactly as if you had written it, and you can test and edit it the same way. Read Who can run it on anything it wrote for a page to call: the assistant picks the narrowest answer that works, and you can change it.