How to Automate Pulumi Operations with Kestrel Workflows: Incident Response, Provisioning, CI/CD, Drift Detection, and Policy
Pulumi is how your infrastructure changes — real programming languages, real state, Pulumi Deployments running the updates. But the operations around it are still mostly manual: someone watches the deployments queue, someone notices the stack has drifted, someone decides whether the destroy is safe, someone chases the CrossGuard violation. Here's how to automate all of it — incident response, infrastructure provisioning, developer requests, CI/CD, security and policy, drift detection and remediation, and stack lifecycle — as deterministic, approval-gated Kestrel workflows, with copy-paste prompts for each.
Every team running Pulumi Cloud carries the same operational load. An update fails at 2am and the failure sits unexamined until standup. Real infrastructure drifts from the declared program state and nobody finds out until the next update produces a diff nobody expected. A CrossGuard policy violation fires during a deploy and gets pasted into Slack by hand. A destroy needs running, and everyone hopes the person clicking it picked the right stack. None of this is a Pulumi problem — each response is a known, repeatable sequence of steps that happens to be executed by a human with the Pulumi Cloud console open. The fix is codifying those sequences as workflows that run the same way every time, with a human approving anything that changes real infrastructure.
This post shows how to automate the seven domains of Pulumi operations with Kestrel Workflows: incident response, infrastructure provisioning, developer requests, CI/CD, security and policy, drift detection and remediation, and stack lifecycle. Each section includes prompts written the way you'd hand them to the Workflow Agent — paste one in, review the workflow it builds, and activate it.
How it works: plain English in, deterministic workflows out
You describe the automation in plain English and the Workflow Agent assembles it from real building blocks — Pulumi Cloud's deployment lifecycle (run a deployment as an update, preview, refresh, destroy, detect-drift, or remediate-drift operation, wait for it to reach a terminal state, cancel it, and pause or resume a stack's deployment queue), stacks and their updates, stack outputs, drift status, stack tags, and a read-only AI investigation block — plus the stack around it: GitHub pull requests, Slack, PagerDuty, and Jira. The AI builds the workflow once; the workflow itself runs deterministically — the exact same steps on every execution, not an agent improvising at runtime against your production infrastructure.
Pulumi Cloud pushes events to Kestrel through organization webhooks, each delivery signed and verified — no polling delay. Stack updates succeeding and failing, previews failing, deployments starting, succeeding, and failing, drift detections, and CrossGuard policy violations all become triggers that fire the moment Pulumi Cloud emits them. Workflows start from the trigger that fits the job: Update Failed, Drift Detected, Policy Violation, CI events, schedules, or plain-English developer requests. And every workflow runs inside Kestrel's access control and approval model — restrict who can invoke it and drop approval gates anywhere in the graph so no update runs, no stack is destroyed, and no drift is remediated until the right person signs off in the dashboard, in Slack, or by merging a PR.
The Workflow Agent building a production-ready workflow from a plain-English description.
How to automate incident response in Pulumi
Pulumi incidents announce themselves through the event stream: the update that fails halfway through, the preview that breaks before anything is applied, the deployment that dies in the queue. Because those events arrive as signed webhooks, the workflow fires the moment the failure happens — and the split is always the same: investigating and notifying is safe to automate fully, and anything that blocks or changes infrastructure gets an approval gate. Pair the pause workflow below with a resume companion (“when the on-call engineer requests resuming a stack's deployments, resume the queue and confirm in #incidents”) so the pause never outlives the incident.
When a Pulumi stack update fails, run a read-only investigation into what failed and why — the update's error, the stack's recent update history, and what changed — then post the findings and the update's resource change counts to #incidents in Slack. If the stack is a production stack, also page the on-call engineer through PagerDuty with the summary attached.
When a Pulumi deployment fails on a production stack, send pausing the stack's deployment queue to a Slack approval gate for the on-call engineer — so nothing else executes onto a half-updated stack — pause it on approval, tag the stack with the incident ID, and post the freeze and the failed deployment's console URL to #incidents in Slack.
When a PagerDuty incident fires for one of our infrastructure-backed services, run a read-only investigation into the related Pulumi stack — recent updates, what resources they created, changed, or deleted, and whether an update lines up with the incident window — and post the change-correlation summary to the incident's Slack channel so responders know immediately whether an infrastructure change is the likely cause.
How to automate infrastructure provisioning in Pulumi
Provisioning through Pulumi is the platform-owned work of turning “we need an environment” into deployed infrastructure — with the preview reviewed before anything is created. Done by hand it's a deployment someone runs, forgets, and re-runs; done as workflows it's one governed pipeline: preview, show the diff, gate, update, confirm. And where the infrastructure doesn't exist in code yet, the workflow generates the Pulumi program and opens a pull request, so provisioning never routes around code review.
When a team requests a new environment, run a preview deployment on the environment's Pulumi stack, fetch the planned resource creates, updates, and deletes, and send them to a Slack approval gate for the platform team with the requesting team and their stated reason in the approval message. On approval, run the update deployment, wait for it to succeed, and confirm the result in #platform in Slack.
When a team requests connection details for an environment — the database endpoint, the queue URL, the cluster name — fetch the stack's current outputs from its latest state and reply to the requester in Slack with the values. Secret outputs are redacted automatically, so this is safe to run ungated for any engineer.
When a team requests a new standardized cloud resource — a bucket, a queue, a database — generate the Pulumi code for it with our tagging and encryption standards applied, and open a pull request against our infrastructure repository with the requesting team and the request in the PR description, so the new resource lands through code review and the normal deployment pipeline instead of ClickOps.
The best way to automate developer requests in Pulumi
Most of what developers need from Pulumi isn't an update — it's an answer. What would this change do? Why did my stack's last update fail? Is the state stale? Each of those is a request to whoever holds Pulumi Cloud access, and each blocks a developer until someone context-switches. Handled by request-triggered workflows, these become self-service: the developer types the request into Slack with /kestrel-workflow, the terminal with kestrel workflows request, or the Developer Requests chat in the dashboard; Kestrel matches it to an active workflow, extracts the stack name from the phrasing, and runs it with team-scoped permissions — no Pulumi Cloud seats or shared access tokens required. This is the same pattern our internal developer platform guide extends across the whole stack.
When a developer requests a preview on their team's Pulumi stack, run a preview deployment, wait for it to finish, and reply in Slack with the planned resource creates, updates, and deletes and the console URL — never run the update. Scope this to the requester's team stacks so developers can see what their changes would do without touching production.
When a developer reports that a stack's state looks stale, send running a refresh deployment on the stack to a Slack approval gate for the platform team with the stack's recent update history attached, run the refresh on approval, wait for it to finish, and confirm the result to the requester in Slack — so state catches up with reality through a tracked deployment.
When a developer asks why their stack's last update failed, run a read-only investigation into the stack's recent updates and deployments — what failed, at which step, and what changed — and reply to the requester in Slack with a plain-English summary of the likely cause and a suggested next step. This is read-only, so allow it for all developers without an approval gate.
How to automate CI/CD with Pulumi
The heart of Pulumi CI/CD is the same as any IaC pipeline: a preview someone has to look at before the update runs. Wire the merge event to a preview, put the update behind a Slack approval gate with the resource change counts in the message, and have the workflow wait for the deployment's terminal state before announcing the result — and the whole pipeline reports itself, from merge to applied infrastructure.
When a pull request merges to main in our infrastructure repository, run a preview deployment on the matching Pulumi stack, fetch the planned resource changes, and send running the update to a Slack approval gate for the release owner with the change counts and console URL in the approval message. On approval, run the update deployment, wait for it to reach a terminal state, and post the outcome to #releases in Slack.
When a Pulumi stack update succeeds on a production stack, fetch the update's resource changes — how many resources were created, updated, and deleted — and post a release summary with the stack and version to #releases in Slack, so every production infrastructure change is announced with its actual diff.
When a Pulumi preview fails on any stack — a broken program or bad config caught before anything was applied — run a read-only investigation into the failure, have the AI investigate the code in our infrastructure repository, generate a fix, and open a pull request with the failure analysis in the description. Post the failure summary and the PR link to the team's Slack channel; the fix ships through normal code review, so no approval gate is needed.
Pulumi security and policy automation
Pulumi ships a policy engine — CrossGuard — that evaluates every stack operation against your policy packs. What it doesn't ship is the response: the violation that fires during a deploy still needs someone to notice it, figure out which resource tripped it, and decide what happens next. Workflows close that loop — violations become investigations with findings attached, risky states get reported on a schedule, and an active incident can freeze the deployment queues that matter.
When a CrossGuard policy violation fires during a Pulumi stack operation, run a read-only investigation into which policy failed and what resource triggered it, post the findings to #security in Slack, and tag the stack with the violation for follow-up. If the violation is mandatory — meaning the operation was blocked — also create a Jira ticket for the owning team so the fix is tracked work.
Every Monday at 9am, run a read-only investigation across our Pulumi Cloud organization — which stacks have failed updates sitting unresolved, which have drifted from their declared state, and which haven't been updated in over 90 days — and post the audit report to #security in Slack so risky states get reviewed weekly instead of discovered during an incident.
When a PagerDuty security incident fires, send pausing the deployment queues on our production Pulumi stacks to a Slack approval gate for the security lead — with the incident in the message — pause them on approval so no infrastructure changes can land mid-incident, tag the stacks with the incident ID, and confirm the freeze in #security in Slack.
How to automate Pulumi drift detection and remediation
Drift is the gap between what your Pulumi program declares and what your cloud actually runs — and it widens silently until an update produces a diff nobody expected. Pulumi Deployments has drift as a first-class operation: detect-drift runs find it, remediate-drift runs fix it. The workflows below decide what happens between those two — an investigation with findings attached, a gated remediation, and a tracked ticket when the detection itself stops working.
When Pulumi detects drift on a stack, run a read-only investigation into which resources drifted and what the likely cause is — a manual console change, an external automation, a deleted resource — then post the findings to #platform in Slack and create a Jira ticket for the owning team so the drift is tracked work with an owner.
When Pulumi detects drift on a production stack, fetch the stack's drift status and send running a remediate-drift deployment to a Slack approval gate for the platform team with the drift summary in the approval message. On approval, run the remediation, wait for it to succeed, and confirm in #platform that declared state and reality have reconverged.
Every weekday at 7am, run a detect-drift deployment on our production Pulumi stacks, wait for the runs to finish, and post a drift report to #platform in Slack — which stacks are clean and which have drifted — so the drift signal is never staler than a day. If a drift detection run itself fails, create a Jira ticket for the platform team; a stack whose drift detection is broken is a blind spot, and blind spots get tracked.
Pulumi stack and environment lifecycle automation
Stacks accumulate: the ephemeral environment nobody tore down, the stack nobody has updated since Q1, the inventory nobody has looked at since the last cost review. Lifecycle workflows keep the estate tidy on a schedule and make teardown a governed request instead of a dreaded manual destroy — with stack tags carrying the ownership and lifecycle metadata that make the inventory meaningful.
When a team requests tearing down an ephemeral environment, send running a destroy deployment on the environment's Pulumi stack to a Slack approval gate for the platform team with the requesting team and reason in the approval message. On approval, run the destroy, wait for it to succeed, and confirm the teardown result in #platform in Slack.
Every Monday at 9am, list our Pulumi stacks with their last update time and resource counts and post the inventory report to #platform in Slack — so forgotten environments, stale stacks, and stacks that quietly doubled in size get spotted in review instead of on the invoice.
When a new Pulumi stack is created in the organization, fetch its details, tag it with the creation date and a lifecycle: unclassified marker, and post the new stack to #platform in Slack so the platform team assigns an owner while the stack is a day old — not when the quarterly inventory finds it unclaimed.
Making Pulumi easier to manage
Twenty-one workflows, seven domains, one pattern: describe the operation in plain English, let the Workflow Agent assemble it from real Pulumi Cloud blocks and the stack around them, review the graph, and put approval gates on anything that updates, destroys, remediates, or pauses. Pulumi keeps doing what it's best at — declaring your infrastructure in real programming languages — and Kestrel turns its event stream into governed action: investigations with findings attached, gated updates and destroys, drift remediations, policy responses, deployment freezes, pages, and tickets. The recurring 80% runs itself, and your team's time goes to the judgment calls.
This isn't Pulumi-only, either. The same workflow engine spans 30+ integrations across infrastructure, PaaS, observability, comms, databases, CI/CD, and IaC — so the workflow that gates a production update lives next to the one that rolls back an ArgoCD application or locks a Terraform workspace. For deeper dives, see the internal developer platform guide and the companion posts on automating Terraform operations, automating ArgoCD operations, automating Kubernetes operations, automating AWS cloud operations, and automating Cloudflare operations.
FAQ: automating Pulumi operations
How do you automate Pulumi operations?
Turn each recurring stack event — a failed update, detected drift, a CrossGuard policy violation, a deployment that needs gating — into a deterministic, approval-gated workflow instead of a human watching the Pulumi Cloud console. With Kestrel, you describe the automation in plain English, the Workflow Agent assembles it from real Pulumi Cloud blocks plus the stack around them (GitHub, Slack, PagerDuty, Jira), and it runs the exact same steps every time, pausing at approval gates before anything changes real infrastructure.
What is the best automation tool for Pulumi?
It depends on scope. Pulumi itself — with pulumi preview and pulumi up running through Pulumi Deployments or CI — is the right primitive for declaring and shipping infrastructure. For turning Pulumi Cloud events into governed action across your whole stack — update investigations, gated updates and destroys, drift remediation, policy responses, deployment freezes, stack inventories, pages, and tickets in one system — Kestrel Workflows builds deterministic workflows from plain English, triggered by stack events, deployment events, drift detections, policy violations, schedules, CI events, and developer requests.
Is it safe to automate destructive operations in Pulumi?
Yes — because Pulumi's own model separates preview from execution, and Kestrel enforces that separation. Running a preview changes nothing; it produces a diff. The steps that change real infrastructure — running an update, a destroy, or a drift remediation, pausing a deployment queue — always sit behind an approval gate in these workflows, so nothing executes until the right person signs off in Slack, with the requester, the preview's change counts, and every step recorded in the run's audit trail. Read-only workflows (investigations, stack outputs, drift checks, inventories) are always safe to run ungated.
How do you make Pulumi easier to manage?
Reduce the number of stack events a human has to react to. Automate the recurring responses — failed updates, drifted stacks, policy violations, stale environments — give developers self-service stack outputs, previews, and refreshes without Pulumi Cloud access, and keep humans in the loop only where judgment matters: approving updates, destroys, and drift remediations, not babysitting the deployments queue.
Getting started
Connect Pulumi Cloud — an access token plus an organization webhook, about five minutes end to end — then pick the domain that hurts most. For most teams that's CI/CD: the preview that needs a human eye should be a Slack approval with the change counts attached, not a console tab someone forgot. Paste one of the prompts above into the Workflow Agent, review the workflow it builds, tighten the scoping and approvals, activate it, and add the next one. The Workflows Quickstart walks through your first workflow end to end, and the Create Workflows guide and Integrations Setup cover connecting GitHub and the rest of your stack. Prefer the terminal or an AI coding agent? Workflows can also be created and managed through the CLI, Python SDK, and MCP. Within a few weeks every stack, update, and drift run that matters will have a workflow behind it — and an audit trail to prove it.
Automate your Pulumi operations with $1,000 in credits
Incident response, infrastructure provisioning, developer requests, CI/CD, security and policy, drift detection, and stack lifecycle — describe each workflow in plain English and Kestrel builds it. New accounts get $1,000 in usage credits to get started.
Get Started