What you will take away from this lesson
Lesson 607 ended with a scheduled automation that reads a feed in batches and keeps its place. Some work does not want a batch. A return over a few hundred dollars, a supplier application, a delay notice from a carrier: each one is a decision somebody should see while it is still fresh, and waiting for the next fire to sweep it up adds delay for nothing.
This lesson builds the other shape on the demo tenant: an automation that names a source and runs once for each return it stores, checks it against the store’s day, and posts the ones a person should look at.
Learning Objectives
- 01Make an automation run once for each event a source stores, and read the event it was made for.
- 02Read a per-event run in the run history: the trigger, the source, and the event id it was made once for.
- 03Explain what happens on a burst: a bounded queue, the backlog recorded as skipped, and arrival order when runs go one at a time.
- 04State what a failed event run does: it alerts its owner, it is never run again on its own, and the next event still runs.
- 05Choose between one run per event and a scheduled batch.
Where this lesson sits
Lesson 604 named the four triggers and 607 showed where events come from. This lesson takes the third trigger, once per event, and builds an automation around it. The channel it posts to is the one from 608.
600 Series: Automations
- 601Do not spend AI on what a script can doThe automation gap, what integration platforms and laptop scripts each cost, and the division of labor: a script for the deterministic part, the model for writing it and for judgment.
- 602The agent writes the first scriptThe loop from a recorded draft through tests to the save, what a save requires, what validate and a dry run report, the dialect’s deliberate absences, the traps that fail a draft, and the script’s page in the portal.
- 603Outputs: feeds, reports, and dashboards that refresh themselvesOutput identity across runs, tables and documents, the semi-dynamic dashboard and its data region, the referencing pattern, version caps, and delivery to a bucket drop.
- 604Running it: by hand, from the portal, and on a scheduleFour triggers, the cadence builder, the pinned fire date, what a schedule guarantees, and the run history with every trigger, duration, output, and log.
- 605What a run may do, and the record it leavesThe authority a run carries, what a save refuses, why the language cannot reach out, the lifecycle, ownership and transfer, and the administrator’s view.
- 606Scripts as skills: the weekly review the agent runs on your businessThree scripts attached to one prompt, the agent running them and reading the outputs against the knowledge graph, and a weekly list of action items with the figures behind them.
- 607Events in: a webhook source, its table, and an automation that reads itCreating a source, presets for known senders, what a sender is told, the table that serves events from acknowledgement, compaction and retention, the Webhooks page and its alerts, and the two ways an automation reads events.
- 608Results out: notification channels and signed delivery to other systemsChannel kinds and who may send to them, sending from a session and from an automation, the delivery history and the retry rule, the JSON envelope a system routes on, signed requests, and delivery to another deployment.
- 609One run per event: an automation that answers each returnNaming a source, the event a run reads, the run history with each event id, bursts and arrival order, a failed event run that alerts and is not replayed, and when a scheduled batch fits better.
- 610A mailbox as a source: filing the mail other systems sendA mailbox Plexara reads, allowed senders and sender authentication, one row per message and a file per attachment, text marked external, a filing automation, and the limits: no OCR.
- 611When an automation fails at 2 a.m.One incident instead of a message per failure, the recovery message, the operations channel, causes and what is retried within a run, and the agent’s briefing at the next session.
The 600 series picks up the registered table from the 500 series and the prompt mechanics from the 400 series.
What runs on the demo tenant
Four parts, three of them already familiar from 607 and 608. The new one is a source that carries only returns, so that only a return starts a run.
The return check on the demo tenant
The source
pos-returns
- A webhook source an administrator created beside pos-sales. Each request carries a batch of returns, split into one event per return, with the sale id as the event id and the store id as the key. Its sender connection names its token as a stored secret.
The sender
ACME POS sales simulator
- The same simulator 607 follows. After it posts each batch of sales to pos-sales, it posts the batch’s returns, about one in twenty-five sales, to pos-returns.
The automation
acme-pos-return-event-609
- Names pos-returns as its event source and runs one at a time, queued. Each run counts the store’s returns in the 24 hours up to this one and flags the return when it is $250 or more, or the store’s third in a day.
Where a flag goes
ops-events
- The JSON webhook channel from 608, signed by its connection and received by the ops-events source, so a system can route on data.type and a person can read the body.
The script
An event run is an ordinary run with one more input. The agent wrote this script through the same loop as every other in the series, with tests that build the event a run will read.
acme-pos-return-event-609, its main() and handle()
def handle(event):
ret = event["payload"]
if ret.get("event") != "sale.returned":
return {"sale_id": ret.get("sale_id"), "flagged": False, "skipped": "not a return"}
day = store_day(ret, event["received_at"])
reasons = reasons_for(ret, day)
if reasons:
platform.notify(
channel = "ops-events",
title = "Return to review at %s" % ret["store_name"],
body = "Sale %s was returned for $%s (%s). Flagged for %s." % (...),
key = "returns-watch:%s" % ret["store_id"],
data = {"type": "pos.return.flagged", "sale_id": ..., "reasons": reasons},
)
return {"sale_id": ..., "store": ..., "amount": ..., "returns_24h": ...,
"flagged": len(reasons) > 0, "reasons": reasons}
def main():
if run.event == None:
platform.result({"flagged": False, "skipped": "started without an event"})
return
platform.result(handle(run.event))
# store_day counts the store's returns stored in the 24 hours before this
# one, excluding this event id, and adds this one.The run reads its event as run.event: the event id, its type and key as the source read them, when it was received, the source’s name, and the payload. On every other kind of run run.event is None, so the script says so instead of failing when somebody presses Run.
The tests build events the way the source stores them and call handle() directly: a large return, a store’s third return, an ordinary return that posts nothing, an empty count, an event that is not a return, and a run with no event. The save reached all but one statement. Each post carries a key per store, so a store that keeps returning inside the channel’s repeat window is counted, not posted again.
Naming the source
What turns the script into a per-event automation is one setting. It was set with two others in the same call: the source, and one run at a time, queued, so a burst is answered in the order it arrived.
Naming the source
What the agent calls. This is the exchange the agent has with Plexara on your behalf, shown for the technical reader. You ask in plain language; you never type any of it.
manage_script update
name acme-pos-return-event-609
event_source pos-returns
exclusive queue
-> status updated
message Saved, and this version is what runs now: it presents the roles
you held when you saved it, and any schedule fires it.The same setting is on the automation’s page under Events, beside the schedule, and clearing it stops the runs. Naming a source means reading every event it stores, so an administrator may name any source and an owner only the source of a form they own. A script with a required parameter and no default cannot run from an event, because an event passes no parameters.
The runs it made
From then on each return the simulator posted made one run, without anyone asking for it and without a schedule.
The run history, one row per return
What the agent calls. This is the exchange the agent has with Plexara on your behalf, shown for the technical reader. You ask in plain language; you never type any of it.
manage_script runs acme-pos-return-event-609
trigger event_source event_id status duration
event pos-returns dpx_73252d4f…-0008 succeeded 279 ms
event pos-returns dpx_73252d4f…-0020 succeeded 203 ms
event pos-returns dpx_733c9b2c…-0038 succeeded 201 ms
event pos-returns dpx_733c9b2c…-0048 succeeded 213 ms
event pos-returns dpx_109c51c1…-0005 succeeded 186 ms
manage_script get_run dpx_475722ec…
-> trigger event
event_source pos-returns
result {"sale_id": "dpx_5396c560…-0002", "store": "ACME Store #165",
"amount": 178.34, "flagged": false, "reasons": []}Three simulator deliveries a few seconds apart carried five returns, and the history shows five runs, each naming the source and the event it was made once for. Each run started within a second of its delivery and took about a fifth of a second, almost all of it the count query. The first return checked was $178.34 and the store’s first of the day, so the run recorded it and posted nothing.
What one run per event guarantees
Six rules decide what happens when events arrive faster than runs finish, and when a run fails.
What one run per event guarantees
- 01
One event, one run
A run is made once for each event id. A delivery the sender retries, or two servers noticing the same event, makes no second run.
- 02
The sender never waits for the automation
The run is queued in the same step that stores the event, before the sender is answered, and executes afterwards on the platform’s workers. A slow or failing automation cannot slow the sender down.
- 03
A burst is bounded
An automation holds at most 100 event runs waiting. An event past that is recorded as a skipped run whose reason says the queue was full and the event is still in its source, and the Events section counts the week’s skips.
- 04
One at a time keeps arrival order
An automation set to run one at a time, refused or queued, runs its event runs in the order the events arrived. An event run is never refused for an open run; it waits.
- 05
A failed event run alerts and is not replayed
It is recorded with its cause like any run, and its owner is told as for a failed scheduled run. The platform does not run it again on its own, and the next event still runs.
- 06
The event stays in its table
Whatever the automation does, the event is in the source’s table, so a run that failed or was skipped can be made good later by a run by hand or a scheduled sweep that reads the table.
One run per event, or a scheduled batch
Both shapes read the same events. The choice is about what each event needs and how many of them there are.
One run per event, or a scheduled batch
| Question | One run per event | A scheduled batch |
|---|---|---|
| Does each event need its own answer? | Yes: a flag, a reply, a write to another system for this one record. | No: a total, a file, or a dashboard over many events. |
| How soon does somebody act on it? | Within seconds of the event being stored. | At the next fire, which is fine for a daily or hourly summary. |
| How many events arrive? | Tens or hundreds an hour, each worth a run. | Thousands an hour, where one query over the window is cheaper than a run each. |
| What does a run need to remember? | Nothing: the event is the input. | Its place in the feed: a watermark in state, as in 607. |
The demo’s point-of-sale feed carries about 8,600 events a day. Running an automation for every sale would make thousands of runs that do nothing, which is why the returns go to their own source and only they start a run. The scheduled readers in 607 keep reading the whole feed.
Where this goes next
Each return on the demo tenant is now checked within seconds of being stored, the ones worth a look reach the operations channel with their reasons, and every check is in the run history with the event it was made for.
The same shape serves a form: its submissions are a source, and an automation that names it runs once per submission, which the next lesson follows for a mailbox. What happens when one of these runs fails at an hour nobody is watching is 611.
Key terms
Four terms cover an automation that runs once per event.
Key Terms
- Event source
- The webhook, form, or mailbox source an automation names. Each event it stores queues one run.
- run.event
- What an event run reads: the event id, type, key, when it was received, the source, and the payload. None on every other run.
- Event run
- A run recorded with trigger event, the source, and the event id it was made once for.
- Skipped as backlog
- An event that arrived while the automation already held its limit of waiting runs. Recorded, never executed, and still in its source.
