· 6 min read
How I decide a project is actually finished
A practical, non-hype framework for knowing when an AI automation project is done, drawn from running agents, local rendering, and MCP tooling in production.
The question I get wrong most often
“Is it done?” sounds like a yes-or-no question. In practice, for anything involving AI agents or automation pipelines, it is closer to a status check with a shelf life. Something I called done two weeks ago can quietly stop being done because a model update changed an output format, a scraper source changed its HTML, or a queue silently filled up with a bug nobody noticed. So the honest answer to “how do you decide a project is finished” is not a checklist you tick once. It is a set of conditions I check for, and a habit of re-checking them.
I run automation for content production, local rendering, and a handful of agent-driven tools every day. None of it is theoretical. So this is not a philosophy piece about “done” as a concept. It is the actual bar I use before I stop touching something and let it run unattended.
Done means it survives without me watching it
The first and most important test: can this run for a week without me opening a terminal to check on it?
This sounds simple but it rules out a lot of things people call finished. A script that works when you run it by hand, with your eyes on the output, is not the same as a script that works at 3am when nobody is looking. The difference is almost always in the failure paths, not the happy path. Does it retry a failed API call, or does it just die? Does it log something a person can actually read later, or does it log “ok” regardless of what happened? I have shipped automation that logged success even when the underlying task partially failed, because the logging checked “did the process exit” instead of “did the process do what I asked.” That is not a finished project. That is a project wearing a finished project’s clothes.
So before I call anything done, I ask what happens when the thing it depends on is slow, missing, or wrong. Not hypothetically. I have actually killed the network mid-run, fed it a malformed input, or let a queue sit empty on purpose, and watched what happens.
Done means the failure mode is boring
Every system fails eventually. An API rate-limits you, a model returns something unexpected, a file lock doesn’t release. The question is not whether failure happens, it’s whether the failure is boring or exciting.
A boring failure looks like: the job skips, something writes a clear note about why, and the next scheduled run tries again cleanly. An exciting failure looks like: partial output gets treated as complete output and moves downstream, or the failure cascades and takes something else with it, or nobody notices until a customer does.
I have hit that second kind more than once. A text-to-speech job that got cut off partway through would still produce a valid audio file, just a short one, and the pipeline had no way to tell “short because it finished” from “short because it broke.” The fix wasn’t clever. It was checking the output against what was expected and refusing to pass along anything that didn’t match, instead of trusting that a file existing meant the job worked. That is the kind of thing you only find by deliberately trying to break your own system, and it is why “it worked in my test” is not the same bar as “done.”
Done means someone other than me could restart it
If I get hit by a bus, or more realistically, if I am traveling and something breaks, can the thing be restarted by someone who did not build it? This is a harder bar than it sounds, because when you build something yourself you carry a huge amount of context in your head that never makes it into the code or the docs. You remember which config file actually matters, which one is a leftover, which service depends on which other service being up first.
I do not write elaborate documentation for everything, that would slow me down more than it helps. But for anything that touches money, customer data, or a live service, there needs to be at least a short note on how to tell if it’s broken and how to bring it back. If that note doesn’t exist, the project is not finished, it is just working for now.
Done does not mean perfect
This is the flip side, and it matters just as much. I have watched projects stay “almost done” for months because the bar kept moving. Every automation system has edge cases you could keep handling forever. At some point you have to decide which edge cases are worth handling and which ones are rare enough, or low-stakes enough, that a human catching it manually once a month is actually fine.
The test I use here is blast radius. If a rare failure means one video renders wrong and I notice it in a weekly review, that is an acceptable gap. If a rare failure means a customer gets billed twice, or a device gets wiped, or a script gets published with the wrong facts in it, that is not an edge case I get to skip. The amount of engineering a piece of automation deserves should match what happens when it’s wrong, not how interesting the problem is to solve.
This is also where I try to catch myself overbuilding. Adding a retry system, alerting, and a dashboard to something that runs once a week and is easy to re-run by hand is not thoroughness, it’s wasted effort that could have gone into something that actually needed it.
AI agents specifically change what “done” checks for
Wiring an agent into real tools, whether that’s through MCP or a direct API, adds a failure mode that traditional scripts don’t have: the agent can do the wrong thing confidently. A script either runs the code you wrote or it errors out. An agent can call the right tool with the wrong argument, or the wrong tool entirely, and produce output that looks plausible.
So for anything agent-driven, “done” includes a check on what the agent is actually allowed to do without a human confirming first. Read operations, low-stakes writes, things that are easy to reverse, those can run autonomously once I trust the pattern. Anything that sends a message on my behalf, spends money, deletes something, or touches a live customer-facing system gets a confirmation step, even after the automation has proven itself, because “proven itself” for an agent means it worked in the cases I happened to test, not that it will never take an unexpected path.
I want to be clear here since this is a topic full of overclaiming: none of this means the agent is doing the judgment for me. I am still the one deciding what counts as an acceptable failure, what needs a human in the loop, and when something is actually ready to run unattended. The agent executes faster than I could by hand. It does not decide when a project is finished.
The actual checklist
When I strip out the reasoning above, what’s left is short:
- It runs without me watching, for real, not just in a demo.
- I have deliberately tried to break it and the failure was boring, not silent or cascading.
- Someone who didn’t build it could tell if it’s broken and get it running again.
- The edge cases I’m not handling are ones where being wrong is cheap to notice and cheap to fix.
- Anything that spends money, deletes data, or acts on someone else’s behalf still has a human check, no matter how well it’s performed so far.
That’s it. Not a certification, not a benchmark score, just a set of conditions I actually verify before I stop paying attention to something. Most projects fail this because nobody checked what happens when things go sideways.
If you want to see how this plays out on actual builds, from local rendering pipelines to agents wired into production tools, that’s what I cover on the channel and the rest of the site.
Head back to the homepage for more on running AI automation for real, not in theory.
Get new guides and videos first — join the Telegram channel.