automation builds the workflow that fires when a customer upgrades, the nightly sync between two SaaS tools, the refund that waits for someone to approve it, and the cron job nobody has checked in six months. It owns the decisions, not the click-path: whether to automate a thing at all, which platform to build it on, what triggers it, what order the steps run in, who approves the risky one, and how you learn it stopped — across hosted iPaaS (Zapier, Make), self-hosted engines (n8n, Windmill), code-first durable execution (Temporal, Inngest), and plain cron. Two properties shape every technique here: a step may belong to a vendor you cannot deploy to, and a step may be a person — hence you cannot deploy a fix into someone else's system, and you cannot un-send.
runs onClaude CodeCodexCursorAntigravityopencodeGrok BuildHermes
within-tolerance; only exception escalates — collapsing them into one bucket is how the queue stops getting read.reconciliation.mdsurface-hosted-ipaas.md
2 of 18 loaded · read fully
Route before acting. One job, at most one base surface — the agentic overlay is added only when a model decides which tool to call, in what order, or is the trigger itself, never assumed.
The router is the skill. There is no fixed pipeline to run start-to-finish — each job stands alone and enters where your request is. The animation traces one path (a reconciliation loop closing a gap nothing else caught); the sections below map the whole surface it routes across.
Build processes that span systems, schedules, events and human approvals — and make them survive
the fact that you cannot deploy a fix into someone else's system, and you cannot un-send.
backend owns async work inside a system you control: your queue, your workers,
your database, deployable and testable end to end. automation owns the case where most
of the steps belong to vendors you cannot deploy to, cannot unit-test, and cannot roll back — where
the API changes with no deploy on your side, the quota belongs to someone else, and a person
clicking "approve" is a node in the graph. It writes workflow definitions, integration code,
connector configuration and functions — it does not author the business rule; when no
upstream rule exists, it captures it explicitly rather than inventing one silently.
the wiring across a boundary you don't control
the "Not this skill" table — eight asks this skill declines by design
The default reader is one person, or a small team, with no second pair of eyes. That matters more than it looks: nearly every control this domain teaches assumes a counterparty. Approval assumes an approver who is not the requester. Reconciliation assumes a reconciler who is not the recorder. The functions survive at n=1; the second body does not — the substitute is an independent source, a clock, or a rule committed to in advance (I6).
SKILL.md is a router, not a script. Every request selects the smallest sufficient route: one primary job — the twelve below — combined with at most one base surface that reshapes how the job applies to what's actually running, plus the additive agentic overlay when a model decides which tool to call, in what order, or is the trigger itself. Read the selected references completely; load one or two at most, never the whole pack.
| facet | options | rule |
|---|---|---|
| ① Primary job | reconciliation ⭐ · integration-reliability · compensation-and-recovery · credentials-and-connections · approval-and-authority · trigger-design · sync-semantics · workflow-observability · cost-and-quota · platform-selection · workflow-testing · process-capture | Exactly one. Pick the single job the request needs; the flagship — reconcile against the vendor's own state, never your record of what you told it — is the loop every other job assumes exists somewhere, or states plainly that it does not. |
| ② Base surface | surface-hosted-ipaas (default) · surface-self-hosted-engine · surface-code-first-durable · surface-platform-native | At most one. The surface reshapes what each job means for where the workflow actually runs — it points to the job references, it doesn't redefine them. |
| ③ Agentic overlay ⭐ | surface-agentic — spend ceiling, step/iteration limit, wall-clock deadline, kill switch, blast-radius scope | Additive. Stacks on top of the base surface, only when a model decides which tool to call, in what order, or is the trigger. A model doing one bounded, deterministic task inside a step is not this overlay. |
Each job is one reference, read fully only when its route is selected. Reconciliation is the flagship because every other job either assumes this loop exists somewhere, or has to say plainly that it does not — this is the whole surface, not a headline slice.
| I need to… | Read | Contribution |
|---|---|---|
| Prove what actually happened — catch what the webhook missed, diff against the vendor ⭐ | reconciliation.md |
Flagship. Reconcile against the vendor's authoritative state, never your own record; cadence and window; ID-set diff before field diff; matched / within-tolerance / exception; alert-first at n=1 |
| Stop duplicates and missed work — delivery semantics, dedup | integration-reliability.md |
Quick Acknowledgment (ack fast, process async); dedup keyed on the business event; the completion-check false positive; per-vendor delivery guarantees |
| A step failed after an earlier one already sent, charged or wrote | compensation-and-recovery.md |
Compensation is a forward action, not a rollback; hardest-to-revert last; compensation as a human act; resume-vs-restart before any irreversible step |
| Manage API keys and OAuth across many vendors; something silently stopped authenticating | credentials-and-connections.md |
The credential fleet; silent-expiry traps; scheduled pre-expiry refresh; credential health as its own monitored resource; the shared-account bus factor |
| Put a human in the loop — who approves, what happens on timeout | approval-and-authority.md |
Translating meeting-paced GRC (maker-checker, delegation of authority) into machine-timeout policy; no engine ships a default; the n=1 compensating control |
| Decide what starts the workflow; a trigger fires too often, too broadly, or twice | trigger-design.md |
Trigger taxonomy; over-broad conditions; the cron/DST comparison; trigger idempotency across two delivery paths |
| Keep two systems in step; records duplicated, deleted rows diverging, a loop | sync-semantics.md |
The A→B→A loop; deletes are invisible to incremental sync; updated_at is a lie; conflict policy as a decision; backfill-to-incremental cutover |
| Tell whether it is still running, and what "green" does not mean | workflow-observability.md |
A workflow that stopped is not a workflow that failed; no engine alerts by default; missing-heartbeat over failure notification; audit of what ran on whose authority |
| Cap what this costs; a loop or a retry is burning quota | cost-and-quota.md |
Per-task billing; the quota is the vendor's, and its blast radius is the whole account; retry × 429; the workflow circuit breaker |
| Choose or leave a platform — no-code, self-hosted, code-first | platform-selection.md |
The four tiers; resume-capability as a selection criterion; licence and liveness; exit cost asked up front |
| Test a workflow that spans vendors you cannot control | workflow-testing.md |
What is genuinely untestable and what replaces it — dry run, narrow canary, first-then-bulk gate, fixture replay |
| Turn a business rule into a workflow — or decide not to automate at all | process-capture.md |
Capturing the rule at n=1; the control-flow vocabulary worth having; when not to automate; prefer the API, and what you buy when there isn't one |
Full router table & invariants: SKILL.md.
One base surface, at most, reshapes every job for where the workflow actually runs — the same
reconciliation job is bounded differently on a hosted builder than on code-first durable execution.
The agentic overlay is additive — it stacks on top of whichever base you picked, never
replaces it — and carries a distinct violet identity throughout this page, the same convention
operate, quality, and data use for their own additive
overlay.
Ask an agent to wire Stripe to your CRM and it writes the webhook handler, watches it return
200, and calls the integration done. Nobody checked whether the vendor's side still
holds what you think it holds, what a refund actually undoes, or what happens when the approval
gate times out at 3am with nobody watching. Closing that gap — proving what actually happened, not
what a 200 response or your own "handled" flag claims happened — is reconciliation, and everything
else in this pack assumes a reconciliation loop exists somewhere, or states plainly that it does
not. I1 is the spine: reconcile against the vendor's authoritative state, never against your own
record of what you told it. A 200 response, a queued job, a webhook subscription you believe is
active — none of these are evidence the vendor's side actually holds what you think it holds. A
webhook that never arrives leaves no trace in your logs at all — nothing failed loudly, so there is
nothing to notice.
| Signal | What it actually establishes | What it does not |
|---|---|---|
| A 200 response | The vendor accepted the request, at that moment | That the vendor's side still holds it later, or that nothing downstream reversed it |
| An active webhook subscription | The subscription existed at setup time | That every event since actually fired — a dropped delivery leaves no trace at all (I1) |
| Your own "handled" flag | You believe you finished processing it | That you did — a corrupted retry can read as confirmation instead of failure (I2) |
Compare the ID set first — cheap, and it catches the two failure modes that matter most: something the vendor has that you don't, and something you have that the vendor doesn't. Tolerance-banded field comparison runs second, on IDs present in both sets only; full-field diff only on suspected drift.
Cadence is tiered, not uniform — this is three jobs at different altitudes, not one:
| Tier | What it does | What it leaves for the next tier |
|---|---|---|
| Recent activity | Frequent, tight-window checks against whatever the vendor just processed | Anything left ambiguous rolls to the daily pass |
| Daily accounting | A full pass over the prior period, closing what the fast tier left ambiguous | Drift that survives past the day rolls to the period close |
| Periodic close | A slower, wider pass — the last backstop before numbers get reported anywhere external | Nothing — this is the floor |
The n=1 minimum viable loop: one cron job, calling the provider's "list since timestamp" endpoint, diffing the returned ID set against local IDs — and alerting, never auto-healing, on any gap that survives a grace window. Adding this loop is not a free safety net: it is a second delivery path for the same business event, so the idempotency key must be derived from the event's own identity, not from whichever path delivered it (I4) — trigger-design's job, named here as the obligation the moment reconciliation exists.
Two things set automation apart from a technique library: it names its own wedge as synthesis, not discovery, and it grounds its agentic-overlay claim in filed bug reports and merged fixes, not vendor marketing.
Almost nothing here is unknown. The problem is that it is known in five places that have never been introduced to each other.
Not vendor claims — filed issues and a merged fix, which is stronger evidence than any retelling.
max_iter (default stays 25) and a 100-hop flow-router cap, citing CWE-770 and CWE-835The refined claim: an agentic step fails by continuing by default. It fails loudly only to the extent someone bolted a deterministic ceiling onto it — and the mechanism that makes failure loud again is itself a deterministic guardrail, not the model's own restraint.
References cite these by number; the numbering is canonical. These rules govern every route, whichever files it loads.
Retry-After.automation's core workflow runs against whatever upstream artifacts exist — a business rule from
product, a contract from backend, an NFR budget from
architecture — and says so explicitly when none were supplied, rather than inventing
one.
One row per step that reaches outside your system, in three tiers — reverses cleanly, compensable only, cannot be taken back — filled before the run order is decided, not after.
The vendor's authoritative source, cadence, comparison method, and tolerance — fixed before the loop's first cycle, not after a month of unread exceptions.
One row per externally-issued credential — detection method written before the mitigation. Never records a real key, token, or secret value.
Who may approve, requester ≠ approver, and the timeout default — filled before the gate goes live, not the first time a request times out.
One row per trigger — the business event it stands for, DST behavior, other paths on the same event, self-audited before calling trigger design done.
Billing unit named before the number; a monthly ceiling, a circuit breaker, and the blast radius if the quota is exhausted — this workflow, this account, or the vendor's shared bucket.
The routing companion carrying irreversible steps, idempotency, the reconciliation loop, credentials, human gates, evidence, and every volatile fact with its re-verify trigger.
automation consumes upstream artifacts without silently overriding them — the business rule from
product, a contract from backend, an NFR budget from
architecture — and says so explicitly when none exist, rather than inventing a rule or
a target to fill the gap. It is rarely terminal: it emits a compact handoff.yaml
beside the workflow artifacts whenever downstream work is expected.
objective: <one sentence> surface: base + agentic? irreversible_steps: [step, order, compensation, resume_or_restart] reconciliation_loop: exists, compares, cadence, on_discrepancy credentials: [vendor, expires, refresh_mechanism] human_gates: [approvers, timeout, on_timeout]
The deployed process to run and watch — plus the missing-heartbeat gap this skill deliberately leaves unfilled by default (I8), and credential expiries that need their own monitored schedule (I7).
Every claim this skill made about its own reliability — a step is idempotent, the reconciliation loop actually catches drift, a timeout policy is enforced — as something to independently verify, not to re-run and call independent.
Owns the idempotency-key primitive, queues, outbox, and saga inside a system you control; automation applies the same discipline across a boundary you don't, and hands back a contract violation rather than silently working around it.
A standalone request with no downstream consumer needs no handoff.yaml at all. Only objective is required — every other field may be empty, and a consumer must tolerate it absent, never treat absence as a schema violation. reconciliation_loop.exists: no is a valid, required answer when there is no loop; leaving the block blank is not the same statement. Never silently invoke a sibling skill — name it in recommended_next.
Install once. It's a plain SKILL.md router — no flags, no config, no scripts — so it
activates on natural-language phrasing ("was the webhook ever sent," "set up nightly reconciliation
before we close the books," "the refund double-charged someone, what's the compensating action")
rather than a fixed command.
The same install runs on any Agent Skills
host. Codex installs to ${CODEX_HOME:-$HOME/.codex}/skills and triggers with
$automation; agents remains a separate cross-agent installation target.
| host | install target | command |
|---|---|---|
| Claude Code | ~/.claude/skills | ./install.sh claude |
| Codex | ${CODEX_HOME:-$HOME/.codex}/skills | ./install.sh codex |
| Cross-agent path | ~/.agents/skills | ./install.sh agents |
| Cursor CLI | ~/.cursor/skills | ./install.sh cursor |
| Antigravity (IDE + agy) | ~/.gemini/…/skills | ./install.sh antigravity |
| opencode | ~/.config/opencode/skills | ./install.sh opencode |
| Grok Build | ~/.grok/skills | ./install.sh grok |
| Hermes | ~/.hermes/skills | ./install.sh hermes |
Prefer npx skills add gabros20/automation-skill when you have Node — it maps supported clients itself.
More docs: docs/installation.md · docs/usage.md · docs/recipes.md.