Last week the harness made an agent survive production. This week the agent leaves the screen. A chat agent is an interface; a background agent is a lifecycle. Nobody is watching it: an alert starts it at 3 a.m., it runs for minutes or days, and the work has to survive the process dying, the reply getting lost, and the world changing while it waits.
This week builds an on-call agent for a checkout service that breaks in three ways: a bad feature the agent may switch off, a bad release that needs a person to approve the rollback, and a payment gateway that belongs to another team, where the honest move is to wait or ask.
Each of the six steps adds a few lines to the previous one, so the diff is the lesson. The code uses the real Inngest SDK — ctx.step.run, step.sleep, step.wait_for_event — and a live visualizer lets you kill the agent mid-run and watch finished steps come back from the journal instead of running again.
The question to ask at every line: what if the process dies here, what if the world changed while we waited, and who is allowed to decide this?
The walkthrough
Each part adds one capability to the same growing codebase, and each is a runnable checkpoint.
- 01A goal and a loopObserve fresh every cycle, let the model propose one action, and check the goal in code. A policy table, not the prompt, decides what may run.
- 02Durable stepsWrap every piece of work in ctx.step.run. Kill the process: Inngest runs the function again from the top and finished steps return their saved result.
- 03Wait for the worldstep.wait_for_event with a timeout. The event is a doorbell, not the truth: after waking, look again before believing anything.
- 04A person approvesThe risky action waits in an inbox for a yes. Silence is not a yes, and a yes given for an older version of the service is dropped.
- 05Safe retriesThe reply was lost but the change happened. An action id built from run, cycle and action makes the retry the same request, so it is never done twice.
- 06Ask for helpWhen the cause is outside our service, ask. An answer is information, not permission: nothing runs because a person said so.
After this week you can
- Run an agent from an event, with no one watching, and bound it
- Make agent progress survive crashes with durable steps
- Pause for events and people without holding a process open
- Design retries that can never repeat a side effect