Docs / The language & scripts
Recipes
Four patterns that come up in almost every integration. Each one is short enough to copy and change.
Remember which record is which
Two systems that cannot store each other’s keys still have to agree on which person is which. The platform keeps a durable table of pairs for you, one namespace per kind of thing.
const order = input.event.body;
const known = getMapping("contacts", order.customer);
if (known !== null) {
return { contact: known, created: false };
}
const created = CreateContact({ email: order.customer, name: order.customer });
setMapping("contacts", order.customer, created);
return { contact: created, created: true };
getMapping answering null is the everyday case, not a failure: it is a
record seen for the first time. The mapping outlives the run, so tomorrow night
the same order takes the first branch.
Doing this for thousands of records at once? setMappings and getMappings
take whole lists, and that is the shape a real sync uses — see Syncing data
between two systems.
Check that a write actually landed
A 201 means the far end accepted your request. It does not always mean the
record is there, indexed, and findable by the key you will look it up by
tomorrow. When that matters, read it back.
const created = CreateContact({ email: "ada@example.com", name: "Ada Lovelace" });
const back = FindContact({ email: "ada@example.com" });
if (back === null || back.id !== created) {
logError("the contact is not findable after creating it", { expected: created });
throw new Error("create did not stick for ada@example.com");
}
return created;
Two deliberate choices in there. logError records the detail on the run — and
marks this script as failing, so it shows up without anybody reading logs. The
throw ends the run: this is a case where continuing would build more work on
a record that may not exist.
Say something when it goes wrong
There are two levels, and most environments want both.
Inside the script, for something the run should note but survive:
const order = input.event.body;
if (order.customer === undefined) {
logWarning("order has no customer — nothing to match", { order: order.id });
return { order: order.id, skipped: "no customer" };
}
return { order: order.id, customer: order.customer };
logWarning and logError are how a script reports the half of integration
work that does not throw: the record that was skipped, the field that was
missing, the answer that made no sense. They colour the script’s health, so a
quiet run and a run that skipped four hundred records do not look the same.
Outside the script, for the run that failed at 02:00 with nobody watching: a notification rule mails somebody, and a system trigger runs a script of yours with the failure as its input. Both are in Reacting to failures.
Let a model read something for you
Classification, extraction and summarising are what a language model is genuinely good at inside an integration: turning a sentence a person wrote into a field a system can store.
const message = input.event.body.customer;
const verdict = ClassifyMessage({ text: message });
const answered = verdict.json === undefined ? undefined : verdict.json.category;
const categories = ["billing", "technical", "other"];
const category = categories.indexOf(answered) === -1 ? "other" : answered;
log("classified", { category: category, answered: answered, model: verdict.model });
return { category: category };
The important line is the one that does not trust the answer. A model can reply with a category you never defined, an empty object, or a perfectly reasonable word that happens not to be one of yours — none of it is an error, and none of it can be caught for you. Decide what an unusable answer means (a fallback here; elsewhere, a refusal) and write that decision down.
And when it stops being small
The moment a script is looping over more than a handful of records, it is a different job with different tools — pulls that page themselves, staged rows, comparisons done where the rows are, and a report at the end. That is Syncing data between two systems, and it is worth reading before you write the loop rather than after.