Attended vs unattended isn't a licensing choice. It's a decision about who catches the 4% of runs that go wrong, and how many days pass before they notice. Here's the arithmetic we run, and why almost every real build lands hybrid.
A payables bot we inherited ran green for six days. Every run exited 0, every Slack summary said complete. It was also processing 38 of 214 invoices a night, because the source API returned a `next` cursor the client never read and logged success after page one. The alert that would have caught it — volume down 80% against trailing median — didn't exist, because nobody thinks to alert on a number being too small. Finance found it at reconciliation.
The mechanical difference fits on one slide. Attended runs inside a person's desktop session on their login, started by them. Unattended runs on a server under a service account, started by a schedule or an event. Vendors turn that into a licensing conversation. The question that actually picks your architecture is who catches the 4% of runs that don't look like the other 96%: the invoice carrying two PO numbers, the portal that starts serving a captcha on Tuesdays, the refund over £2,000 that legally needs a named approver. We've shipped both — in n8n, in Temporal, and in unglamorous Python on cron — and we land the same way nearly every time: unattended by default, with a deliberate, instrumented path back to a human.
Attended exists because the target system has no API worth using, no service account you're permitted to create, and SSO with MFA bound to a named person. Insurance carrier portals. State tax filing sites. A 2009 ERP whose vendor charges per named user and audits you for sharing logins. The only identity available is a human's, so the automation has to live inside their session. "Keeps the human in control" is brochure copy painted over that constraint.
Which means it inherits every property of a laptop. The machine hits idle timeout and kills the run mid-batch. Someone docks a second monitor, Windows switches to 125% scaling, and recorded click coordinates drift past their targets. A Teams toast steals focus between a policy dropdown and the claim amount, the keystrokes land in the previous screen's search box, and nothing errors — you've just updated the wrong policy. Throughput ceilings at one person's working day: 900 records at 40 seconds of foreground session time each is a ten-hour job you can't parallelize without another laptop and another person sitting beside it.
A 3am crash is the good outcome — stack trace, page fires, fixed before the business opens. The bad outcome is the run that exits clean because a date parser read 03/07 as March 7th and routed every DD/MM invoice into a branch that no-ops. Nobody finds it for six days, and by then it's a reconciliation problem, not an automation problem. Rebuilding finance's trust costs an order of magnitude more than the bug did.
So the non-negotiables are structural, not clever. An idempotency key per unit of work — we hash vendor ID, document number and amount — so a replay can't double-post. A dead letter queue holding the real failed payload, not a truncated error string. Alerts on volume anomalies in both directions, zero included. A replay path on-call can run without a deploy. If you can't re-run yesterday's batch and land on the same end state, you don't have unattended automation, you have a script on a timer. Credentials go in a vault with rotation and scoped permissions — not an env var holding a copy of someone's password that outlives their employment by fourteen months.
Run the arithmetic before you pick an architecture: exception rate times minutes burned resolving one times volume, against cost per unattended run. Above roughly 15–20% exceptions, attended usually wins — the operator is already in the session, so catching a problem costs ten seconds of attention instead of a context switch two days later plus re-reading the case. Below about 5%, unattended wins clearly, provided the review queue has a named owner and a stated SLA. The band between is where hybrids belong, and where most B2B processes actually sit.
The failure we see most is unattended automation with nobody owning the exception queue. It works beautifully for a month. Then sixty items sit in a Postgres table with no dashboard, someone trips over them during an audit, and the whole program loses credibility over work the system flagged correctly and stored correctly. An exception queue without an owner and a response time is a landfill. Put it in front of a person daily, in the tool already open on their second monitor, with the payload and a one-click resolve — or don't build it.
Extraction that used to need a human eye — a scanned remittance advice, a PDF where the totals live in a footer, an email with the ship-to address buried in a signature block — now goes straight through often enough to change the math. On one messy-input queue the exception rate dropped from a third to 7%, moving work that had to be attended into unattended. That's the direction everyone talks about. The other direction: models add a failure mode neither architecture was built for. An OCR error looks like garbage. A model error looks like an answer — well-formed JSON, no crash, wrong number.
We route on validation and blast radius, never on the model's self-assessment; ask a model whether it's sure and it says yes. Checking that line items sum to the stated total within rounding, that the vendor exists in the master record, that the invoice date falls inside 90 days, that a second pass with a different prompt returns the same figure to the penny — those earn you something. Anything that fails validation, clears the money threshold, or names a vendor seen fewer than three times goes to a person. That's attended automation, structurally, triggered by the system instead of by someone clicking a button on their desktop.
Default to unattended with an explicit approval hop. Concretely: a Slack message with approve and reject actions that writes back into the running workflow — in Temporal, a signal against a workflow parked on a timer with a 24-hour escalation — so the human is a node in the graph rather than someone watching a bot move a mouse. Reserve session-bound attended automation for systems where credential reality leaves no choice, and log it as debt with an expiry date. Portals do eventually ship APIs, and when one does you want the migration list without the archaeology.
Then measure straight-through rate, not hours saved. On a 2,400-invoice-a-month AP flow we opened at 71% and reached 93% in six weeks. That wasn't a better model. It was three vendor-specific field templates and one date-parsing rule that had been silently dumping every DD/MM invoice into the exception queue. Hours saved is a number a skeptical CFO can argue with, because every assumption in it is yours. Straight-through rate tells you exactly what to fix on Monday, and it's the one metric that keeps an automation program alive past its first quarter.
A software studio that ships and maintains its own products — KeepChats, Gwora and Cairn — and builds the same way for clients. Founded and led by codewithumar.
Talk to the studio →Send the problem. You get one fixed number and a plan back within a business day.
We build software worth keeping — for clients, and for ourselves.
Founded & led by codewithumar