How to put repetitive AI work on autopilot, without building the plumbing
Trigger an AI agent from a webhook or a cron schedule — triage, PR review, digests, nudges — without writing your own orchestration glue.
All postsThere is a category of work I do for AI that AI should really be doing for me. Triaging the error report that just landed. Skimming the pull request before I look at it properly. Writing the Friday digest of what moved this week. Nudging the workunit that has been sitting in in_progress for nine days. None of it is hard. All of it is recurring, and all of it quietly eats the start of my day.
For a while my answer was scripts. A cron job that hit an API, dumped JSON into a prompt, and posted the result somewhere. It worked until it didn't — the script rotted, the prompt drifted from the script, the secret expired, and I was the only person who knew which box it ran on. The actual AI part was five lines. Everything around it was plumbing I had to babysit. This post is about how Workunit's Automations let me delete that plumbing and keep the five lines.
The chores that are actually automatable
If you write down the recurring AI tasks you do by hand, almost all of them split the same way: either something happened and you want an agent to react to it, or it's a particular time and you want an agent to go look. That's the whole shape. An event, or a clock.
Reacting to events
A Sentry error fires, a PR opens, a Stripe payment fails, a Linear issue gets filed. You want triage, a first-pass review, or a workunit created — within seconds, not whenever you next check.
Reacting to a clock
Monday's leadership digest. The daily standup summary. The weekly walk through stale work that nobody has touched. Nothing triggers these except the calendar, and they're the easiest to forget.
Both halves are automatable, and both are the kind of thing an LLM with the right context handles well. The reason they don't get automated is rarely the AI — it's the glue. You need somewhere to receive the event, verify it actually came from GitHub and not someone poking your URL, run the prompt, give the model the tools to act, track what it cost, and show you what happened when it goes wrong. That's the part I no longer want to write per task.
Two triggers: a webhook or a schedule
An automation in Workunit is a trigger plus a recipe. The trigger decides when it runs, and there are exactly two kinds, matching the two halves above.
Webhook
Each automation gets its own signed URL at /hooks/<token>. Anything POSTed to it becomes the run's payload. This is what you point GitHub, Stripe, Linear, Sentry, Shopify, or your own service at. The agent sees the exact JSON the sender delivered.
Schedule
A standard five-field cron expression. The payload is just the timestamp of the slot it fired for; the recipe is expected to fetch its own inputs through MCP tools. This is your AI on a cron — digests, rollups, nudges, anything recurring.
Both routes land in the same run pipeline. Same prompt rendering, same tool access, same cost accounting. The trigger is just the front door. Once a payload is inside, it doesn't matter whether a webhook or a schedule let it in.
Recipes: where the prompt and the guardrails travel together
The part I care most about is the recipe. A recipe is the reusable bundle that the trigger fires. It owns four things, and bundling them together is what stops the prompt-drifting-from-the-script problem I kept hitting with my own cron jobs.
A prompt template
Plain text with two substitution sites — {{.payload}} for what the trigger handed in, and {{.cfg.field}} for per-automation config. Written in Go's text/template syntax. This is the actual instruction the model runs.
An MCP tool allow-list
The set of Workunit tools the agent may call — create_workunit, search, save_context, and so on. A model handed four relevant tools makes better calls than one given thirty. The allow-list is about a tight menu, not security.
An execution tier
Lightweight or heavy. The choice that decides whether the run is a quick LLM call or a full coding agent in a VM. More on this below.
An optional pinned model
Leave it blank and the run uses your org's default automation model. Pin it when a recipe needs something specific — say, a model that's strong at structured extraction.
One recipe can back many automations. I might write a single "Linear bug triage" recipe and point two automations at it — one webhook from Linear for live issues, one schedule for the weekly backlog walk. Same prompt, same tools, two front doors. Workunit ships a library of built-in recipes to start from — daily and weekly reporting digests, Linear-to-Workunit mirroring, GitHub PR review agents, Sentry triage, stale-workunit nudges — and you can write your own with the New recipe button.
Lightweight when you want an answer, heavy when you want work done
The two execution tiers are the difference between asking a model a question and handing a coding agent a machine. Picking the right one is mostly about whether the task is one-shot or multi-step.
Lightweight
One LLM call with MCP tool access. Fast and cheap. Right for triage, classification, and digests — anything where the model reads some context, makes a few tool calls, and produces a result. The Sentry triage and the weekly digest both live here.
Heavy
Boots a full Cloud Execution VM with a coding agent inside. It can run shell commands, read a repo, and do multi-step work — same engine as a manual Cloud Execution, billed against the same quota. Right for a PR review agent that actually checks out the branch.
Most automations want lightweight. It's the one-shot call that turns an incoming event into a triaged workunit or a written summary, and it costs cents. Reach for heavy only when the agent genuinely needs to run things — clone a repo, execute tests, work a task across several steps. The tier lives on the recipe, so the decision is made once by whoever authored it, not re-litigated per run.
Pointing GitHub, Stripe, and Sentry straight at it
The webhook side is where the plumbing usually hurts most, because the moment you expose a URL to the public internet you have to think about who's allowed to call it. Workunit handles this by verifying each vendor's native signature scheme. You don't reformat payloads, you don't run a proxy — you paste Workunit's endpoint into the vendor's webhook settings and it verifies the signature the vendor already sends.
| Source | Verified header |
|---|---|
| GitHub | X-Hub-Signature-256 |
| Stripe | Stripe-Signature (with timestamp anti-replay) |
| Linear | Linear-Signature |
| Sentry | Sentry-Hook-Signature |
| Shopify | X-Shopify-Hmac-Sha256 |
| Custom sender | X-WU-Signature (Workunit-native HMAC) |
For your own services there's a Workunit-native HMAC scheme in the Stripe style — sign the exact bytes you POST with a 32-byte secret, send it in an X-WU-Signature header, and Workunit verifies it with timestamp anti-replay and per-delivery dedup. A signing snippet for the custom scheme looks like this in Node:
const crypto = require("crypto");
const body = JSON.stringify(payload); // the EXACT bytes you POST
const ts = Math.floor(Date.now() / 1000).toString();
const sig = crypto
.createHmac("sha256", process.env.WU_WEBHOOK_SECRET)
.update(ts + "." + body)
.digest("hex");
await fetch("https://workunit.app/hooks/<token>", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-WU-Signature": "t=" + ts + ",v1=" + sig,
},
body,
});The endpoint URL carries a 43-character token — 256 bits of entropy — that's distinct from the automation's internal ID, so you can re-mint the public URL without breaking audit references. The signing examples ship in curl, Node, Python, and Go in the Automations guide. And before you wire up the real sender, the Test-fire button on each automation row replays a sample payload through the live template, so you can debug your prompt against realistic data without waiting for a webhook to arrive.
Knowing what it cost and what it did
The thing my homegrown scripts never gave me was visibility. When a cron job silently stopped firing, I'd find out a week later. When one started costing more than it was worth, I'd find out on the bill. Automations close both gaps.
Every run gets a detail page with a live terminal. For a heavy-tier run you watch the coding agent work in real time, exactly like a manual Cloud Execution. For a lightweight run the same page shows the MCP tool-call transcript and the model's response. Status, duration, and cost stream in without a refresh.
Cost and token usage are tracked per run and rolled up per automation, read straight from the model response and stored as USD. The Automations page breaks 7-day spend down by model, so the question "which automation is the expensive one, and which model is it burning" has an answer on the screen instead of in a spreadsheet. One honest caveat: heavy-tier runs don't yet surface their model spend back into that rollup, so the panel flags when heavy runs are in the window and undercounting — budget those separately for now.
Why the recipe owns the guardrails
An agent fired by a webhook runs without you watching. That's the point, and it's also the risk. Pinning the tool allow-list and the execution tier to the recipe means a webhook can only ever invoke the capabilities the recipe author already chose — the trigger can't widen them. The blast radius is decided once, at authoring time, not at runtime by whatever payload happened to arrive.
What this replaces
I want to be precise about what Automations is and isn't. It isn't a general workflow engine with branches and loops and a visual canvas. It's a narrow thing done deliberately: take an event you already have — a webhook you already emit, a schedule you already keep in your head — and run an AI workflow off it, with the prompt, the tools, the model, and the cost tracking handled. The orchestration plumbing I used to write per task is the part that's gone.
And because the agent runs inside Workunit, the work it produces lands where the rest of your work already lives. A Sentry error becomes a triaged workunit with the right tasks. A PR review writes its findings as context atoms the next agent will read. A weekly digest pulls from the same workunits you and your collaborators have been editing all week. The automation isn't a side channel firing off into a Slack message and forgetting — it writes back into the shared workspace, so the next human or agent picks up where it left off. That's the difference between putting AI chores on autopilot and just adding another integration to maintain.
Bring your AI agents and your team into one workspace
Workunit gives your agents structured context and your team a shared place to plan, track, and ship the work. Free to start, no credit card.
Dive deeper
Want to go from the idea to the actual workflow? These guides walk through it step by step.
Recipes, triggers, signing, and the full prompt-template reference.
The heavy-tier engine that backs multi-step automation runs.
The full guide library covers every part of Workunit, and the community discussions are open if you want to ask.