Skip to content

What an inline routine sees

The triggering event is bound in scope as one normalised shape, whatever the signal type:

signal.id, signal.typeName, signal.subject, signal.occurredAt
signal.source.{ kind, id, label, url }
signal.properties.<field> // type-specific fields — for a realm signal these are the event's
// mapping keys (repo, number, author, …); read them from here
trigger // "signal" | "cron"
now // ISO-8601 timestamp of this run
dryRun // true when being tested — GUARD every external effect with if (!dryRun)

A routine reacts through the typed gateway.* surface — read with gateway.kg.query, judge with gateway.ai.classify, act with Realm Functions or gateway.notifications.createNotification. Reads and gateway.ai.* are always safe; guard writes with if (!dryRun).

agents/pr-review.routine.ts
if (trigger !== "signal" || !signal) { console.log("not a signal event"); return; }
const { repo, number, author } = signal.properties;
const [owner, name] = String(repo).split("/");
const commits = await gateway.gh.reposListCommits({ owner, repo: name, author, per_page: 1 });
const isNew = commits.length === 0;
console.log(isNew ? `new contributor ${author}` : `${author} has prior commits`);
if (isNew) {
console.log(dryRun ? `WOULD notify about PR #${number}` : `notifying about PR #${number}`);
if (!dryRun) await gateway.notifications.createNotification({ event: "NewContributorPR", source: "pr-review", url: signal.source.url });
}