All writingApplications and automation · 5 min read

You cannot automate a process nobody has written down

The flowchart you were handed describes the good day. The two days a week the job actually takes are spent on everything the flowchart leaves out.

ClaudePostgresorchestrationAirflowApplications and automationProfessional servicesPublic sectorLogistics

The brief usually arrives in one sentence. Invoice coding takes two days a week, can you automate it. There is no document describing what happens during those two days. There is a person, a shared drive, and a spreadsheet with a tab called temp that has been load-bearing for four years.

Ask for the process documentation and you will often get something. A flowchart drawn for an audit, five boxes wide, every arrow pointing right. It is not wrong. It describes what happens when the invoice arrives with a purchase order number on it, from a supplier already in the system, for an amount inside the approval limit. It says nothing about the rest, and the rest is the reason the job takes two days rather than two hours.

That gap, between the process as drawn and the process as worked, is where most automation projects fail. Not in the code. The code is usually fine. It faithfully implements a description of the work that nobody has ever actually done.

The job as it is actually worked2 days a week
The job as the flowchart describes it2 hours
The flowchart is not wrong. It describes the two hours. Everything it leaves out is why the brief said two days.

The map you are given is a map of the good day

Processes in operations teams are rarely designed. They accrete. Someone handles an awkward case, the handling works, it becomes the way that case is handled. Nobody writes it down because writing it down was never the point. The point was to get the invoice out of the queue before the ledger closed.

So the knowledge sits in habit rather than in documentation, and it does not come out easily. Ask the person who does the job to describe the process and they will describe the good day too. This is not evasion. Exceptions are not stored in their head as rules, they are stored as recognition. They know a difficult one when they see it, and they can tell you what they did about the last one, but they cannot enumerate the category. The only reliable way to get at it is to watch the work happen and to read the record of what was actually done.

The same five box invoice process drawn twice. Above, the flowchart drawn for the audit, five boxes with every arrow pointing right. Below, the identical boxes with dashed exception branches dropping off the first three: no purchase order number, a supplier not yet in the system, and an amount over the approval limit, each one needing somebody with the authority to decide.
The same five boxes, drawn for the audit and worked on the day. Nothing below the line appears on the diagram above it.

A discovery pass that captures the real path

  1. 01
    Watch, do not interviewTwo sessions of sitting alongside the person while they work through a normal batch, with them narrating aloud. You are listening for the moments where they pause, open a second window, or say something like this one is a bit odd.
  2. 02
    Count from the system, not from the storyPull the last few months of records from wherever the work leaves a trace: the shared mailbox, the ticket queue, a Postgres table, the file names on the drive. Establish how many items completed on the straight path and how many did not. Memory will underestimate this every time.
  3. 03
    Name every exception and its deciderFor each deviation you find, write what triggered it, what was done, and who had the authority to do it. Some will turn out to be the same exception wearing different clothes. Some will turn out to be two people quietly disagreeing.
  4. 04
    Write it as decisions, not as boxesA diagram hides the interesting part. A numbered list of decisions, each with its inputs and its failure branch, exposes it.
  5. 05
    Read it back to the person who does the jobThey will correct you. The corrections are the deliverable. If they read it and say yes that is right, first time, you have written down the good day again.
A discovery pass on a single process. Usually a few days, not a few weeks.

What each step needs to say

  • Trigger What starts this step, precisely. An email landing is not a trigger. An email landing from one of these senders with an attachment matching this pattern is a trigger.
  • Inputs Where the data comes from and what state it is in on arrival, including the state it is in when the upstream party is careless.
  • Decision What judgement is being applied. Either express it as a rule you could code, or admit plainly that it is judgement and cannot be expressed that way yet.
  • Exception What makes this step branch or fail, and roughly how often.
  • Owner Who fixes it when it breaks, and whether that person is reachable at six on a Friday.

The fourth is the one that gets skipped, and it is the one that decides whether the thing you build survives its first month in production.

The exception rate decides the design

When the rate is low, the design is straightforward and the discipline is in the routing. Automate the main path, and send everything else to a human with the full context attached: the item, what the system tried, which rule it failed, and what it would need in order to proceed. The review queue is a first-class part of the system, not an error log nobody opens. Build it so that a resolved exception can be turned into a new rule, and revisit that queue on a schedule, because the exception mix drifts as the business changes.

A two-lane diagram: items entering on the left, most flowing through an automated main path to a completed state, a smaller branch peeling off into a human review queue that carries the item plus the rule it failed, and a dotted line running back from the queue into the rule set
The exception branch is part of the design, not an afterthought bolted on when the first batch fails.

When the rate is high, the process is the problem and code will not touch it. A high exception rate usually means one of three things: the inputs are inconsistent because nobody upstream has been asked to fix them, the rules genuinely conflict, or three people are doing the job three different ways and none of them knows that. None of those is an automation problem. They are agreement problems, and the fixes are dull. Ask the supplier to include the reference. Make the field mandatory on the form. Get the two systems to agree on one customer identifier. Do that first, watch the exception rate fall, and then automate what is left.

Automating a process nobody has agreed on does not produce agreement. It produces the same disagreement, faster, and with nobody left to ask.

The pattern, stated plainly

Where our own answer is the wrong one

Some processes should not be automated, and saying so is part of the job. A task that runs ten times a month with a real decision in the middle of each one will not repay the engineering, the monitoring, or the eventual maintenance. The honest recommendation is a better checklist and a shared inbox with clear ownership. We have finished a Week 1 audit and advised exactly that, and the one-pager was still worth the fee, because it named the process for the first time.

There is also a newer temptation worth naming. A language model can absorb an undocumented process by pattern matching against past examples, and it will appear to work. What you have then done is move unwritten judgement from a person who can explain themselves to a system that cannot. Models earn their place on the genuinely judgement-shaped steps, reading a messy document, classifying a free-text description, drafting the exception summary a reviewer will approve. Use Claude there deliberately, with an eval set built from the exceptions you catalogued during discovery, so you can tell when its behaviour drifts. That is a use of the write-up, not a substitute for it.

What the build looks like once the process is honest

With a written process, the engineering gets boring in the right way. Orchestration, Airflow or an equivalent, makes each step visible and each failure attributable to a named point rather than to the system in general. State lives in Postgres, so every item has a status you can query and a history you can read, and an exception is a row with a reason rather than a message in somebody's inbox. Retries are configured per step, because the ones that are safe to retry and the ones that are not are already distinguished in the document. The written process becomes the test plan: each exception you catalogued is a case you can assert against before the thing goes anywhere near production.

The document also outlives the automation. In eighteen months a supplier will change their file format, or a rule will change in the finance policy, and the person who has to fix it will not be whoever built it. What they need is not the code comments. They need the numbered list of decisions, with the exceptions named, that somebody sat down and wrote while watching the work being done.

Start by writing the process down

Our Week 1 audit is a fixed-fee discovery pass on one process: two calls, time spent with the people who actually do the work, and a written one-pager covering the real path, the exceptions and their rate, and a plain recommendation on whether to build at all. You keep the one-pager either way, including when the answer is that automation is not the right move yet.